pxBody.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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/physX/pxBody.h"
  24. #include "T3D/physics/physX/px.h"
  25. #include "T3D/physics/physX/pxCasts.h"
  26. #include "T3D/physics/physX/pxWorld.h"
  27. #include "T3D/physics/physX/pxCollision.h"
  28. PxBody::PxBody() :
  29. mActor( NULL ),
  30. mMaterial( NULL ),
  31. mWorld( NULL ),
  32. mBodyFlags( 0 ),
  33. mIsEnabled( true )
  34. {
  35. }
  36. PxBody::~PxBody()
  37. {
  38. _releaseActor();
  39. }
  40. void PxBody::_releaseActor()
  41. {
  42. if ( !mActor )
  43. return;
  44. // This sucks, but it has to happen if we want
  45. // to avoid write lock errors from PhysX right now.
  46. mWorld->releaseWriteLock();
  47. mActor->userData = NULL;
  48. mWorld->releaseActor( *mActor );
  49. mActor = NULL;
  50. mBodyFlags = 0;
  51. if ( mMaterial )
  52. {
  53. mWorld->releaseMaterial( *mMaterial );
  54. mMaterial = NULL;
  55. }
  56. mColShape = NULL;
  57. }
  58. bool PxBody::init( PhysicsCollision *shape,
  59. F32 mass,
  60. U32 bodyFlags,
  61. SceneObject *obj,
  62. PhysicsWorld *world )
  63. {
  64. AssertFatal( obj, "PxBody::init - Got a null scene object!" );
  65. AssertFatal( world, "PxBody::init - Got a null world!" );
  66. AssertFatal( dynamic_cast<PxWorld*>( world ), "PxBody::init - The world is the wrong type!" );
  67. AssertFatal( shape, "PxBody::init - Got a null collision shape!" );
  68. AssertFatal( dynamic_cast<PxCollision*>( shape ), "PxBody::init - The collision shape is the wrong type!" );
  69. AssertFatal( !((PxCollision*)shape)->getShapes().empty(), "PxBody::init - Got empty collision shape!" );
  70. // Cleanup any previous actor.
  71. _releaseActor();
  72. mWorld = (PxWorld*)world;
  73. mColShape = (PxCollision*)shape;
  74. mBodyFlags = bodyFlags;
  75. NxActorDesc actorDesc;
  76. NxBodyDesc bodyDesc;
  77. const bool isKinematic = mBodyFlags & BF_KINEMATIC;
  78. const bool isTrigger = mBodyFlags & BF_TRIGGER;
  79. const bool isDebris = mBodyFlags & BF_DEBRIS;
  80. if ( isKinematic )
  81. {
  82. // Kinematics are dynamics... so they need
  83. // a body description.
  84. actorDesc.body = &bodyDesc;
  85. bodyDesc.mass = getMax( mass, 1.0f );
  86. bodyDesc.flags |= NX_BF_KINEMATIC;
  87. }
  88. else if ( mass > 0.0f )
  89. {
  90. // We have mass so its a dynamic.
  91. actorDesc.body = &bodyDesc;
  92. bodyDesc.mass = mass;
  93. }
  94. if ( isTrigger )
  95. actorDesc.flags |= NX_AF_DISABLE_RESPONSE;
  96. // Add all the shapes.
  97. const Vector<NxShapeDesc*> &shapes = mColShape->getShapes();
  98. for ( U32 i=0; i < shapes.size(); i++ )
  99. {
  100. NxShapeDesc *desc = shapes[i];
  101. // If this hits then something is broken with
  102. // this descrption... check all the fields to be
  103. // sure their values are correctly filled out.
  104. AssertFatal( desc->isValid(), "PxBody::init - Got invalid shape description!" );
  105. if ( isTrigger )
  106. desc->group = 31;
  107. if ( isDebris )
  108. desc->group = 30;
  109. actorDesc.shapes.push_back( desc );
  110. }
  111. // This sucks, but it has to happen if we want
  112. // to avoid write lock errors from PhysX right now.
  113. mWorld->releaseWriteLock();
  114. mActor = mWorld->getScene()->createActor( actorDesc );
  115. mIsEnabled = true;
  116. if ( isDebris )
  117. mActor->setDominanceGroup( 31 );
  118. mUserData.setObject( obj );
  119. mUserData.setBody( this );
  120. mActor->userData = &mUserData;
  121. return true;
  122. }
  123. void PxBody::setMaterial( F32 restitution,
  124. F32 friction,
  125. F32 staticFriction )
  126. {
  127. AssertFatal( mActor, "PxBody::setMaterial - The actor is null!" );
  128. // If the body is dynamic then wake it up as
  129. // it may need to change behavior.
  130. if ( isDynamic() )
  131. mActor->wakeUp();
  132. NxMaterialDesc desc;
  133. desc.restitution = restitution;
  134. desc.dynamicFriction = friction;
  135. desc.staticFriction = staticFriction;
  136. // If we have a material then just update it as the shapes
  137. // should already have them mapped.
  138. if ( mMaterial )
  139. {
  140. mMaterial->loadFromDesc( desc );
  141. return;
  142. }
  143. // If we got here then create a new material and
  144. // assign it to all our shapes.
  145. mMaterial = mWorld->createMaterial( desc );
  146. U32 matIndex = mMaterial->getMaterialIndex();
  147. U32 count = mActor->getNbShapes();
  148. NxShape*const* shapes = mActor->getShapes();
  149. for ( U32 i=0; i < count; i++ )
  150. shapes[i]->setMaterial( matIndex );
  151. }
  152. void PxBody::setSleepThreshold( F32 linear, F32 angular )
  153. {
  154. AssertFatal( mActor, "PxBody::setSleepThreshold - The actor is null!" );
  155. mActor->setSleepLinearVelocity( linear );
  156. mActor->setSleepAngularVelocity( angular );
  157. }
  158. void PxBody::setDamping( F32 linear, F32 angular )
  159. {
  160. AssertFatal( mActor, "PxBody::setDamping - The actor is null!" );
  161. mActor->setLinearDamping( linear );
  162. mActor->setAngularDamping( angular );
  163. }
  164. void PxBody::getState( PhysicsState *outState )
  165. {
  166. AssertFatal( mActor, "PxBody::getState - The actor is null!" );
  167. AssertFatal( isDynamic(), "PxBody::getState - This call is only for dynamics!" );
  168. // TODO: Fix this to do what we intended... to return
  169. // false so that the caller can early out of the state
  170. // hasn't changed since the last tick.
  171. outState->position = pxCast<Point3F>( mActor->getGlobalPosition() );
  172. outState->orientation = pxCast<QuatF>( mActor->getGlobalOrientationQuat() );
  173. outState->linVelocity = pxCast<Point3F>( mActor->getLinearVelocity() );
  174. outState->angVelocity = pxCast<Point3F>( mActor->getAngularVelocity() );
  175. outState->sleeping = mActor->isSleeping();
  176. outState->momentum = pxCast<Point3F>( mActor->getLinearMomentum() );
  177. }
  178. F32 PxBody::getMass() const
  179. {
  180. AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
  181. return mActor->getMass();
  182. }
  183. Point3F PxBody::getCMassPosition() const
  184. {
  185. AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
  186. return pxCast<Point3F>( mActor->getCMassGlobalPosition() );
  187. }
  188. void PxBody::setLinVelocity( const Point3F &vel )
  189. {
  190. AssertFatal( mActor, "PxBody::setLinVelocity - The actor is null!" );
  191. AssertFatal( isDynamic(), "PxBody::setLinVelocity - This call is only for dynamics!" );
  192. mActor->setLinearVelocity( pxCast<NxVec3>( vel ) );
  193. }
  194. void PxBody::setAngVelocity( const Point3F &vel )
  195. {
  196. AssertFatal( mActor, "PxBody::setAngVelocity - The actor is null!" );
  197. AssertFatal( isDynamic(), "PxBody::setAngVelocity - This call is only for dynamics!" );
  198. mActor->setAngularVelocity( pxCast<NxVec3>( vel ) );
  199. }
  200. Point3F PxBody::getLinVelocity() const
  201. {
  202. AssertFatal( mActor, "PxBody::getLinVelocity - The actor is null!" );
  203. AssertFatal( isDynamic(), "PxBody::getLinVelocity - This call is only for dynamics!" );
  204. return pxCast<Point3F>( mActor->getLinearVelocity() );
  205. }
  206. Point3F PxBody::getAngVelocity() const
  207. {
  208. AssertFatal( mActor, "PxBody::getAngVelocity - The actor is null!" );
  209. AssertFatal( isDynamic(), "PxBody::getAngVelocity - This call is only for dynamics!" );
  210. return pxCast<Point3F>( mActor->getAngularVelocity() );
  211. }
  212. void PxBody::setSleeping( bool sleeping )
  213. {
  214. AssertFatal( mActor, "PxBody::setSleeping - The actor is null!" );
  215. AssertFatal( isDynamic(), "PxBody::setSleeping - This call is only for dynamics!" );
  216. if ( sleeping )
  217. mActor->putToSleep();
  218. else
  219. mActor->wakeUp();
  220. }
  221. bool PxBody::isDynamic() const
  222. {
  223. AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" );
  224. return mActor->isDynamic() && ( mBodyFlags & BF_KINEMATIC ) == 0;
  225. }
  226. PhysicsWorld* PxBody::getWorld()
  227. {
  228. return mWorld;
  229. }
  230. PhysicsCollision* PxBody::getColShape()
  231. {
  232. return mColShape;
  233. }
  234. MatrixF& PxBody::getTransform( MatrixF *outMatrix )
  235. {
  236. AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
  237. mActor->getGlobalPose().getRowMajor44( *outMatrix );
  238. return *outMatrix;
  239. }
  240. Box3F PxBody::getWorldBounds()
  241. {
  242. AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
  243. NxBounds3 bounds;
  244. bounds.setEmpty();
  245. NxBounds3 shapeBounds;
  246. NxShape *const* pShapeArray = mActor->getShapes();
  247. U32 shapeCount = mActor->getNbShapes();
  248. for ( U32 i = 0; i < shapeCount; i++ )
  249. {
  250. // Get the shape's bounds.
  251. pShapeArray[i]->getWorldBounds( shapeBounds );
  252. // Combine them into the total bounds.
  253. bounds.combine( shapeBounds );
  254. }
  255. return pxCast<Box3F>( bounds );
  256. }
  257. void PxBody::setSimulationEnabled( bool enabled )
  258. {
  259. if ( mIsEnabled == enabled )
  260. return;
  261. // This sucks, but it has to happen if we want
  262. // to avoid write lock errors from PhysX right now.
  263. mWorld->releaseWriteLock();
  264. if ( enabled )
  265. {
  266. mIsEnabled = true;
  267. mActor->clearActorFlag( NX_AF_DISABLE_RESPONSE );
  268. mActor->clearActorFlag( NX_AF_DISABLE_COLLISION );
  269. // Don't clear the flag if its supposed to be kinematic.
  270. if ( !(mBodyFlags & BF_KINEMATIC) )
  271. mActor->clearBodyFlag( NX_BF_KINEMATIC );
  272. if ( isDynamic() )
  273. mActor->wakeUp();
  274. }
  275. else
  276. {
  277. mIsEnabled = false;
  278. mActor->raiseActorFlag( NX_AF_DISABLE_RESPONSE );
  279. mActor->raiseActorFlag( NX_AF_DISABLE_COLLISION );
  280. mActor->raiseBodyFlag( NX_BF_KINEMATIC );
  281. }
  282. NxShape *const* shapes = mActor->getShapes();
  283. for ( S32 i = 0; i < mActor->getNbShapes(); i++ )
  284. shapes[i]->setFlag( NX_SF_DISABLE_RAYCASTING, !mIsEnabled );
  285. }
  286. void PxBody::setTransform( const MatrixF &transform )
  287. {
  288. AssertFatal( mActor, "PxBody::setTransform - The actor is null!" );
  289. // This sucks, but it has to happen if we want
  290. // to avoid write lock errors from PhysX right now.
  291. mWorld->releaseWriteLock();
  292. NxMat34 xfm;
  293. xfm.setRowMajor44( transform );
  294. mActor->setGlobalPose( xfm );
  295. // If its dynamic we have more to do.
  296. if ( mActor->isDynamic() && !mActor->readBodyFlag( NX_BF_KINEMATIC ) )
  297. {
  298. mActor->setLinearVelocity( NxVec3( 0, 0, 0 ) );
  299. mActor->setAngularVelocity( NxVec3( 0, 0, 0 ) );
  300. mActor->wakeUp();
  301. }
  302. }
  303. void PxBody::applyCorrection( const MatrixF &transform )
  304. {
  305. AssertFatal( mActor, "PxBody::applyCorrection - The actor is null!" );
  306. AssertFatal( isDynamic(), "PxBody::applyCorrection - This call is only for dynamics!" );
  307. // This sucks, but it has to happen if we want
  308. // to avoid write lock errors from PhysX right now.
  309. mWorld->releaseWriteLock();
  310. NxMat34 xfm;
  311. xfm.setRowMajor44( transform );
  312. mActor->setGlobalPose( xfm );
  313. }
  314. void PxBody::applyImpulse( const Point3F &origin, const Point3F &force )
  315. {
  316. AssertFatal( mActor, "PxBody::applyImpulse - The actor is null!" );
  317. // This sucks, but it has to happen if we want
  318. // to avoid write lock errors from PhysX right now.
  319. mWorld->releaseWriteLock();
  320. if ( mIsEnabled && isDynamic() )
  321. mActor->addForceAtPos( pxCast<NxVec3>( force ),
  322. pxCast<NxVec3>( origin ),
  323. NX_IMPULSE );
  324. }