btBody.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "T3D/physics/bullet/btBody.h"
  24. #include "T3D/physics/bullet/bt.h"
  25. #include "T3D/physics/bullet/btCasts.h"
  26. #include "T3D/physics/bullet/btWorld.h"
  27. #include "T3D/physics/bullet/btCollision.h"
  28. #include "math/mBox.h"
  29. #include "console/console.h"
  30. BtBody::BtBody() :
  31. mActor( NULL ),
  32. mWorld( NULL ),
  33. mMass( 0.0f ),
  34. mCompound( NULL ),
  35. mCenterOfMass( NULL ),
  36. mInvCenterOfMass( NULL ),
  37. mIsDynamic( false ),
  38. mIsEnabled( false )
  39. {
  40. }
  41. BtBody::~BtBody()
  42. {
  43. _releaseActor();
  44. }
  45. void BtBody::_releaseActor()
  46. {
  47. if ( mActor )
  48. {
  49. mWorld->getDynamicsWorld()->removeRigidBody( mActor );
  50. mActor->setUserPointer( NULL );
  51. SAFE_DELETE( mActor );
  52. }
  53. SAFE_DELETE( mCompound );
  54. SAFE_DELETE( mCenterOfMass );
  55. SAFE_DELETE( mInvCenterOfMass );
  56. mColShape = NULL;
  57. }
  58. bool BtBody::init( PhysicsCollision *shape,
  59. F32 mass,
  60. U32 bodyFlags,
  61. SceneObject *obj,
  62. PhysicsWorld *world )
  63. {
  64. AssertFatal( obj, "BtBody::init - Got a null scene object!" );
  65. AssertFatal( world, "BtBody::init - Got a null world!" );
  66. AssertFatal( dynamic_cast<BtWorld*>( world ), "BtBody::init - The world is the wrong type!" );
  67. AssertFatal( shape, "BtBody::init - Got a null collision shape!" );
  68. AssertFatal( dynamic_cast<BtCollision*>( shape ), "BtBody::init - The collision shape is the wrong type!" );
  69. AssertFatal( ((BtCollision*)shape)->getShape(), "BtBody::init - Got empty collision shape!" );
  70. // Cleanup any previous actor.
  71. _releaseActor();
  72. mWorld = (BtWorld*)world;
  73. mColShape = (BtCollision*)shape;
  74. btCollisionShape *btColShape = mColShape->getShape();
  75. MatrixF localXfm = mColShape->getLocalTransform();
  76. btVector3 localInertia( 0, 0, 0 );
  77. // If we have a mass then we're dynamic.
  78. mIsDynamic = mass > 0.0f;
  79. if ( mIsDynamic )
  80. {
  81. if ( btColShape->isCompound() )
  82. {
  83. btCompoundShape *btCompound = (btCompoundShape*)btColShape;
  84. btScalar *masses = new btScalar[ btCompound->getNumChildShapes() ];
  85. for ( U32 j=0; j < btCompound->getNumChildShapes(); j++ )
  86. masses[j] = mass / btCompound->getNumChildShapes();
  87. btVector3 principalInertia;
  88. btTransform principal;
  89. btCompound->calculatePrincipalAxisTransform( masses, principal, principalInertia );
  90. delete [] masses;
  91. // Create a new compound with the shifted children.
  92. btColShape = mCompound = new btCompoundShape();
  93. for ( U32 i=0; i < btCompound->getNumChildShapes(); i++ )
  94. {
  95. btTransform newChildTransform = principal.inverse() * btCompound->getChildTransform(i);
  96. mCompound->addChildShape( newChildTransform, btCompound->getChildShape(i) );
  97. }
  98. localXfm = btCast<MatrixF>( principal );
  99. }
  100. // Note... this looks like we're changing the shape, but
  101. // we're not. All this does is ask the shape to calculate the
  102. // local inertia vector from the mass... the shape doesn't change.
  103. btColShape->calculateLocalInertia( mass, localInertia );
  104. }
  105. // If we have a local transform then we need to
  106. // store it and the inverse to offset the center
  107. // of mass from the graphics origin.
  108. if ( !localXfm.isIdentity() )
  109. {
  110. mCenterOfMass = new MatrixF( localXfm );
  111. mInvCenterOfMass = new MatrixF( *mCenterOfMass );
  112. mInvCenterOfMass->inverse();
  113. }
  114. mMass = mass;
  115. mActor = new btRigidBody( mass, NULL, btColShape, localInertia );
  116. int btFlags = mActor->getCollisionFlags();
  117. if ( bodyFlags & BF_TRIGGER )
  118. btFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
  119. if ( bodyFlags & BF_KINEMATIC )
  120. {
  121. btFlags &= ~btCollisionObject::CF_STATIC_OBJECT;
  122. btFlags |= btCollisionObject::CF_KINEMATIC_OBJECT;
  123. }
  124. mActor->setCollisionFlags( btFlags );
  125. mWorld->getDynamicsWorld()->addRigidBody( mActor );
  126. mIsEnabled = true;
  127. mUserData.setObject( obj );
  128. mUserData.setBody( this );
  129. mActor->setUserPointer( &mUserData );
  130. return true;
  131. }
  132. void BtBody::setMaterial( F32 restitution,
  133. F32 friction,
  134. F32 staticFriction )
  135. {
  136. AssertFatal( mActor, "BtBody::setMaterial - The actor is null!" );
  137. mActor->setRestitution( restitution );
  138. // TODO: Weird.. Bullet doesn't have seperate dynamic
  139. // and static friction.
  140. //
  141. // Either add it and submit it as an official patch
  142. // or hack it via contact reporting or something
  143. // like that.
  144. mActor->setFriction( friction );
  145. // Wake it up... it may need to move.
  146. mActor->activate();
  147. }
  148. void BtBody::setSleepThreshold( F32 linear, F32 angular )
  149. {
  150. AssertFatal( mActor, "BtBody::setSleepThreshold - The actor is null!" );
  151. mActor->setSleepingThresholds( linear, angular );
  152. }
  153. void BtBody::setDamping( F32 linear, F32 angular )
  154. {
  155. AssertFatal( mActor, "BtBody::setDamping - The actor is null!" );
  156. mActor->setDamping( linear, angular );
  157. }
  158. void BtBody::getState( PhysicsState *outState )
  159. {
  160. AssertFatal( isDynamic(), "BtBody::getState - This call is only for dynamics!" );
  161. // TODO: Fix this to do what we intended... to return
  162. // false so that the caller can early out of the state
  163. // hasn't changed since the last tick.
  164. MatrixF trans;
  165. if ( mInvCenterOfMass )
  166. trans.mul( btCast<MatrixF>( mActor->getCenterOfMassTransform() ), *mInvCenterOfMass );
  167. else
  168. trans = btCast<MatrixF>( mActor->getCenterOfMassTransform() );
  169. outState->position = trans.getPosition();
  170. outState->orientation.set( trans );
  171. outState->linVelocity = btCast<Point3F>( mActor->getLinearVelocity() );
  172. outState->angVelocity = btCast<Point3F>( mActor->getAngularVelocity() );
  173. outState->sleeping = !mActor->isActive();
  174. // Bullet doesn't keep the momentum... recalc it.
  175. outState->momentum = ( 1.0f / mActor->getInvMass() ) * outState->linVelocity;
  176. }
  177. Point3F BtBody::getCMassPosition() const
  178. {
  179. AssertFatal( mActor, "BtBody::getCMassPosition - The actor is null!" );
  180. return btCast<Point3F>( mActor->getCenterOfMassTransform().getOrigin() );
  181. }
  182. void BtBody::setLinVelocity( const Point3F &vel )
  183. {
  184. AssertFatal( mActor, "BtBody::setLinVelocity - The actor is null!" );
  185. AssertFatal( isDynamic(), "BtBody::setLinVelocity - This call is only for dynamics!" );
  186. mActor->setLinearVelocity( btCast<btVector3>( vel ) );
  187. }
  188. void BtBody::setAngVelocity( const Point3F &vel )
  189. {
  190. AssertFatal( mActor, "BtBody::setAngVelocity - The actor is null!" );
  191. AssertFatal( isDynamic(), "BtBody::setAngVelocity - This call is only for dynamics!" );
  192. mActor->setAngularVelocity( btCast<btVector3>( vel ) );
  193. }
  194. Point3F BtBody::getLinVelocity() const
  195. {
  196. AssertFatal( mActor, "BtBody::getLinVelocity - The actor is null!" );
  197. AssertFatal( isDynamic(), "BtBody::getLinVelocity - This call is only for dynamics!" );
  198. return btCast<Point3F>( mActor->getLinearVelocity() );
  199. }
  200. Point3F BtBody::getAngVelocity() const
  201. {
  202. AssertFatal( mActor, "BtBody::getAngVelocity - The actor is null!" );
  203. AssertFatal( isDynamic(), "BtBody::getAngVelocity - This call is only for dynamics!" );
  204. return btCast<Point3F>( mActor->getAngularVelocity() );
  205. }
  206. void BtBody::setSleeping( bool sleeping )
  207. {
  208. AssertFatal( mActor, "BtBody::setSleeping - The actor is null!" );
  209. AssertFatal( isDynamic(), "BtBody::setSleeping - This call is only for dynamics!" );
  210. if ( sleeping )
  211. {
  212. //mActor->setCollisionFlags( mActor->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT );
  213. mActor->setActivationState( WANTS_DEACTIVATION );
  214. mActor->setDeactivationTime( 0.0f );
  215. }
  216. else
  217. {
  218. //mActor->setCollisionFlags( mActor->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT );
  219. mActor->activate();
  220. }
  221. }
  222. PhysicsWorld* BtBody::getWorld()
  223. {
  224. return mWorld;
  225. }
  226. PhysicsCollision* BtBody::getColShape()
  227. {
  228. return mColShape;
  229. }
  230. MatrixF& BtBody::getTransform( MatrixF *outMatrix )
  231. {
  232. AssertFatal( mActor, "BtBody::getTransform - The actor is null!" );
  233. if ( mInvCenterOfMass )
  234. outMatrix->mul( *mInvCenterOfMass, btCast<MatrixF>( mActor->getCenterOfMassTransform() ) );
  235. else
  236. *outMatrix = btCast<MatrixF>( mActor->getCenterOfMassTransform() );
  237. return *outMatrix;
  238. }
  239. void BtBody::setTransform( const MatrixF &transform )
  240. {
  241. AssertFatal( mActor, "BtBody::setTransform - The actor is null!" );
  242. if ( mCenterOfMass )
  243. {
  244. MatrixF xfm;
  245. xfm.mul( transform, *mCenterOfMass );
  246. mActor->setCenterOfMassTransform( btCast<btTransform>( xfm ) );
  247. }
  248. else
  249. mActor->setCenterOfMassTransform( btCast<btTransform>( transform ) );
  250. // If its dynamic we have more to do.
  251. if ( isDynamic() )
  252. {
  253. // Clear any velocity and forces... this is a warp.
  254. mActor->clearForces();
  255. mActor->setLinearVelocity( btVector3( 0, 0, 0 ) );
  256. mActor->setAngularVelocity( btVector3( 0, 0, 0 ) );
  257. mActor->activate();
  258. }
  259. }
  260. void BtBody::applyCorrection( const MatrixF &transform )
  261. {
  262. AssertFatal( mActor, "BtBody::applyCorrection - The actor is null!" );
  263. AssertFatal( isDynamic(), "BtBody::applyCorrection - This call is only for dynamics!" );
  264. if ( mCenterOfMass )
  265. {
  266. MatrixF xfm;
  267. xfm.mul( transform, *mCenterOfMass );
  268. mActor->setCenterOfMassTransform( btCast<btTransform>( xfm ) );
  269. }
  270. else
  271. mActor->setCenterOfMassTransform( btCast<btTransform>( transform ) );
  272. }
  273. void BtBody::applyImpulse( const Point3F &origin, const Point3F &force )
  274. {
  275. AssertFatal( mActor, "BtBody::applyImpulse - The actor is null!" );
  276. AssertFatal( isDynamic(), "BtBody::applyImpulse - This call is only for dynamics!" );
  277. // Convert the world position to local
  278. MatrixF trans = btCast<MatrixF>( mActor->getCenterOfMassTransform() );
  279. trans.inverse();
  280. Point3F localOrigin( origin );
  281. trans.mulP( localOrigin );
  282. if ( mCenterOfMass )
  283. {
  284. Point3F relOrigin( localOrigin );
  285. mCenterOfMass->mulP( relOrigin );
  286. Point3F relForce( force );
  287. mCenterOfMass->mulV( relForce );
  288. mActor->applyImpulse( btCast<btVector3>( relForce ), btCast<btVector3>( relOrigin ) );
  289. }
  290. else
  291. mActor->applyImpulse( btCast<btVector3>( force ), btCast<btVector3>( localOrigin ) );
  292. if ( !mActor->isActive() )
  293. mActor->activate();
  294. }
  295. void BtBody::applyTorque(const Point3F &torque)
  296. {
  297. AssertFatal(mActor, "BtBody::applyTorque - The actor is null!");
  298. AssertFatal(isDynamic(), "BtBody::applyTorque - This call is only for dynamics!");
  299. mActor->applyTorque( btCast<btVector3>(torque) );
  300. if (!mActor->isActive())
  301. mActor->activate();
  302. }
  303. Box3F BtBody::getWorldBounds()
  304. {
  305. btVector3 min, max;
  306. mActor->getAabb( min, max );
  307. Box3F bounds( btCast<Point3F>( min ), btCast<Point3F>( max ) );
  308. return bounds;
  309. }
  310. void BtBody::setSimulationEnabled( bool enabled )
  311. {
  312. if ( mIsEnabled == enabled )
  313. return;
  314. if ( !enabled )
  315. mWorld->getDynamicsWorld()->removeRigidBody( mActor );
  316. else
  317. mWorld->getDynamicsWorld()->addRigidBody( mActor );
  318. mIsEnabled = enabled;
  319. }
  320. void BtBody::findContact(SceneObject **contactObject,
  321. VectorF *contactNormal,
  322. Vector<SceneObject*> *outOverlapObjects) const
  323. {
  324. }
  325. void BtBody::moveKinematicTo(const MatrixF &transform)
  326. {
  327. AssertFatal(mActor, "BtBody::moveKinematicTo - The actor is null!");
  328. U32 bodyflags = mActor->getCollisionFlags();
  329. const bool isKinematic = bodyflags & BF_KINEMATIC;
  330. if (!isKinematic)
  331. {
  332. Con::errorf("BtBody::moveKinematicTo is only for kinematic bodies.");
  333. return;
  334. }
  335. if (mCenterOfMass)
  336. {
  337. MatrixF xfm;
  338. xfm.mul(transform, *mCenterOfMass);
  339. mActor->setCenterOfMassTransform(btCast<btTransform>(xfm));
  340. }
  341. else
  342. mActor->setCenterOfMassTransform(btCast<btTransform>(transform));
  343. }