cubes.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /** Demo showing a wrecking ball hitting a few boxes. */
  2. #include "helper.h"
  3. #define ROOM_SIZE (14 * TPE_F)
  4. #define CUBE_SIZE (3 * TPE_F / 2)
  5. #define GRAVITY (TPE_F / 100)
  6. TPE_Vec3 environmentDistance(TPE_Vec3 p, TPE_Unit maxD)
  7. {
  8. return TPE_envAABoxInside(p,TPE_vec3(0,ROOM_SIZE / 4,0),
  9. TPE_vec3(ROOM_SIZE,ROOM_SIZE / 2,ROOM_SIZE));
  10. }
  11. TPE_Vec3 cubeOrientations[6];
  12. TPE_Vec3 cubePositions[6];
  13. TPE_Joint ballJoints[4]; // for the wrecking ball body
  14. TPE_Connection ballConnections[3];
  15. /** Updates the orientation and position of the ith cube's 3D model accordint to
  16. the physics model. This will only be done for active bodies to help
  17. performance a bit. */
  18. void updateOrientPos(int i)
  19. {
  20. cubeOrientations[i] = TPE_bodyGetRotation(&tpe_world.bodies[i],0,2,1);
  21. cubePositions[i] = TPE_bodyGetCenterOfMass(&tpe_world.bodies[i]);
  22. }
  23. int main(void)
  24. {
  25. helper_init();
  26. tpe_world.environmentFunction = environmentDistance;
  27. s3l_scene.camera.transform.translation.z -= ROOM_SIZE / 2;
  28. s3l_scene.camera.transform.translation.y += ROOM_SIZE / 3;
  29. s3l_scene.camera.transform.translation.x -= ROOM_SIZE / 4;
  30. s3l_scene.camera.transform.rotation.y = -1 * TPE_F / 16;
  31. for (int i = 0; i < 6; ++i) // add 6 cubes
  32. {
  33. helper_addBox(CUBE_SIZE / 2,CUBE_SIZE / 2,CUBE_SIZE / 2,CUBE_SIZE / 4,TPE_F / 5);
  34. helper_lastBody.friction = TPE_F / 20; // decrease friction for fun
  35. }
  36. #define move(i,x,y) \
  37. TPE_bodyMoveBy(&tpe_world.bodies[i],TPE_vec3((CUBE_SIZE / 2 + 10) * x,10 + CUBE_SIZE / 2 + y * (CUBE_SIZE + 10),0));
  38. move(0,0,0)
  39. move(1,-2,0)
  40. move(2,2,0)
  41. move(3,-1,1)
  42. move(4,1,1)
  43. move(5,0,2)
  44. #undef move
  45. for (int i = 0; i < 6; ++i)
  46. {
  47. updateOrientPos(i);
  48. /* normally the cubes wouldn't stand on each other as they're really made of
  49. spheres, so we deactivate them to keep them in place until the wrecking
  50. ball hits them: */
  51. TPE_bodyDeactivate(&tpe_bodies[i]);
  52. }
  53. // now create the wrecking ball body:
  54. ballJoints[0] = TPE_joint(TPE_vec3(0,ROOM_SIZE / 2,0),0);
  55. ballJoints[1] = TPE_joint(TPE_vec3(0,ROOM_SIZE / 2 - TPE_F / 5,-1 * TPE_F),0);
  56. ballJoints[2] = TPE_joint(TPE_vec3(0,ROOM_SIZE / 2 - TPE_F / 2,-2 * TPE_F),0);
  57. ballJoints[3] = TPE_joint(TPE_vec3(0,ROOM_SIZE / 2 - TPE_F,-4 * TPE_F),TPE_F);
  58. ballJoints[3].velocity[1] = -1 * TPE_F / 2;
  59. ballJoints[3].velocity[2] = -1 * TPE_F / 2;
  60. ballConnections[0].joint1 = 0; ballConnections[0].joint2 = 1;
  61. ballConnections[1].joint1 = 1; ballConnections[1].joint2 = 2;
  62. ballConnections[2].joint1 = 2; ballConnections[2].joint2 = 3;
  63. TPE_Body *ballBody = &tpe_world.bodies[6];
  64. TPE_bodyInit(ballBody,ballJoints,4,ballConnections,3,2 * TPE_F);
  65. ballBody->flags |= TPE_BODY_FLAG_SIMPLE_CONN;
  66. ballBody->flags |= TPE_BODY_FLAG_ALWAYS_ACTIVE;
  67. ballBody->friction = 0;
  68. ballBody->elasticity = TPE_F;
  69. tpe_world.bodyCount++;
  70. while (helper_running)
  71. {
  72. helper_frameStart();
  73. helper_cameraFreeMovement();
  74. if (helper_frame % 16 == 0)
  75. {
  76. helper_printCPU();
  77. if (sdl_keyboard[SDL_SCANCODE_L]) // pressing L explodes the cubes :)
  78. for (int i = 0; i < 6; ++i)
  79. {
  80. TPE_bodyActivate(&tpe_world.bodies[i]);
  81. TPE_bodyAccelerate(&tpe_world.bodies[i],
  82. TPE_vec3Plus(TPE_vec3(0,TPE_F / 5,0),TPE_vec3Times(cubePositions[i],TPE_F / 4)));
  83. }
  84. }
  85. // pin the top point of the wrecking ball to the ceiling:
  86. TPE_jointPin(&ballBody->joints[0],TPE_vec3(0,ROOM_SIZE / 2 - TPE_F / 100,0));
  87. TPE_worldStep(&tpe_world);
  88. helper_set3DColor(170,170,170);
  89. helper_draw3DBoxInside(TPE_vec3(0,ROOM_SIZE / 4,0),TPE_vec3(ROOM_SIZE,ROOM_SIZE / 2,ROOM_SIZE),TPE_vec3(0,0,0));
  90. helper_set3DColor(200,10,10);
  91. for (int i = 0; i < 6; ++i)
  92. {
  93. TPE_bodyApplyGravity(&tpe_world.bodies[i],GRAVITY);
  94. if (TPE_bodyIsActive(&tpe_world.bodies[i]))
  95. updateOrientPos(i);
  96. helper_draw3DBox(cubePositions[i],TPE_vec3(CUBE_SIZE,CUBE_SIZE,CUBE_SIZE),
  97. cubeOrientations[i]);
  98. }
  99. ballBody->joints[3].velocity[1] -= GRAVITY; // apply gravity only to one joint
  100. helper_draw3DSphere(ballBody->joints[3].position,TPE_vec3(400,400,400),TPE_vec3(0,0,0));
  101. for (int i = 0; i < 3; ++i)
  102. helper_drawLine3D(
  103. ballBody->joints[ballBody->connections[i].joint1].position,
  104. ballBody->joints[ballBody->connections[i].joint2].position,
  105. 255,0,0);
  106. if (helper_debugDrawOn)
  107. helper_debugDraw(1);
  108. helper_frameEnd();
  109. }
  110. helper_end();
  111. return 0;
  112. }