25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BtPhysTest.cpp 9.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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 = 64;
  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, 1, 0));
  45. m_camera->SetRotation(quat::fromeuler_xyz(0.f, 0.f, 0.f));
  46. m_camera->SetPerspective(90.f, 1280.f, 960.f, .1f, 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_bt_collision_shapes << new btCylinderShape(btVector3(.5f,.5f,.5f));
  73. btTransform groundTransform;
  74. groundTransform.setIdentity();
  75. //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
  76. {
  77. btScalar mass(0.);
  78. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  79. bool isDynamic = (mass != 0.f);
  80. btVector3 localInertia(0,0,0);
  81. if (isDynamic)
  82. groundShape->calculateLocalInertia(mass,localInertia);
  83. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  84. btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
  85. btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,groundShape,localInertia);
  86. btRigidBody* body = new btRigidBody(rbInfo);
  87. //add the body to the dynamics world
  88. m_bt_world->addRigidBody(body);
  89. }
  90. //Adding Shapes
  91. {
  92. //create a few dynamic rigidbodies
  93. // Re-using the same collision is better for memory usage and performance
  94. btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
  95. m_rigid_mesh[0].Compile("[sc#add afcb2 2 2 -.1]");
  96. m_rigid_mesh[1].Compile("[sc#dad afcb2 2 2 -.1]");
  97. m_rigid_mesh[2].Compile("[sc#dda afcb2 2 2 -.1]");
  98. m_rigid_mesh[3].Compile("[sc#daa afcb2 2 2 -.1]");
  99. m_rigid_mesh[4].Compile("[sc#ada afcb2 2 2 -.1]");
  100. m_rigid_mesh[5].Compile("[sc#aad afcb2 2 2 -.1]");
  101. m_bt_collision_shapes << colShape;
  102. m_bt_dynamic_shapes << colShape;
  103. /// Create Dynamic Objects
  104. btTransform startTransform;
  105. startTransform.setIdentity();
  106. btScalar mass(1.f);
  107. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  108. bool isDynamic = (mass != 0.f);
  109. btVector3 localInertia(0,0,0);
  110. if (isDynamic)
  111. colShape->calculateLocalInertia(mass,localInertia);
  112. int i;
  113. for (i=0;i<gNumObjects;i++)
  114. {
  115. btCollisionShape* shape = colShape;
  116. btTransform trans;
  117. trans.setIdentity();
  118. //stack them
  119. int colsize = 10;
  120. int row = (i*CUBE_HALF_EXTENTS*2)/(colsize*2*CUBE_HALF_EXTENTS);
  121. int row2 = row;
  122. int col = (i)%(colsize)-colsize/2;
  123. if (col>3)
  124. {
  125. col=11;
  126. row2 |=1;
  127. }
  128. btVector3 pos(((row+col+row2) % 4)*CUBE_HALF_EXTENTS,
  129. 20.0f + row*8*CUBE_HALF_EXTENTS+CUBE_HALF_EXTENTS+EXTRA_HEIGHT,
  130. col*8*CUBE_HALF_EXTENTS + 2 * (row2%2)*CUBE_HALF_EXTENTS);
  131. trans.setOrigin(pos);
  132. float mass = 1.f;
  133. btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
  134. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  135. bool isDynamic = (mass != 0.f);
  136. btVector3 localInertia(0,0,0);
  137. if (isDynamic)
  138. shape->calculateLocalInertia(mass,localInertia);
  139. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  140. btDefaultMotionState* myMotionState = new btDefaultMotionState(trans);
  141. btRigidBody::btRigidBodyConstructionInfo cInfo(mass,myMotionState,shape,localInertia);
  142. btRigidBody* body = new btRigidBody(cInfo);
  143. body->setContactProcessingThreshold(BT_LARGE_FLOAT);
  144. m_bt_world->addRigidBody(body);
  145. ///when using m_ccdMode
  146. if (m_bt_ccd_mode == USE_CCD)
  147. {
  148. body->setCcdMotionThreshold(CUBE_HALF_EXTENTS);
  149. body->setCcdSweptSphereRadius(0.9*CUBE_HALF_EXTENTS);
  150. }
  151. }
  152. }
  153. }
  154. }
  155. void BtPhysTest::TickGame(float seconds)
  156. {
  157. WorldEntity::TickGame(seconds);
  158. if (Input::GetButtonState(27 /*SDLK_ESCAPE*/))
  159. Ticker::Shutdown();
  160. ///step the simulation
  161. if (m_bt_world)
  162. {
  163. int steps = (int)(seconds / 0.005f);
  164. for (int i = 0; i < steps; i++)
  165. m_bt_world->stepSimulation(seconds / steps);
  166. //optional but useful: debug drawing
  167. //m_bt_world->debugDrawWorld();
  168. }
  169. }
  170. void BtPhysTest::TickDraw(float seconds)
  171. {
  172. WorldEntity::TickDraw(seconds);
  173. if (!m_ready)
  174. {
  175. m_ground_mesh.MeshConvert();
  176. m_rigid_mesh[0].MeshConvert();
  177. m_rigid_mesh[1].MeshConvert();
  178. m_rigid_mesh[2].MeshConvert();
  179. m_rigid_mesh[3].MeshConvert();
  180. m_rigid_mesh[4].MeshConvert();
  181. m_rigid_mesh[5].MeshConvert();
  182. /* FIXME: this object never cleans up */
  183. m_ready = true;
  184. }
  185. Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f));
  186. vec3 BarycenterLocation = vec3(.0f);
  187. float BarycenterFactor = 0.0f;
  188. for(int i=0;i<gNumObjects;i++)
  189. {
  190. mat4 m(1.0f);
  191. btMatrix3x3 rot; rot.setIdentity();
  192. btCollisionObject* colObj = m_bt_world->getCollisionObjectArray()[i];
  193. btRigidBody* body = btRigidBody::upcast(colObj);
  194. if(body && body->getMotionState())
  195. {
  196. btDefaultMotionState* myMotionState = (btDefaultMotionState*)body->getMotionState();
  197. myMotionState->m_graphicsWorldTrans.getOpenGLMatrix(&m[0][0]);
  198. rot = myMotionState->m_graphicsWorldTrans.getBasis();
  199. }
  200. else
  201. {
  202. colObj->getWorldTransform().getOpenGLMatrix(&m[0][0]);
  203. rot = colObj->getWorldTransform().getBasis();
  204. }
  205. if (i > 0)
  206. {
  207. BarycenterLocation += m.v3.xyz;
  208. BarycenterFactor += 1.0f;
  209. }
  210. if (i == 0)
  211. m_ground_mesh.Render(m);
  212. else
  213. m_rigid_mesh[i % 6].Render(m);
  214. }
  215. if (BarycenterFactor > .0f)
  216. {
  217. BarycenterLocation /= BarycenterFactor;
  218. m_camera->SetTarget(BarycenterLocation);
  219. m_camera->SetPosition(BarycenterLocation + vec3(-20.0f, 8.0f, .0f));
  220. }
  221. }
  222. BtPhysTest::~BtPhysTest()
  223. {
  224. Ticker::Unref(m_camera);
  225. //Exit Physics
  226. {
  227. //cleanup in the reverse order of creation/initialization
  228. //remove the rigidbodies from the dynamics world and delete them
  229. for (int i = m_bt_world->getNumCollisionObjects() - 1; i >= 0 ;i--)
  230. {
  231. btCollisionObject* obj = m_bt_world->getCollisionObjectArray()[i];
  232. btRigidBody* body = btRigidBody::upcast(obj);
  233. if (body && body->getMotionState())
  234. delete body->getMotionState();
  235. m_bt_world->removeCollisionObject(obj);
  236. delete obj;
  237. }
  238. //delete collision shapes
  239. for (int j = 0; j < m_bt_collision_shapes.Count(); j++)
  240. {
  241. btCollisionShape* shape = m_bt_collision_shapes[j];
  242. delete shape;
  243. }
  244. m_bt_collision_shapes.Empty();
  245. delete m_bt_world;
  246. delete m_bt_solver;
  247. delete m_bt_broadphase;
  248. delete m_bt_dispatcher;
  249. delete m_bt_collision_config;
  250. }
  251. }
  252. int main(int argc, char **argv)
  253. {
  254. Application app("BtPhysTest", ivec2(1280, 720), 60.0f);
  255. #if defined _MSC_VER && !defined _XBOX
  256. _chdir("..");
  257. #elif defined _WIN32 && !defined _XBOX
  258. _chdir("../..");
  259. #endif
  260. new BtPhysTest(argc > 1);
  261. app.ShowPointer(false);
  262. app.Run();
  263. return EXIT_SUCCESS;
  264. }