px3Player.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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/px3Player.h"
  24. #include "T3D/physics/physicsPlugin.h"
  25. #include "T3D/physics/physx3/px3World.h"
  26. #include "T3D/physics/physx3/px3Casts.h"
  27. #include "T3D/physics/physx3/px3Utils.h"
  28. #include "collision/collision.h"
  29. Px3Player::Px3Player()
  30. : PhysicsPlayer(),
  31. mController( NULL ),
  32. mWorld( NULL ),
  33. mObject( NULL ),
  34. mSkinWidth( 0.05f ),
  35. mOriginOffset( 0.0f ),
  36. mElapsed(0)
  37. {
  38. PHYSICSMGR->getPhysicsResetSignal().notify( this, &Px3Player::_onPhysicsReset );
  39. }
  40. Px3Player::~Px3Player()
  41. {
  42. _releaseController();
  43. PHYSICSMGR->getPhysicsResetSignal().remove( this, &Px3Player::_onPhysicsReset );
  44. }
  45. void Px3Player::_releaseController()
  46. {
  47. if ( mController )
  48. {
  49. mController->getActor()->userData = NULL;
  50. mWorld->getStaticChangedSignal().remove( this, &Px3Player::_onStaticChanged );
  51. SafeReleasePhysx(mController);
  52. }
  53. }
  54. void Px3Player::init( const char *type,
  55. const Point3F &size,
  56. F32 runSurfaceCos,
  57. F32 stepHeight,
  58. SceneObject *obj,
  59. PhysicsWorld *world )
  60. {
  61. AssertFatal( obj, "Px3Player::init - Got a null scene object!" );
  62. AssertFatal( world, "Px3Player::init - Got a null world!" );
  63. AssertFatal( dynamic_cast<Px3World*>( world ), "Px3Player::init - The world is the wrong type!" );
  64. // Cleanup any previous controller.
  65. _releaseController();
  66. mObject = obj;
  67. mWorld = (Px3World*)world;
  68. mOriginOffset = size.z * 0.5f;
  69. physx::PxCapsuleControllerDesc desc;
  70. desc.contactOffset = mSkinWidth;
  71. desc.radius = getMax( size.x, size.y ) * 0.5f;
  72. desc.radius -= mSkinWidth;
  73. desc.height = size.z - ( desc.radius * 2.0f );
  74. desc.height -= mSkinWidth * 2.0f;
  75. desc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED;
  76. desc.position.set( 0, 0, 0 );
  77. desc.upDirection = physx::PxVec3(0,0,1);
  78. desc.reportCallback = this;
  79. desc.slopeLimit = runSurfaceCos;
  80. desc.stepOffset = stepHeight;
  81. desc.behaviorCallback = NULL;
  82. desc.material = gPhysics3SDK->createMaterial(0.1f, 0.1f, 0.2f);
  83. mController = mWorld->createController( desc );
  84. mWorld->getStaticChangedSignal().notify( this, &Px3Player::_onStaticChanged );
  85. physx::PxRigidDynamic *kineActor = mController->getActor();
  86. //player only has one shape
  87. physx::PxShape *shape = px3GetFirstShape(kineActor);
  88. physx::PxFilterData colData;
  89. colData.word0 = PX3_PLAYER;
  90. shape->setSimulationFilterData(colData);
  91. shape->setQueryFilterData(colData);
  92. //store geometry for later use in findContact calls
  93. shape->getCapsuleGeometry(mGeometry);
  94. mUserData.setObject( obj );
  95. kineActor->userData = &mUserData;
  96. }
  97. void Px3Player::_onStaticChanged()
  98. {
  99. if(mController)
  100. mController->invalidateCache();
  101. }
  102. void Px3Player::_onPhysicsReset( PhysicsResetEvent reset )
  103. {
  104. if(mController)
  105. mController->invalidateCache();
  106. }
  107. Point3F Px3Player::move( const VectorF &disp, CollisionList &outCol )
  108. {
  109. AssertFatal( mController, "Px3Player::move - The controller is null!" );
  110. // Return the last position if the simulation is stopped.
  111. //
  112. // See PxPlayer::_onPhysicsReset
  113. if ( !mWorld->isEnabled() )
  114. {
  115. Point3F newPos = px3Cast<Point3F>( mController->getPosition() );
  116. newPos.z -= mOriginOffset;
  117. return newPos;
  118. }
  119. mCollisionList = &outCol;
  120. physx::PxVec3 dispNx( disp.x, disp.y, disp.z );
  121. if (mIsZero(disp.z))
  122. dispNx.z = 0.0f;
  123. U32 groups = 0xffffffff;
  124. groups &= ~( PX3_TRIGGER ); // No trigger shapes!
  125. groups &= ~( PX3_DEBRIS);
  126. physx::PxControllerFilters filter;
  127. physx::PxFilterData data;
  128. data.word0=groups;
  129. filter.mFilterData = &data;
  130. filter.mFilterFlags = physx::PxQueryFlags(physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::eSTATIC);
  131. mController->move( dispNx,0.0001f,0, filter );
  132. Point3F newPos = px3Cast<Point3F>( mController->getPosition() );
  133. newPos.z -= mOriginOffset;
  134. mCollisionList = NULL;
  135. return newPos;
  136. }
  137. void Px3Player::onShapeHit( const physx::PxControllerShapeHit& hit )
  138. {
  139. if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions)
  140. return;
  141. physx::PxRigidActor *actor = hit.actor;
  142. PhysicsUserData *userData = PhysicsUserData::cast( actor->userData );
  143. // Fill out the Collision
  144. // structure for use later.
  145. Collision &col = mCollisionList->increment();
  146. dMemset( &col, 0, sizeof( col ) );
  147. col.normal = px3Cast<Point3F>( hit.worldNormal );
  148. col.point = px3Cast<Point3F>( hit.worldPos );
  149. col.distance = hit.length;
  150. if ( userData )
  151. col.object = userData->getObject();
  152. if (mIsZero(hit.dir.z))
  153. {
  154. if (col.normal.z > 0.0f)
  155. {
  156. col.normal.z = 0.0f;
  157. col.normal.normalizeSafe();
  158. }
  159. }
  160. else
  161. {
  162. col.normal.set(0.0f, 0.0f, 1.0f);
  163. }
  164. }
  165. void Px3Player::onControllerHit( const physx::PxControllersHit& hit )
  166. {
  167. if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions)
  168. return;
  169. physx::PxRigidActor *actor = hit.other->getActor();
  170. PhysicsUserData *userData = PhysicsUserData::cast( actor->userData );
  171. // For controller-to-controller hit we don't have an actual hit point, so all
  172. // we can do is set the hit object.
  173. Collision &col = mCollisionList->increment();
  174. dMemset( &col, 0, sizeof( col ) );
  175. if ( userData )
  176. col.object = userData->getObject();
  177. }
  178. void Px3Player::findContact( SceneObject **contactObject,
  179. VectorF *contactNormal,
  180. Vector<SceneObject*> *outOverlapObjects ) const
  181. {
  182. // Calculate the sweep motion...
  183. F32 halfCapSize = mOriginOffset;
  184. F32 halfSmallCapSize = halfCapSize * 0.8f;
  185. F32 diff = halfCapSize - halfSmallCapSize;
  186. F32 distance = diff + mSkinWidth + 0.01f;
  187. physx::PxVec3 dir(0,0,-1);
  188. physx::PxScene *scene = mWorld->getScene();
  189. physx::PxHitFlags hitFlags(physx::PxHitFlag::eDEFAULT);
  190. physx::PxQueryFilterData filterData(physx::PxQueryFlag::eDYNAMIC|physx::PxQueryFlag::eSTATIC);
  191. filterData.data.word0 = PX3_DEFAULT;
  192. physx::PxSweepHit sweepHit;
  193. physx::PxRigidDynamic *actor= mController->getActor();
  194. physx::PxU32 shapeIndex;
  195. bool hit = physx::PxRigidBodyExt::linearSweepSingle(*actor,*scene,dir,distance,hitFlags,sweepHit,shapeIndex,filterData);
  196. if ( hit )
  197. {
  198. PhysicsUserData *data = PhysicsUserData::cast( sweepHit.actor->userData);
  199. if ( data )
  200. {
  201. *contactObject = data->getObject();
  202. *contactNormal = px3Cast<Point3F>( sweepHit.normal );
  203. }
  204. }
  205. // Check for overlapped objects ( triggers )
  206. if ( !outOverlapObjects )
  207. return;
  208. filterData.data.word0 = PX3_TRIGGER;
  209. const physx::PxU32 bufferSize = 10;
  210. physx::PxOverlapBufferN<bufferSize> hitBuffer;
  211. hit = scene->overlap(mGeometry,actor->getGlobalPose(),hitBuffer,filterData);
  212. if(hit)
  213. {
  214. for ( U32 i = 0; i < hitBuffer.nbTouches; i++ )
  215. {
  216. PhysicsUserData *data = PhysicsUserData::cast( hitBuffer.touches[i].actor->userData );
  217. if ( data )
  218. outOverlapObjects->push_back( data->getObject() );
  219. }
  220. }
  221. }
  222. void Px3Player::enableCollision()
  223. {
  224. AssertFatal( mController, "Px3Player::enableCollision - The controller is null!" );
  225. px3GetFirstShape(mController->getActor())->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,true);
  226. }
  227. void Px3Player::disableCollision()
  228. {
  229. AssertFatal( mController, "Px3Player::disableCollision - The controller is null!" );
  230. px3GetFirstShape(mController->getActor())->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,false);
  231. }
  232. PhysicsWorld* Px3Player::getWorld()
  233. {
  234. return mWorld;
  235. }
  236. void Px3Player::setTransform( const MatrixF &transform )
  237. {
  238. AssertFatal( mController, "Px3Player::setTransform - The controller is null!" );
  239. Point3F newPos = transform.getPosition();
  240. newPos.z += mOriginOffset;
  241. const Point3F &curPos = px3Cast<Point3F>(mController->getPosition());
  242. if ( !(newPos - curPos ).isZero() )
  243. mController->setPosition( px3Cast<physx::PxExtendedVec3>(newPos) );
  244. }
  245. MatrixF& Px3Player::getTransform( MatrixF *outMatrix )
  246. {
  247. AssertFatal( mController, "Px3Player::getTransform - The controller is null!" );
  248. Point3F newPos = px3Cast<Point3F>( mController->getPosition() );
  249. newPos.z -= mOriginOffset;
  250. outMatrix->setPosition( newPos );
  251. return *outMatrix;
  252. }
  253. void Px3Player::setScale( const Point3F &scale )
  254. {
  255. //Ignored
  256. }
  257. Box3F Px3Player::getWorldBounds()
  258. {
  259. physx::PxBounds3 bounds;
  260. physx::PxRigidDynamic *actor = mController->getActor();
  261. physx::PxShape *shape = px3GetFirstShape(actor);
  262. bounds = physx::PxShapeExt::getWorldBounds(*shape,*actor);
  263. return px3Cast<Box3F>( bounds );
  264. }
  265. bool Px3Player::testSpacials(const Point3F &nPos, const Point3F &nSize) const
  266. {
  267. F32 offset = nSize.z * 0.5f;
  268. F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth;
  269. F32 height = (nSize.z - (radius * 2.0f)) * 0.5f;
  270. height -= mSkinWidth * 2.0f;
  271. physx::PxCapsuleGeometry geom(radius, height);
  272. physx::PxVec3 pos(nPos.x, nPos.y, nPos.z + offset);
  273. physx::PxQuat orientation(Float_HalfPi, physx::PxVec3(0.0f, 1.0f, 0.0f));
  274. physx::PxOverlapBuffer hit;
  275. physx::PxQueryFilterData queryFilter(physx::PxQueryFlag::eANY_HIT | physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC);
  276. queryFilter.data.word0 = PX3_DEFAULT;
  277. bool hasHit = mWorld->getScene()->overlap(geom, physx::PxTransform(pos, orientation), hit, queryFilter);
  278. return !hasHit; // Return true if there are no overlapping objects
  279. }
  280. void Px3Player::setSpacials(const Point3F &nPos, const Point3F &nSize)
  281. {
  282. mOriginOffset = nSize.z * 0.5f;
  283. F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth;
  284. F32 height = nSize.z - (radius * 2.0f);
  285. height -= mSkinWidth * 2.0f;
  286. mController->resize(height);
  287. px3GetFirstShape(mController->getActor())->getCapsuleGeometry(mGeometry);
  288. }