2
0

px3Body.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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/physx3/px3Body.h"
  24. #include "T3D/physics/physx3/px3.h"
  25. #include "T3D/physics/physx3/px3Casts.h"
  26. #include "T3D/physics/physx3/px3World.h"
  27. #include "T3D/physics/physx3/px3Collision.h"
  28. #include "console/console.h"
  29. #include "console/consoleTypes.h"
  30. Px3Body::Px3Body() :
  31. mActor( NULL ),
  32. mMaterial( NULL ),
  33. mWorld( NULL ),
  34. mBodyFlags( 0 ),
  35. mIsEnabled( true ),
  36. mIsStatic(false)
  37. {
  38. }
  39. Px3Body::~Px3Body()
  40. {
  41. _releaseActor();
  42. }
  43. void Px3Body::_releaseActor()
  44. {
  45. if ( !mActor )
  46. return;
  47. mWorld->releaseWriteLock();
  48. mActor->userData = NULL;
  49. mActor->release();
  50. mActor = NULL;
  51. mBodyFlags = 0;
  52. if ( mMaterial )
  53. {
  54. mMaterial->release();
  55. }
  56. mColShape = NULL;
  57. }
  58. bool Px3Body::init( PhysicsCollision *shape,
  59. F32 mass,
  60. U32 bodyFlags,
  61. SceneObject *obj,
  62. PhysicsWorld *world )
  63. {
  64. AssertFatal( obj, "Px3Body::init - Got a null scene object!" );
  65. AssertFatal( world, "Px3Body::init - Got a null world!" );
  66. AssertFatal( dynamic_cast<Px3World*>( world ), "Px3Body::init - The world is the wrong type!" );
  67. AssertFatal( shape, "Px3Body::init - Got a null collision shape!" );
  68. AssertFatal( dynamic_cast<Px3Collision*>( shape ), "Px3Body::init - The collision shape is the wrong type!" );
  69. AssertFatal( !((Px3Collision*)shape)->getShapes().empty(), "Px3Body::init - Got empty collision shape!" );
  70. // Cleanup any previous actor.
  71. _releaseActor();
  72. mWorld = (Px3World*)world;
  73. mColShape = (Px3Collision*)shape;
  74. mBodyFlags = bodyFlags;
  75. const bool isKinematic = mBodyFlags & BF_KINEMATIC;
  76. const bool isTrigger = mBodyFlags & BF_TRIGGER;
  77. const bool isDebris = mBodyFlags & BF_DEBRIS;
  78. if ( isKinematic )
  79. {
  80. mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY()));
  81. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  82. actor->setRigidDynamicFlag(physx::PxRigidDynamicFlag::eKINEMATIC, true);
  83. actor->setMass(getMax( mass, 1.0f ));
  84. }
  85. else if ( mass > 0.0f )
  86. {
  87. mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY()));
  88. }
  89. else
  90. {
  91. mActor = gPhysics3SDK->createRigidStatic(physx::PxTransform(physx::PxIDENTITY()));
  92. mIsStatic = true;
  93. }
  94. mMaterial = gPhysics3SDK->createMaterial(0.6f,0.4f,0.1f);
  95. // Add all the shapes.
  96. const Vector<Px3CollisionDesc*> &shapes = mColShape->getShapes();
  97. for ( U32 i=0; i < shapes.size(); i++ )
  98. {
  99. Px3CollisionDesc* desc = shapes[i];
  100. if( mass > 0.0f )
  101. {
  102. if(desc->pGeometry->getType() == physx::PxGeometryType::eTRIANGLEMESH)
  103. {
  104. Con::errorf("PhysX3 Dynamic Triangle Mesh is not supported.");
  105. }
  106. }
  107. physx::PxShape * pShape = mActor->createShape(*desc->pGeometry,*mMaterial);
  108. physx::PxFilterData colData;
  109. if(isDebris)
  110. colData.word0 = PX3_DEBRIS;
  111. else if(isTrigger)
  112. colData.word0 = PX3_TRIGGER;
  113. else
  114. colData.word0 = PX3_DEFAULT;
  115. //set local pose - actor->createShape with a local pose is deprecated in physx 3.3
  116. pShape->setLocalPose(desc->pose);
  117. //set the skin width
  118. pShape->setContactOffset(0.01f);
  119. pShape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !isTrigger);
  120. pShape->setFlag(physx::PxShapeFlag::eSCENE_QUERY_SHAPE,true);
  121. pShape->setSimulationFilterData(colData);
  122. pShape->setQueryFilterData(colData);
  123. }
  124. //mass & intertia has to be set after creating the shape
  125. if ( mass > 0.0f )
  126. {
  127. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  128. physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass);
  129. }
  130. // This sucks, but it has to happen if we want
  131. // to avoid write lock errors from PhysX right now.
  132. mWorld->releaseWriteLock();
  133. mWorld->getScene()->addActor(*mActor);
  134. mIsEnabled = true;
  135. if ( isDebris )
  136. mActor->setDominanceGroup( 31 );
  137. mUserData.setObject( obj );
  138. mUserData.setBody( this );
  139. mActor->userData = &mUserData;
  140. return true;
  141. }
  142. void Px3Body::setMaterial( F32 restitution,
  143. F32 friction,
  144. F32 staticFriction )
  145. {
  146. AssertFatal( mActor, "Px3Body::setMaterial - The actor is null!" );
  147. if ( isDynamic() )
  148. {
  149. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  150. actor->wakeUp();
  151. }
  152. mMaterial->setRestitution(restitution);
  153. mMaterial->setStaticFriction(staticFriction);
  154. mMaterial->setDynamicFriction(friction);
  155. }
  156. void Px3Body::setSleepThreshold( F32 linear, F32 angular )
  157. {
  158. AssertFatal( mActor, "Px3Body::setSleepThreshold - The actor is null!" );
  159. if(mIsStatic)
  160. return;
  161. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  162. physx::PxF32 massNormalized= (linear*linear+angular*angular)/2.0f;
  163. actor->setSleepThreshold(massNormalized);
  164. }
  165. void Px3Body::setDamping( F32 linear, F32 angular )
  166. {
  167. AssertFatal( mActor, "Px3Body::setDamping - The actor is null!" );
  168. if(mIsStatic)
  169. return;
  170. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  171. actor->setLinearDamping( linear );
  172. actor->setAngularDamping( angular );
  173. }
  174. void Px3Body::getState( PhysicsState *outState )
  175. {
  176. AssertFatal( mActor, "Px3Body::getState - The actor is null!" );
  177. AssertFatal( isDynamic(), "Px3Body::getState - This call is only for dynamics!" );
  178. outState->position = px3Cast<Point3F>( mActor->getGlobalPose().p );
  179. outState->orientation = px3Cast<QuatF>( mActor->getGlobalPose().q );
  180. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  181. outState->linVelocity = px3Cast<Point3F>( actor->getLinearVelocity() );
  182. outState->angVelocity = px3Cast<Point3F>( actor->getAngularVelocity() );
  183. outState->sleeping = actor->isSleeping();
  184. outState->momentum = px3Cast<Point3F>( (1.0f/actor->getMass()) * actor->getLinearVelocity() );
  185. }
  186. F32 Px3Body::getMass() const
  187. {
  188. AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
  189. if(mIsStatic)
  190. return 0;
  191. const physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  192. return actor->getMass();
  193. }
  194. Point3F Px3Body::getCMassPosition() const
  195. {
  196. AssertFatal( mActor, "Px3Body::getCMassPosition - The actor is null!" );
  197. if(mIsStatic)
  198. return px3Cast<Point3F>(mActor->getGlobalPose().p);
  199. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  200. physx::PxTransform pose = actor->getGlobalPose() * actor->getCMassLocalPose();
  201. return px3Cast<Point3F>(pose.p);
  202. }
  203. void Px3Body::setLinVelocity( const Point3F &vel )
  204. {
  205. AssertFatal( mActor, "Px3Body::setLinVelocity - The actor is null!" );
  206. AssertFatal( isDynamic(), "Px3Body::setLinVelocity - This call is only for dynamics!" );
  207. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  208. actor->setLinearVelocity( px3Cast<physx::PxVec3>( vel ) );
  209. }
  210. void Px3Body::setAngVelocity( const Point3F &vel )
  211. {
  212. AssertFatal( mActor, "Px3Body::setAngVelocity - The actor is null!" );
  213. AssertFatal( isDynamic(), "Px3Body::setAngVelocity - This call is only for dynamics!" );
  214. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  215. actor->setAngularVelocity(px3Cast<physx::PxVec3>( vel ) );
  216. }
  217. Point3F Px3Body::getLinVelocity() const
  218. {
  219. AssertFatal( mActor, "Px3Body::getLinVelocity - The actor is null!" );
  220. AssertFatal( isDynamic(), "Px3Body::getLinVelocity - This call is only for dynamics!" );
  221. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  222. return px3Cast<Point3F>( actor->getLinearVelocity() );
  223. }
  224. Point3F Px3Body::getAngVelocity() const
  225. {
  226. AssertFatal( mActor, "Px3Body::getAngVelocity - The actor is null!" );
  227. AssertFatal( isDynamic(), "Px3Body::getAngVelocity - This call is only for dynamics!" );
  228. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  229. return px3Cast<Point3F>( actor->getAngularVelocity() );
  230. }
  231. void Px3Body::setSleeping( bool sleeping )
  232. {
  233. AssertFatal( mActor, "Px3Body::setSleeping - The actor is null!" );
  234. AssertFatal( isDynamic(), "Px3Body::setSleeping - This call is only for dynamics!" );
  235. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  236. if ( sleeping )
  237. actor->putToSleep();
  238. else
  239. actor->wakeUp();
  240. }
  241. bool Px3Body::isDynamic() const
  242. {
  243. AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" );
  244. return !mIsStatic && ( mBodyFlags & BF_KINEMATIC ) == 0;
  245. }
  246. PhysicsWorld* Px3Body::getWorld()
  247. {
  248. return mWorld;
  249. }
  250. PhysicsCollision* Px3Body::getColShape()
  251. {
  252. return mColShape;
  253. }
  254. MatrixF& Px3Body::getTransform( MatrixF *outMatrix )
  255. {
  256. AssertFatal( mActor, "Px3Body::getTransform - The actor is null!" );
  257. *outMatrix = px3Cast<MatrixF>(mActor->getGlobalPose());
  258. return *outMatrix;
  259. }
  260. Box3F Px3Body::getWorldBounds()
  261. {
  262. AssertFatal( mActor, "Px3Body::getTransform - The actor is null!" );
  263. physx::PxBounds3 bounds;
  264. bounds.setEmpty();
  265. physx::PxBounds3 shapeBounds;
  266. U32 shapeCount = mActor->getNbShapes();
  267. physx::PxShape **shapes = new physx::PxShape*[shapeCount];
  268. mActor->getShapes(shapes, shapeCount);
  269. for ( U32 i = 0; i < shapeCount; i++ )
  270. {
  271. // Get the shape's bounds.
  272. shapeBounds = physx::PxShapeExt::getWorldBounds(*shapes[i],*mActor);
  273. // Combine them into the total bounds.
  274. bounds.include( shapeBounds );
  275. }
  276. delete [] shapes;
  277. return px3Cast<Box3F>( bounds );
  278. }
  279. void Px3Body::setSimulationEnabled( bool enabled )
  280. {
  281. if ( mIsEnabled == enabled )
  282. return;
  283. //Don't need to enable/disable eSIMULATION_SHAPE for trigger,it's disabled permanently
  284. if(mBodyFlags & BF_TRIGGER)
  285. return;
  286. // This sucks, but it has to happen if we want
  287. // to avoid write lock errors from PhysX right now.
  288. mWorld->releaseWriteLock();
  289. U32 shapeCount = mActor->getNbShapes();
  290. physx::PxShape **shapes = new physx::PxShape*[shapeCount];
  291. mActor->getShapes(shapes, shapeCount);
  292. for ( S32 i = 0; i < mActor->getNbShapes(); i++ )
  293. {
  294. shapes[i]->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,!mIsEnabled);//?????
  295. }
  296. delete [] shapes;
  297. }
  298. void Px3Body::setTransform( const MatrixF &transform )
  299. {
  300. AssertFatal( mActor, "Px3Body::setTransform - The actor is null!" );
  301. // This sucks, but it has to happen if we want
  302. // to avoid write lock errors from PhysX right now.
  303. mWorld->releaseWriteLock();
  304. mActor->setGlobalPose(px3Cast<physx::PxTransform>(transform),false);
  305. if(mIsStatic)
  306. return;
  307. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  308. bool kinematic = actor->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC;
  309. // If its dynamic we have more to do.
  310. if ( isDynamic() && !kinematic )
  311. {
  312. actor->setLinearVelocity( physx::PxVec3(0) );
  313. actor->setAngularVelocity( physx::PxVec3(0) );
  314. actor->wakeUp();
  315. }
  316. }
  317. void Px3Body::applyCorrection( const MatrixF &transform )
  318. {
  319. AssertFatal( mActor, "Px3Body::applyCorrection - The actor is null!" );
  320. AssertFatal( isDynamic(), "Px3Body::applyCorrection - This call is only for dynamics!" );
  321. // This sucks, but it has to happen if we want
  322. // to avoid write lock errors from PhysX right now.
  323. mWorld->releaseWriteLock();
  324. mActor->setGlobalPose( px3Cast<physx::PxTransform>(transform) );
  325. }
  326. void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force )
  327. {
  328. AssertFatal( mActor, "Px3Body::applyImpulse - The actor is null!" );
  329. // This sucks, but it has to happen if we want
  330. // to avoid write lock errors from PhysX right now.
  331. mWorld->releaseWriteLock();
  332. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  333. if ( mIsEnabled && isDynamic() )
  334. physx::PxRigidBodyExt::addForceAtPos(*actor,px3Cast<physx::PxVec3>(force),
  335. px3Cast<physx::PxVec3>(origin),
  336. physx::PxForceMode::eIMPULSE);
  337. }
  338. void Px3Body::applyTorque( const Point3F &torque )
  339. {
  340. AssertFatal(mActor, "Px3Body::applyImpulse - The actor is null!");
  341. mWorld->releaseWriteLock();
  342. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  343. if (mIsEnabled && isDynamic())
  344. actor->addTorque( px3Cast<physx::PxVec3>(torque), physx::PxForceMode::eFORCE, true);
  345. }
  346. void Px3Body::applyForce( const Point3F &force )
  347. {
  348. AssertFatal(mActor, "Px3Body::applyTorque - The actor is null!");
  349. mWorld->releaseWriteLock();
  350. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  351. if (mIsEnabled && isDynamic())
  352. actor->addForce( px3Cast<physx::PxVec3>(force), physx::PxForceMode::eFORCE, true);
  353. }
  354. void Px3Body::findContact(SceneObject **contactObject,
  355. VectorF *contactNormal,
  356. Vector<SceneObject*> *outOverlapObjects) const
  357. {
  358. }
  359. void Px3Body::moveKinematicTo(const MatrixF &transform)
  360. {
  361. AssertFatal(mActor, "Px3Body::moveKinematicTo - The actor is null!");
  362. const bool isKinematic = mBodyFlags & BF_KINEMATIC;
  363. if (!isKinematic)
  364. {
  365. Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies.");
  366. return;
  367. }
  368. mWorld->lockScene();
  369. physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
  370. actor->setKinematicTarget(px3Cast<physx::PxTransform>(transform));
  371. mWorld->unlockScene();
  372. }