You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

303 rivejä
8.3 KiB

  1. //
  2. // BtPhysTest
  3. //
  4. // Copyright: (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com>
  5. // (c) 2012 Sam Hocevar <sam@hocevar.net>
  6. //
  7. #if defined HAVE_CONFIG_H
  8. # include "config.h"
  9. #endif
  10. #if defined _WIN32
  11. # include <direct.h>
  12. #endif
  13. #if defined _XBOX
  14. # define _USE_MATH_DEFINES /* for M_PI */
  15. # include <xtl.h>
  16. # undef near /* Fuck Microsoft */
  17. # undef far /* Fuck Microsoft again */
  18. #elif defined _WIN32
  19. # define _USE_MATH_DEFINES /* for M_PI */
  20. # define WIN32_LEAN_AND_MEAN
  21. # include <windows.h>
  22. # undef near /* Fuck Microsoft */
  23. # undef far /* Fuck Microsoft again */
  24. #else
  25. # include <cmath>
  26. #endif
  27. #if USE_SDL && defined __APPLE__
  28. # include <SDL_main.h>
  29. #endif
  30. #include <bullet/btBulletDynamicsCommon.h>
  31. #include <bullet/btBulletCollisionCommon.h>
  32. #include "core.h"
  33. #include "loldebug.h"
  34. using namespace lol;
  35. #include "BtPhysTest.h"
  36. #define CUBE_HALF_EXTENTS .5f
  37. #define EXTRA_HEIGHT 1.f
  38. int gNumObjects = 8;
  39. BtPhysTest::BtPhysTest(bool editor)
  40. {
  41. /* Create a camera that matches the settings of XNA BtPhysTest */
  42. m_camera = new Camera(vec3(0.f, 600.f, 0.f),
  43. vec3(0.f, 0.f, 0.f),
  44. vec3(0, 0, -1));
  45. m_camera->SetRotation(quat::fromeuler_yxz(0.f, -30.f, 0.f));
  46. //m_camera->SetPerspective(120.f, 1280.f, 960.f, -1000.f, 1000.f);
  47. m_camera->SetOrtho(1280.f / 6, 960.f / 6, -1000.f, 1000.f);
  48. Ticker::Ref(m_camera);
  49. m_ready = false;
  50. //init Physics
  51. {
  52. m_bt_ccd_mode = USE_CCD;
  53. //collision configuration contains default setup for memory, collision setup
  54. m_bt_collision_config = new btDefaultCollisionConfiguration();
  55. //use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
  56. m_bt_dispatcher = new btCollisionDispatcher(m_bt_collision_config);
  57. m_bt_dispatcher->registerCollisionCreateFunc(BOX_SHAPE_PROXYTYPE,BOX_SHAPE_PROXYTYPE,m_bt_collision_config->getCollisionAlgorithmCreateFunc(CONVEX_SHAPE_PROXYTYPE,CONVEX_SHAPE_PROXYTYPE));
  58. m_bt_broadphase = new btDbvtBroadphase();
  59. ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
  60. m_bt_solver = new btSequentialImpulseConstraintSolver;
  61. m_bt_world = new btDiscreteDynamicsWorld(m_bt_dispatcher, m_bt_broadphase, m_bt_solver, m_bt_collision_config);
  62. //m_bt_world->setDebugDrawer(&sDebugDrawer);
  63. m_bt_world->getSolverInfo().m_splitImpulse = true;
  64. m_bt_world->getSolverInfo().m_numIterations = 20;
  65. m_bt_world->getDispatchInfo().m_useContinuous = (m_bt_ccd_mode == USE_CCD);
  66. m_bt_world->setGravity(btVector3(0,-10,0));
  67. ///create a few basic rigid bodies
  68. btBoxShape* box = new btBoxShape(btVector3(btScalar(110.),btScalar(1.),btScalar(110.)));
  69. btCollisionShape* groundShape = box;
  70. m_bt_collision_shapes << groundShape;
  71. m_ground_mesh.Compile("[sc#ddd afcb110 1 110 -1]");
  72. m_rigid_mesh.Compile("[sc#ada afcb1 1 1 -.1]");
  73. //m_bt_collision_shapes << new btCylinderShape(btVector3(.5f,.5f,.5f));
  74. btTransform groundTransform;
  75. groundTransform.setIdentity();
  76. //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
  77. {
  78. btScalar mass(0.);
  79. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  80. bool isDynamic = (mass != 0.f);
  81. btVector3 localInertia(0,0,0);
  82. if (isDynamic)
  83. groundShape->calculateLocalInertia(mass,localInertia);
  84. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  85. btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
  86. btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
  87. btRigidBody* body = new btRigidBody(rbInfo);
  88. //add the body to the dynamics world
  89. m_bt_world->addRigidBody(body);
  90. }
  91. //Adding Shapes
  92. {
  93. //create a few dynamic rigidbodies
  94. // Re-using the same collision is better for memory usage and performance
  95. btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
  96. m_bt_collision_shapes << colShape;
  97. m_bt_dynamic_shapes << colShape;
  98. /// Create Dynamic Objects
  99. btTransform startTransform;
  100. startTransform.setIdentity();
  101. btScalar mass(1.f);
  102. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  103. bool isDynamic = (mass != 0.f);
  104. btVector3 localInertia(0,0,0);
  105. if (isDynamic)
  106. colShape->calculateLocalInertia(mass,localInertia);
  107. int i;
  108. for (i=0;i<gNumObjects;i++)
  109. {
  110. btCollisionShape* shape = colShape;
  111. btTransform trans;
  112. trans.setIdentity();
  113. //stack them
  114. int colsize = 10;
  115. int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS);
  116. int row2 = row;
  117. int col = (i)%(colsize)-colsize/2;
  118. if (col>3)
  119. {
  120. col=11;
  121. row2 |=1;
  122. }
  123. btVector3 pos(col*2*CUBE_HALF_EXTENTS + (row2%2)*CUBE_HALF_EXTENTS,
  124. row*2*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,0);
  125. trans.setOrigin(pos);
  126. float mass = 1.f;
  127. btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
  128. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  129. bool isDynamic = (mass != 0.f);
  130. btVector3 localInertia(0,0,0);
  131. if (isDynamic)
  132. shape->calculateLocalInertia(mass,localInertia);
  133. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  134. btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
  135. btRigidBody::btRigidBodyConstructionInfo cInfo(mass,myMotionState,shape,localInertia);
  136. btRigidBody* body = new btRigidBody(cInfo);
  137. body->setContactProcessingThreshold(BT_LARGE_FLOAT);
  138. m_bt_world->addRigidBody(body);
  139. ///when using m_ccdMode
  140. if (m_bt_ccd_mode == USE_CCD)
  141. {
  142. body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
  143. body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS);
  144. }
  145. }
  146. }
  147. }
  148. }
  149. void BtPhysTest::TickGame(float seconds)
  150. {
  151. WorldEntity::TickGame(seconds);
  152. if (Input::GetButtonState(27 /*SDLK_ESCAPE*/))
  153. Ticker::Shutdown();
  154. ///step the simulation
  155. if (m_bt_world)
  156. {
  157. m_bt_world->stepSimulation(seconds);
  158. //optional but useful: debug drawing
  159. //m_bt_world->debugDrawWorld();
  160. }
  161. }
  162. void BtPhysTest::TickDraw(float seconds)
  163. {
  164. WorldEntity::TickDraw(seconds);
  165. if (!m_ready)
  166. {
  167. m_ground_mesh.MeshConvert();
  168. m_rigid_mesh.MeshConvert();
  169. /* FIXME: this object never cleans up */
  170. m_ready = true;
  171. }
  172. Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f));
  173. m_ground_mesh.Render(mat4(1.0f));
  174. for(int i=0;i<gNumObjects;i++)
  175. {
  176. mat4 m(1.0f);
  177. btMatrix3x3 rot; rot.setIdentity();
  178. btCollisionObject* colObj = m_bt_world->getCollisionObjectArray()[i];
  179. btRigidBody* body = btRigidBody::upcast(colObj);
  180. if(body && body->getMotionState())
  181. {
  182. btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState();
  183. myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(&m[0][0]);
  184. rot = myMotionState->m_graphicsWorldTrans.getBasis();
  185. }
  186. else
  187. {
  188. colObj->getWorldTransform().getOpenGLMatrix(&m[0][0]);
  189. rot = colObj->getWorldTransform().getBasis();
  190. }
  191. m_rigid_mesh.Render(m);
  192. }
  193. }
  194. BtPhysTest::~BtPhysTest()
  195. {
  196. Ticker::Unref(m_camera);
  197. //Exit Physics
  198. {
  199. //cleanup in the reverse order of creation/initialization
  200. //remove the rigidbodies from the dynamics world and delete them
  201. for (int i = m_bt_world->getNumCollisionObjects() - 1; i >= 0 ;i--)
  202. {
  203. btCollisionObject* obj = m_bt_world->getCollisionObjectArray()[i];
  204. btRigidBody* body = btRigidBody::upcast(obj);
  205. if (body && body->getMotionState())
  206. delete body->getMotionState();
  207. m_bt_world->removeCollisionObject(obj);
  208. delete obj;
  209. }
  210. //delete collision shapes
  211. for (int j = 0; j < m_bt_collision_shapes.Count(); j++)
  212. {
  213. btCollisionShape* shape = m_bt_collision_shapes[j];
  214. delete shape;
  215. }
  216. m_bt_collision_shapes.Empty();
  217. delete m_bt_world;
  218. delete m_bt_solver;
  219. delete m_bt_broadphase;
  220. delete m_bt_dispatcher;
  221. delete m_bt_collision_config;
  222. }
  223. }
  224. int main(int argc, char **argv)
  225. {
  226. Application app("BtPhysTest", ivec2(800, 600), 60.0f);
  227. #if defined _MSC_VER && !defined _XBOX
  228. _chdir("..");
  229. #elif defined _WIN32 && !defined _XBOX
  230. _chdir("../..");
  231. #endif
  232. new BtPhysTest(argc > 1);
  233. app.ShowPointer(false);
  234. app.Run();
  235. return EXIT_SUCCESS;
  236. }