FractureDemo.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. Bullet Continuous Collision Detection and Physics Library
  3. Copyright (c) 2003-2011 Erwin Coumans http://continuousphysics.com/Bullet/
  4. This software is provided 'as-is', without any express or implied warranty.
  5. In no event will the authors be held liable for any damages arising from the use of this software.
  6. Permission is granted to anyone to use this software for any purpose,
  7. including commercial applications, and to alter it and redistribute it freely,
  8. subject to the following restrictions:
  9. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  10. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  11. 3. This notice may not be removed or altered from any source distribution.
  12. */
  13. ///FractureDemo shows how to break objects.
  14. ///It assumes a btCompoundShaps (where the childshapes are the pre-fractured pieces)
  15. ///The btFractureBody is a class derived from btRigidBody, dealing with the collision impacts.
  16. ///Press the F key to toggle between fracture and glue mode
  17. ///This is preliminary work
  18. #define CUBE_HALF_EXTENTS 1.f
  19. #define EXTRA_HEIGHT 1.f
  20. ///scaling of the objects (0.1 = 20 centimeter boxes )
  21. #define SCALING 1.
  22. #define START_POS_X -5
  23. #define START_POS_Y -5
  24. #define START_POS_Z -3
  25. #include "FractureDemo.h"
  26. ///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
  27. #include "btBulletDynamicsCommon.h"
  28. #include <stdio.h> //printf debugging
  29. int sFrameNumber = 0;
  30. #include "btFractureBody.h"
  31. #include "btFractureDynamicsWorld.h"
  32. #include "LinearMath/btAlignedObjectArray.h"
  33. #include "../CommonInterfaces/CommonRigidBodyBase.h"
  34. ///FractureDemo shows basic breaking and glueing of objects
  35. class FractureDemo : public CommonRigidBodyBase
  36. {
  37. public:
  38. FractureDemo(struct GUIHelperInterface* helper)
  39. :CommonRigidBodyBase(helper)
  40. {
  41. }
  42. virtual ~FractureDemo()
  43. {
  44. }
  45. void initPhysics();
  46. void exitPhysics();
  47. virtual void stepSimulation(float deltaTime)
  48. {
  49. CommonRigidBodyBase::stepSimulation(deltaTime);
  50. {
  51. BT_PROFILE("recreate graphics");
  52. //@todo: make this graphics re-creation better
  53. //right now: brute force remove all graphics objects, and re-create them every frame
  54. m_guiHelper->getRenderInterface()->removeAllInstances();
  55. for (int i=0;i<m_dynamicsWorld->getNumCollisionObjects();i++)
  56. {
  57. btCollisionObject* colObj = m_dynamicsWorld->getCollisionObjectArray()[i];
  58. colObj->getCollisionShape()->setUserIndex(-1);
  59. colObj->setUserIndex(-1);
  60. }
  61. m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
  62. }
  63. }
  64. virtual bool keyboardCallback(int key, int state);
  65. void resetCamera()
  66. {
  67. float dist = 41;
  68. float pitch = 52;
  69. float yaw = 35;
  70. float targetPos[3]={0,0.46,0};
  71. m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
  72. }
  73. };
  74. void FractureDemo::initPhysics()
  75. {
  76. m_guiHelper->setUpAxis(1);
  77. ///collision configuration contains default setup for memory, collision setup
  78. m_collisionConfiguration = new btDefaultCollisionConfiguration();
  79. //m_collisionConfiguration->setConvexConvexMultipointIterations();
  80. ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
  81. m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
  82. m_broadphase = new btDbvtBroadphase();
  83. ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
  84. btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
  85. m_solver = sol;
  86. //m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
  87. btFractureDynamicsWorld* fractureWorld = new btFractureDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
  88. m_dynamicsWorld = fractureWorld;
  89. m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
  90. //m_splitImpulse removes the penetration resolution from the applied impulse, otherwise objects might fracture due to deep penetrations.
  91. m_dynamicsWorld->getSolverInfo().m_splitImpulse = true;
  92. {
  93. ///create a few basic rigid bodies
  94. btCollisionShape* groundShape = new btBoxShape(btVector3(50,1,50));
  95. /// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),0);
  96. m_collisionShapes.push_back(groundShape);
  97. btTransform groundTransform;
  98. groundTransform.setIdentity();
  99. groundTransform.setOrigin(btVector3(0,0,0));
  100. createRigidBody(0.f,groundTransform,groundShape);
  101. }
  102. {
  103. ///create a few basic rigid bodies
  104. btCollisionShape* shape = new btBoxShape(btVector3(1,1,1));
  105. m_collisionShapes.push_back(shape);
  106. btTransform tr;
  107. tr.setIdentity();
  108. tr.setOrigin(btVector3(5,2,0));
  109. createRigidBody(0.f,tr,shape);
  110. }
  111. {
  112. //create a few dynamic rigidbodies
  113. // Re-using the same collision is better for memory usage and performance
  114. btCollisionShape* colShape = new btBoxShape(btVector3(SCALING*1,SCALING*1,SCALING*1));
  115. //btCollisionShape* colShape = new btCapsuleShape(SCALING*0.4,SCALING*1);
  116. //btCollisionShape* colShape = new btSphereShape(btScalar(1.));
  117. m_collisionShapes.push_back(colShape);
  118. /// Create Dynamic Objects
  119. btTransform startTransform;
  120. startTransform.setIdentity();
  121. btScalar mass(1.f);
  122. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  123. bool isDynamic = (mass != 0.f);
  124. btVector3 localInertia(0,0,0);
  125. if (isDynamic)
  126. colShape->calculateLocalInertia(mass,localInertia);
  127. int gNumObjects = 10;
  128. for (int i=0;i<gNumObjects;i++)
  129. {
  130. btTransform trans;
  131. trans.setIdentity();
  132. btVector3 pos(i*2*CUBE_HALF_EXTENTS ,20,0);
  133. trans.setOrigin(pos);
  134. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  135. btDefaultMotionState* myMotionState = new btDefaultMotionState(trans);
  136. btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
  137. btFractureBody* body = new btFractureBody(rbInfo, m_dynamicsWorld);
  138. body->setLinearVelocity(btVector3(0,-10,0));
  139. m_dynamicsWorld->addRigidBody(body);
  140. }
  141. }
  142. fractureWorld->stepSimulation(1./60.,0);
  143. fractureWorld->glueCallback();
  144. m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
  145. }
  146. #if 0
  147. void FractureDemo::showMessage()
  148. {
  149. if((getDebugMode() & btIDebugDraw::DBG_DrawText))
  150. {
  151. setOrthographicProjection();
  152. glDisable(GL_LIGHTING);
  153. glColor3f(0, 0, 0);
  154. char buf[124];
  155. int lineWidth=380;
  156. int xStart = m_glutScreenWidth - lineWidth;
  157. int yStart = 20;
  158. btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;
  159. if (world->getFractureMode())
  160. {
  161. sprintf(buf,"Fracture mode");
  162. } else
  163. {
  164. sprintf(buf,"Glue mode");
  165. }
  166. GLDebugDrawString(xStart,yStart,buf);
  167. sprintf(buf,"f to toggle fracture/glue mode");
  168. yStart+=20;
  169. GLDebugDrawString(xStart,yStart,buf);
  170. sprintf(buf,"space to restart, mouse to pick/shoot");
  171. yStart+=20;
  172. GLDebugDrawString(xStart,yStart,buf);
  173. resetPerspectiveProjection();
  174. glEnable(GL_LIGHTING);
  175. }
  176. }
  177. #endif
  178. #if 0
  179. void FractureDemo::displayCallback(void) {
  180. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  181. renderme();
  182. showMessage();
  183. //optional but useful: debug drawing to detect problems
  184. if (m_dynamicsWorld)
  185. m_dynamicsWorld->debugDrawWorld();
  186. glFlush();
  187. swapBuffers();
  188. }
  189. #endif
  190. bool FractureDemo::keyboardCallback(int key, int state)
  191. {
  192. if (key=='f' && (state==0))
  193. {
  194. btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;
  195. world->setFractureMode(!world->getFractureMode());
  196. if (world->getFractureMode())
  197. {
  198. b3Printf("Fracturing mode");
  199. } else
  200. {
  201. b3Printf("Gluing mode");
  202. }
  203. return true;
  204. }
  205. return false;
  206. }
  207. #if 0
  208. void FractureDemo::keyboardUpCallback(unsigned char key, int x, int y)
  209. {
  210. if (key=='f')
  211. {
  212. btFractureDynamicsWorld* world = (btFractureDynamicsWorld*)m_dynamicsWorld;
  213. world->setFractureMode(!world->getFractureMode());
  214. }
  215. PlatformDemoApplication::keyboardUpCallback(key,x,y);
  216. }
  217. #endif
  218. #if 0
  219. void FractureDemo::shootBox(const btVector3& destination)
  220. {
  221. if (m_dynamicsWorld)
  222. {
  223. btScalar mass = 1.f;
  224. btTransform startTransform;
  225. startTransform.setIdentity();
  226. btVector3 camPos = getCameraPosition();
  227. startTransform.setOrigin(camPos);
  228. setShootBoxShape ();
  229. btAssert((!m_shootBoxShape || m_shootBoxShape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
  230. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  231. bool isDynamic = (mass != 0.f);
  232. btVector3 localInertia(0,0,0);
  233. if (isDynamic)
  234. m_shootBoxShape->calculateLocalInertia(mass,localInertia);
  235. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  236. btFractureBody* body = new btFractureBody(mass,0,m_shootBoxShape,localInertia,&mass,1,m_dynamicsWorld);
  237. body->setWorldTransform(startTransform);
  238. m_dynamicsWorld->addRigidBody(body);
  239. body->setLinearFactor(btVector3(1,1,1));
  240. //body->setRestitution(1);
  241. btVector3 linVel(destination[0]-camPos[0],destination[1]-camPos[1],destination[2]-camPos[2]);
  242. linVel.normalize();
  243. linVel*=m_ShootBoxInitialSpeed;
  244. body->getWorldTransform().setOrigin(camPos);
  245. body->getWorldTransform().setRotation(btQuaternion(0,0,0,1));
  246. body->setLinearVelocity(linVel);
  247. body->setAngularVelocity(btVector3(0,0,0));
  248. body->setCcdMotionThreshold(1.);
  249. body->setCcdSweptSphereRadius(0.2f);
  250. }
  251. }
  252. #endif
  253. void FractureDemo::exitPhysics()
  254. {
  255. //cleanup in the reverse order of creation/initialization
  256. //remove the rigidbodies from the dynamics world and delete them
  257. int i;
  258. for (i=m_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
  259. {
  260. btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
  261. btRigidBody* body = btRigidBody::upcast(obj);
  262. if (body && body->getMotionState())
  263. {
  264. delete body->getMotionState();
  265. }
  266. m_dynamicsWorld->removeCollisionObject( obj );
  267. delete obj;
  268. }
  269. //delete collision shapes
  270. for (int j=0;j<m_collisionShapes.size();j++)
  271. {
  272. btCollisionShape* shape = m_collisionShapes[j];
  273. delete shape;
  274. }
  275. m_collisionShapes.clear();
  276. delete m_dynamicsWorld;
  277. m_dynamicsWorld=0;
  278. delete m_solver;
  279. m_solver=0;
  280. delete m_broadphase;
  281. m_broadphase=0;
  282. delete m_dispatcher;
  283. m_dispatcher=0;
  284. delete m_collisionConfiguration;
  285. m_collisionConfiguration=0;
  286. }
  287. class CommonExampleInterface* FractureDemoCreateFunc(struct CommonExampleOptions& options)
  288. {
  289. return new FractureDemo(options.m_guiHelper);
  290. }