px3Body.cpp

Engine/source/T3D/physics/physx3/px3Body.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "T3D/physics/physx3/px3Body.h"
 26
 27#include "T3D/physics/physx3/px3.h"
 28#include "T3D/physics/physx3/px3Casts.h"
 29#include "T3D/physics/physx3/px3World.h"
 30#include "T3D/physics/physx3/px3Collision.h"
 31
 32#include "console/console.h"
 33#include "console/consoleTypes.h"
 34
 35
 36Px3Body::Px3Body() :
 37   mActor( NULL ),
 38   mMaterial( NULL ),
 39   mWorld( NULL ),
 40   mBodyFlags( 0 ),
 41   mIsEnabled( true ),
 42   mIsStatic(false)
 43{
 44}
 45
 46Px3Body::~Px3Body()
 47{
 48   _releaseActor();
 49}
 50
 51void Px3Body::_releaseActor()
 52{
 53   if ( !mActor )
 54      return;
 55
 56   mActor->userData = NULL;
 57
 58   SafeReleasePhysx(mActor);
 59   mBodyFlags = 0;
 60
 61   if ( mMaterial )
 62   {
 63      mMaterial->release();
 64   }
 65
 66   mColShape = NULL;
 67}
 68
 69bool Px3Body::init(   PhysicsCollision *shape, 
 70                     F32 mass,
 71                     U32 bodyFlags,
 72                     SceneObject *obj, 
 73                     PhysicsWorld *world )
 74{
 75   AssertFatal( obj, "Px3Body::init - Got a null scene object!" );
 76   AssertFatal( world, "Px3Body::init - Got a null world!" );
 77   AssertFatal( dynamic_cast<Px3World*>( world ), "Px3Body::init - The world is the wrong type!" );
 78   AssertFatal( shape, "Px3Body::init - Got a null collision shape!" );
 79   AssertFatal( dynamic_cast<Px3Collision*>( shape ), "Px3Body::init - The collision shape is the wrong type!" );
 80   AssertFatal( !((Px3Collision*)shape)->getShapes().empty(), "Px3Body::init - Got empty collision shape!" );
 81    
 82   // Cleanup any previous actor.
 83   _releaseActor();
 84
 85   mWorld = (Px3World*)world;
 86   mColShape = (Px3Collision*)shape;
 87   mBodyFlags = bodyFlags;
 88
 89   const bool isKinematic = mBodyFlags & BF_KINEMATIC;
 90   const bool isTrigger = mBodyFlags & BF_TRIGGER;
 91   const bool isDebris = mBodyFlags & BF_DEBRIS;
 92
 93   if ( isKinematic )
 94   {
 95      mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY()));
 96      physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
 97      actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, true);
 98      actor->setMass(getMax( mass, 1.0f ));
 99   }
