CommonRigidBodyBase.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. #ifndef COMMON_RIGID_BODY_BASE_H
  2. #define COMMON_RIGID_BODY_BASE_H
  3. #include "btBulletDynamicsCommon.h"
  4. #include "CommonExampleInterface.h"
  5. #include "CommonGUIHelperInterface.h"
  6. #include "CommonRenderInterface.h"
  7. #include "CommonCameraInterface.h"
  8. #include "CommonGraphicsAppInterface.h"
  9. #include "CommonWindowInterface.h"
  10. struct CommonRigidBodyBase : public CommonExampleInterface
  11. {
  12. //keep the collision shapes, for deletion/cleanup
  13. btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
  14. btBroadphaseInterface* m_broadphase;
  15. btCollisionDispatcher* m_dispatcher;
  16. btConstraintSolver* m_solver;
  17. btDefaultCollisionConfiguration* m_collisionConfiguration;
  18. btDiscreteDynamicsWorld* m_dynamicsWorld;
  19. //data for picking objects
  20. class btRigidBody* m_pickedBody;
  21. class btTypedConstraint* m_pickedConstraint;
  22. int m_savedState;
  23. btVector3 m_oldPickingPos;
  24. btVector3 m_hitPos;
  25. btScalar m_oldPickingDist;
  26. struct GUIHelperInterface* m_guiHelper;
  27. CommonRigidBodyBase(struct GUIHelperInterface* helper)
  28. :m_broadphase(0),
  29. m_dispatcher(0),
  30. m_solver(0),
  31. m_collisionConfiguration(0),
  32. m_dynamicsWorld(0),
  33. m_pickedBody(0),
  34. m_pickedConstraint(0),
  35. m_guiHelper(helper)
  36. {
  37. }
  38. virtual ~CommonRigidBodyBase()
  39. {
  40. }
  41. btDiscreteDynamicsWorld* getDynamicsWorld()
  42. {
  43. return m_dynamicsWorld;
  44. }
  45. virtual void createEmptyDynamicsWorld()
  46. {
  47. ///collision configuration contains default setup for memory, collision setup
  48. m_collisionConfiguration = new btDefaultCollisionConfiguration();
  49. //m_collisionConfiguration->setConvexConvexMultipointIterations();
  50. ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
  51. m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
  52. m_broadphase = new btDbvtBroadphase();
  53. ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
  54. btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver;
  55. m_solver = sol;
  56. m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
  57. m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
  58. }
  59. virtual void stepSimulation(float deltaTime)
  60. {
  61. if (m_dynamicsWorld)
  62. {
  63. m_dynamicsWorld->stepSimulation(deltaTime);
  64. }
  65. }
  66. virtual void physicsDebugDraw(int debugFlags)
  67. {
  68. if (m_dynamicsWorld && m_dynamicsWorld->getDebugDrawer())
  69. {
  70. m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugFlags);
  71. m_dynamicsWorld->debugDrawWorld();
  72. }
  73. }
  74. virtual void exitPhysics()
  75. {
  76. removePickingConstraint();
  77. //cleanup in the reverse order of creation/initialization
  78. //remove the rigidbodies from the dynamics world and delete them
  79. if (m_dynamicsWorld)
  80. {
  81. int i;
  82. for (i = m_dynamicsWorld->getNumConstraints() - 1; i >= 0; i--)
  83. {
  84. m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i));
  85. }
  86. for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
  87. {
  88. btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
  89. btRigidBody* body = btRigidBody::upcast(obj);
  90. if (body && body->getMotionState())
  91. {
  92. delete body->getMotionState();
  93. }
  94. m_dynamicsWorld->removeCollisionObject(obj);
  95. delete obj;
  96. }
  97. }
  98. //delete collision shapes
  99. for (int j = 0; j<m_collisionShapes.size(); j++)
  100. {
  101. btCollisionShape* shape = m_collisionShapes[j];
  102. delete shape;
  103. }
  104. m_collisionShapes.clear();
  105. delete m_dynamicsWorld;
  106. m_dynamicsWorld=0;
  107. delete m_solver;
  108. m_solver=0;
  109. delete m_broadphase;
  110. m_broadphase=0;
  111. delete m_dispatcher;
  112. m_dispatcher=0;
  113. delete m_collisionConfiguration;
  114. m_collisionConfiguration=0;
  115. }
  116. virtual void debugDraw(int debugDrawFlags)
  117. {
  118. if (m_dynamicsWorld)
  119. {
  120. if (m_dynamicsWorld->getDebugDrawer())
  121. {
  122. m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugDrawFlags);
  123. }
  124. m_dynamicsWorld->debugDrawWorld();
  125. }
  126. }
  127. virtual bool keyboardCallback(int key, int state)
  128. {
  129. if ((key==B3G_F3) && state && m_dynamicsWorld)
  130. {
  131. btDefaultSerializer* serializer = new btDefaultSerializer();
  132. m_dynamicsWorld->serialize(serializer);
  133. FILE* file = fopen("testFile.bullet","wb");
  134. fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file);
  135. fclose(file);
  136. //b3Printf("btDefaultSerializer wrote testFile.bullet");
  137. delete serializer;
  138. return true;
  139. }
  140. return false;//don't handle this key
  141. }
  142. btVector3 getRayTo(int x,int y)
  143. {
  144. CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
  145. if (!renderer)
  146. {
  147. btAssert(0);
  148. return btVector3(0,0,0);
  149. }
  150. float top = 1.f;
  151. float bottom = -1.f;
  152. float nearPlane = 1.f;
  153. float tanFov = (top-bottom)*0.5f / nearPlane;
  154. float fov = btScalar(2.0) * btAtan(tanFov);
  155. btVector3 camPos,camTarget;
  156. renderer->getActiveCamera()->getCameraPosition(camPos);
  157. renderer->getActiveCamera()->getCameraTargetPosition(camTarget);
  158. btVector3 rayFrom = camPos;
  159. btVector3 rayForward = (camTarget-camPos);
  160. rayForward.normalize();
  161. float farPlane = 10000.f;
  162. rayForward*= farPlane;
  163. btVector3 rightOffset;
  164. btVector3 cameraUp=btVector3(0,0,0);
  165. cameraUp[m_guiHelper->getAppInterface()->getUpAxis()]=1;
  166. btVector3 vertical = cameraUp;
  167. btVector3 hor;
  168. hor = rayForward.cross(vertical);
  169. hor.safeNormalize();
  170. vertical = hor.cross(rayForward);
  171. vertical.safeNormalize();
  172. float tanfov = tanf(0.5f*fov);
  173. hor *= 2.f * farPlane * tanfov;
  174. vertical *= 2.f * farPlane * tanfov;
  175. btScalar aspect;
  176. float width = float(renderer->getScreenWidth());
  177. float height = float (renderer->getScreenHeight());
  178. aspect = width / height;
  179. hor*=aspect;
  180. btVector3 rayToCenter = rayFrom + rayForward;
  181. btVector3 dHor = hor * 1.f/width;
  182. btVector3 dVert = vertical * 1.f/height;
  183. btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
  184. rayTo += btScalar(x) * dHor;
  185. rayTo -= btScalar(y) * dVert;
  186. return rayTo;
  187. }
  188. virtual bool mouseMoveCallback(float x,float y)
  189. {
  190. CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
  191. if (!renderer)
  192. {
  193. btAssert(0);
  194. return false;
  195. }
  196. btVector3 rayTo = getRayTo(int(x), int(y));
  197. btVector3 rayFrom;
  198. renderer->getActiveCamera()->getCameraPosition(rayFrom);
  199. movePickedBody(rayFrom,rayTo);
  200. return false;
  201. }
  202. virtual bool mouseButtonCallback(int button, int state, float x, float y)
  203. {
  204. CommonRenderInterface* renderer = m_guiHelper->getRenderInterface();
  205. if (!renderer)
  206. {
  207. btAssert(0);
  208. return false;
  209. }
  210. CommonWindowInterface* window = m_guiHelper->getAppInterface()->m_window;
  211. #if 0
  212. if (window->isModifierKeyPressed(B3G_ALT))
  213. {
  214. printf("ALT pressed\n");
  215. } else
  216. {
  217. printf("NO ALT pressed\n");
  218. }
  219. if (window->isModifierKeyPressed(B3G_SHIFT))
  220. {
  221. printf("SHIFT pressed\n");
  222. } else
  223. {
  224. printf("NO SHIFT pressed\n");
  225. }
  226. if (window->isModifierKeyPressed(B3G_CONTROL))
  227. {
  228. printf("CONTROL pressed\n");
  229. } else
  230. {
  231. printf("NO CONTROL pressed\n");
  232. }
  233. #endif
  234. if (state==1)
  235. {
  236. if(button==0 && (!window->isModifierKeyPressed(B3G_ALT) && !window->isModifierKeyPressed(B3G_CONTROL) ))
  237. {
  238. btVector3 camPos;
  239. renderer->getActiveCamera()->getCameraPosition(camPos);
  240. btVector3 rayFrom = camPos;
  241. btVector3 rayTo = getRayTo(int(x),int(y));
  242. pickBody(rayFrom, rayTo);
  243. }
  244. } else
  245. {
  246. if (button==0)
  247. {
  248. removePickingConstraint();
  249. //remove p2p
  250. }
  251. }
  252. //printf("button=%d, state=%d\n",button,state);
  253. return false;
  254. }
  255. virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
  256. {
  257. if (m_dynamicsWorld==0)
  258. return false;
  259. btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);
  260. m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
  261. if (rayCallback.hasHit())
  262. {
  263. btVector3 pickPos = rayCallback.m_hitPointWorld;
  264. btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject);
  265. if (body)
  266. {
  267. //other exclusions?
  268. if (!(body->isStaticObject() || body->isKinematicObject()))
  269. {
  270. m_pickedBody = body;
  271. m_savedState = m_pickedBody->getActivationState();
  272. m_pickedBody->setActivationState(DISABLE_DEACTIVATION);
  273. //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ());
  274. btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos;
  275. btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body, localPivot);
  276. m_dynamicsWorld->addConstraint(p2p, true);
  277. m_pickedConstraint = p2p;
  278. btScalar mousePickClamping = 30.f;
  279. p2p->m_setting.m_impulseClamp = mousePickClamping;
  280. //very weak constraint for picking
  281. p2p->m_setting.m_tau = 0.001f;
  282. }
  283. }
  284. // pickObject(pickPos, rayCallback.m_collisionObject);
  285. m_oldPickingPos = rayToWorld;
  286. m_hitPos = pickPos;
  287. m_oldPickingDist = (pickPos - rayFromWorld).length();
  288. // printf("hit !\n");
  289. //add p2p
  290. }
  291. return false;
  292. }
  293. virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld)
  294. {
  295. if (m_pickedBody && m_pickedConstraint)
  296. {
  297. btPoint2PointConstraint* pickCon = static_cast<btPoint2PointConstraint*>(m_pickedConstraint);
  298. if (pickCon)
  299. {
  300. //keep it at the same picking distance
  301. btVector3 newPivotB;
  302. btVector3 dir = rayToWorld - rayFromWorld;
  303. dir.normalize();
  304. dir *= m_oldPickingDist;
  305. newPivotB = rayFromWorld + dir;
  306. pickCon->setPivotB(newPivotB);
  307. return true;
  308. }
  309. }
  310. return false;
  311. }
  312. virtual void removePickingConstraint()
  313. {
  314. if (m_pickedConstraint)
  315. {
  316. m_pickedBody->forceActivationState(m_savedState);
  317. m_pickedBody->activate();
  318. m_dynamicsWorld->removeConstraint(m_pickedConstraint);
  319. delete m_pickedConstraint;
  320. m_pickedConstraint = 0;
  321. m_pickedBody = 0;
  322. }
  323. }
  324. btBoxShape* createBoxShape(const btVector3& halfExtents)
  325. {
  326. btBoxShape* box = new btBoxShape(halfExtents);
  327. return box;
  328. }
  329. btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1))
  330. {
  331. btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE));
  332. //rigidbody is dynamic if and only if mass is non zero, otherwise static
  333. bool isDynamic = (mass != 0.f);
  334. btVector3 localInertia(0, 0, 0);
  335. if (isDynamic)
  336. shape->calculateLocalInertia(mass, localInertia);
  337. //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
  338. #define USE_MOTIONSTATE 1
  339. #ifdef USE_MOTIONSTATE
  340. btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
  341. btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia);
  342. btRigidBody* body = new btRigidBody(cInfo);
  343. //body->setContactProcessingThreshold(m_defaultContactProcessingThreshold);
  344. #else
  345. btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia);
  346. body->setWorldTransform(startTransform);
  347. #endif//
  348. body->setUserIndex(-1);
  349. m_dynamicsWorld->addRigidBody(body);
  350. return body;
  351. }
  352. virtual void renderScene()
  353. {
  354. {
  355. m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld);
  356. }
  357. {
  358. m_guiHelper->render(m_dynamicsWorld);
  359. }
  360. }
  361. };
  362. #endif //COMMON_RIGID_BODY_SETUP_H