100   else if ( mass > 0.0f )
101   {
102      mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY()));
103      physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
104      actor->setMaxAngularVelocity(80.f);
105   }
106   else
107   {
108      mActor = gPhysics3SDK->createRigidStatic(physx::PxTransform(physx::PxIDENTITY()));
109      mIsStatic = true;
110   }
111
112   mMaterial = gPhysics3SDK->createMaterial(0.6f,0.4f,0.1f);
113  
114   // Add all the shapes.
115   const Vector<Px3CollisionDesc*> &shapes = mColShape->getShapes();
116   for ( U32 i=0; i < shapes.size(); i++ )
117   {
118      Px3CollisionDesc* desc = shapes[i];
119      if( mass > 0.0f )
120      {
121         if(desc->pGeometry->getType() == physx::PxGeometryType::eTRIANGLEMESH)
122         {
123            Con::errorf("PhysX3 Dynamic Triangle Mesh is not supported.");
124         }
125      }
126      
127      physx::PxShape * pShape = physx::PxRigidActorExt::createExclusiveShape(*mActor, *desc->pGeometry, *mMaterial);
128      physx::PxFilterData colData;
129      if(isDebris)
130         colData.word0 = PX3_DEBRIS;
131      else if(isTrigger)
132         colData.word0 = PX3_TRIGGER;
133      else
134         colData.word0 = PX3_DEFAULT;
135
136      //set local pose - actor->createShape with a local pose is deprecated in physx 3.3
137      pShape->setLocalPose(desc->pose);
138      //set the skin width
139      pShape->setContactOffset(0.01f);
140      pShape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !isTrigger);
141      pShape->setFlag(physx::PxShapeFlag::eSCENE_QUERY_SHAPE,true);
142      pShape->setSimulationFilterData(colData);
143      pShape->setQueryFilterData(colData);
144   }
145
146   //mass & intertia has to be set after creating the shape
147   if ( mass > 0.0f )
148   {
149      physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
150      physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass);
151   }
152
153   mWorld->getScene()->addActor(*mActor);
154   mIsEnabled = true;
155
156   if ( isDebris )
157     mActor->setDominanceGroup( 31 );
158
159   mUserData.setObject( obj );
160   mUserData.setBody( this );
161   mActor->userData = &mUserData;
162
163   return true;
164}
165
166void Px3Body::setMaterial(  F32 restitution,
167                           F32 friction, 
168                           F32 staticFriction )
169{
170   AssertFatal( mActor, "Px3Body::setMaterial - The actor is null!" );
171
172   if ( isDynamic() )
173   {
174      physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
175      actor->wakeUp();
176   }
177
178   mMaterial->setRestitution(restitution);
179   mMaterial->setStaticFriction(staticFriction);
180   mMaterial->setDynamicFriction(friction);
181
182}
183
184void Px3Body::setSleepThreshold( F32 linear, F32 angular )
185{
186   AssertFatal( mActor, "Px3Body::setSleepThreshold - The actor is null!" );
187
188   if(mIsStatic)
189      return;
190
191   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
192   physx::PxF32 massNormalized= (linear*linear+angular*angular)/2.0f;
193   actor->setSleepThreshold(massNormalized);
194}
195
196void Px3Body::setDamping( F32 linear, F32 angular )
197{
198   AssertFatal( mActor, "Px3Body::setDamping - The actor is null!" );
199   if(mIsStatic)
200      return;
201
202   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
203   actor->setLinearDamping( linear );
204   actor->setAngularDamping( angular );
205}
206
207void Px3Body::getState( PhysicsState *outState )
208{
209   AssertFatal( mActor, "Px3Body::getState - The actor is null!" );
210   AssertFatal( isDynamic(), "Px3Body::getState - This call is only for dynamics!" );
211
212   outState->position = px3Cast<Point3F>( mActor->getGlobalPose().p );
213   outState->orientation = px3Cast<QuatF>( mActor->getGlobalPose().q );
214
215   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
216   outState->linVelocity = px3Cast<Point3F>( actor->getLinearVelocity() ); 
217   outState->angVelocity = px3Cast<Point3F>( actor->getAngularVelocity() );
218   outState->sleeping = actor->isSleeping();
219   outState->momentum = px3Cast<Point3F>( (1.0f/actor->getMass()) * actor->getLinearVelocity() );
220
221}
222
223F32 Px3Body::getMass() const
224{
225   AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
226   if(mIsStatic)
227      return 0;
228
229   const physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
230   return actor->getMass();
231}
232
233Point3F Px3Body::getCMassPosition() const
234{
235   AssertFatal( mActor, "Px3Body::getCMassPosition - The actor is null!" );
236   if(mIsStatic)
237      return px3Cast<Point3F>(mActor->getGlobalPose().p);
238
239   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
240   physx::PxTransform pose = actor->getGlobalPose() * actor->getCMassLocalPose();
241   return px3Cast<Point3F>(pose.p);
242}
243
244void Px3Body::setLinVelocity( const Point3F &vel )
245{
246   AssertFatal( mActor, "Px3Body::setLinVelocity - The actor is null!" );
247   AssertFatal( isDynamic(), "Px3Body::setLinVelocity - This call is only for dynamics!" );
248
249   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
250   actor->setLinearVelocity( px3Cast<physx::PxVec3>( vel ) );
251}
252
253void Px3Body::setAngVelocity( const Point3F &vel )
254{
255   AssertFatal( mActor, "Px3Body::setAngVelocity - The actor is null!" );
256   AssertFatal( isDynamic(), "Px3Body::setAngVelocity - This call is only for dynamics!" );
257
258   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
259   actor->setAngularVelocity(px3Cast<physx::PxVec3>( vel ) );
260}
261
262Point3F Px3Body::getLinVelocity() const
263{
264   AssertFatal( mActor, "Px3Body::getLinVelocity - The actor is null!" );
265   AssertFatal( isDynamic(), "Px3Body::getLinVelocity - This call is only for dynamics!" );
266
267   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
268   return px3Cast<Point3F>( actor->getLinearVelocity() );
269}
270
271Point3F Px3Body::getAngVelocity() const
272{
273   AssertFatal( mActor, "Px3Body::getAngVelocity - The actor is null!" );
274   AssertFatal( isDynamic(), "Px3Body::getAngVelocity - This call is only for dynamics!" );
275
276   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
277   return px3Cast<Point3F>( actor->getAngularVelocity() );
278}
279
280void Px3Body::setSleeping( bool sleeping )
281{
282   AssertFatal( mActor, "Px3Body::setSleeping - The actor is null!" );
283   AssertFatal( isDynamic(), "Px3Body::setSleeping - This call is only for dynamics!" );
284
285   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
286   if ( sleeping )
287      actor->putToSleep();
288   else
289      actor->wakeUp();
290}
291
292bool Px3Body::isDynamic() const
293{
294   AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" );
295   return !mIsStatic && ( mBodyFlags & BF_KINEMATIC ) == 0;
296}
297
298PhysicsWorld* Px3Body::getWorld() 
299{
300   return mWorld; 
301}
302
303PhysicsCollision* Px3Body::getColShape() 
304{ 
305   return mColShape; 
306}
307
308MatrixF& Px3Body::getTransform( MatrixF *outMatrix )
309{
310   AssertFatal( mActor, "Px3Body::getTransform - The actor is null!" );
311
312   *outMatrix = px3Cast<MatrixF>(mActor->getGlobalPose());
313   return *outMatrix;
314}
315
316Box3F Px3Body::getWorldBounds()
317{
318   AssertFatal( mActor, "Px3Body::getTransform - The actor is null!" );
319   
320   physx::PxBounds3 bounds;
321   bounds.setEmpty();   
322   physx::PxBounds3 shapeBounds; 
323  
324   U32 shapeCount = mActor->getNbShapes();
325   physx::PxShape **shapes = new physx::PxShape*[shapeCount];
326   mActor->getShapes(shapes, shapeCount);
327   for ( U32 i = 0; i < shapeCount; i++ )
328   {
329      // Get the shape's bounds.    
330      shapeBounds = physx::PxShapeExt::getWorldBounds(*shapes[i],*mActor);
331      // Combine them into the total bounds.
332      bounds.include( shapeBounds ); 
333   }
334
335   delete [] shapes;
336
337   return px3Cast<Box3F>( bounds );
338}
339
340void Px3Body::setSimulationEnabled( bool enabled )
341{
342   if ( mIsEnabled == enabled )
343      return;
344
345   //Don't need to enable/disable eSIMULATION_SHAPE for trigger,it's disabled permanently
346   if(mBodyFlags & BF_TRIGGER)
347      return;
348  
349   U32 shapeCount = mActor->getNbShapes();
350   physx::PxShape **shapes = new physx::PxShape*[shapeCount];
351   mActor->getShapes(shapes, shapeCount);
352   for ( S32 i = 0; i < mActor->getNbShapes(); i++ )
353   {
354      shapes[i]->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,!mIsEnabled);//?????
355   }
356
357   delete [] shapes;
358}
359void Px3Body::setTransform( const MatrixF &transform )
360{
361   AssertFatal( mActor, "Px3Body::setTransform - The actor is null!" );
362   
363   mActor->setGlobalPose(px3Cast<physx::PxTransform>(transform),false);
364
365   if(mIsStatic)
366      return;
367
368   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
369   bool kinematic = actor->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC;
370   // If its dynamic we have more to do.
371   if ( isDynamic() && !kinematic )
372   {
373      actor->setLinearVelocity( physx::PxVec3(0) );
374      actor->setAngularVelocity( physx::PxVec3(0) );
375      actor->wakeUp();
376   }
377}
378
379void Px3Body::applyCorrection( const MatrixF &transform )
380{
381   AssertFatal( mActor, "Px3Body::applyCorrection - The actor is null!" );
382   AssertFatal( isDynamic(), "Px3Body::applyCorrection - This call is only for dynamics!" );
383
384   mActor->setGlobalPose( px3Cast<physx::PxTransform>(transform) ); 
385}
386
387void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force )
388{
389   AssertFatal( mActor, "Px3Body::applyImpulse - The actor is null!" );
390
391   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
392   if ( mIsEnabled && isDynamic() )
393   physx::PxRigidBodyExt::addForceAtPos( *actor,px3Cast<physx::PxVec3>(force), px3Cast<physx::PxVec3>(origin), physx::PxForceMode::eIMPULSE );
394}
395
396void Px3Body::applyTorque(const Point3F &torque)
397{
398   AssertFatal(mActor, "Px3Body::applyImpulse - The actor is null!");
399
400   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
401   if (mIsEnabled && isDynamic())
402      actor->addTorque(px3Cast<physx::PxVec3>(torque), physx::PxForceMode::eFORCE, true);
403}
404
405void Px3Body::applyForce(const Point3F &force)
406{
407   AssertFatal(mActor, "Px3Body::applyTorque - The actor is null!");
408
409   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
410   if (mIsEnabled && isDynamic())
411      actor->addForce(px3Cast<physx::PxVec3>(force), physx::PxForceMode::eFORCE, true);
412}
413
414void Px3Body::findContact(SceneObject **contactObject,
415   VectorF *contactNormal,
416   Vector<SceneObject*> *outOverlapObjects) const
417{
418}
419
420void Px3Body::moveKinematicTo(const MatrixF &transform)
421{
422   AssertFatal(mActor, "Px3Body::moveKinematicTo - The actor is null!");
423
424   const bool isKinematic = mBodyFlags & BF_KINEMATIC;
425   if (!isKinematic)
426   {
427      Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies.");
428      return;
429   }
430
431   mWorld->lockScene();
432
433   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
434   actor->setKinematicTarget(px3Cast<physx::PxTransform>(transform));
435
436   mWorld->unlockScene();
437}
438
439