1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
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:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
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
21 //-----------------------------------------------------------------------------
23 #include "platform/platform.h"
24 #include "T3D/physics/physx3/px3Body.h"
26 #include "T3D/physics/physx3/px3.h"
27 #include "T3D/physics/physx3/px3Casts.h"
28 #include "T3D/physics/physx3/px3World.h"
29 #include "T3D/physics/physx3/px3Collision.h"
31 #include "console/console.h"
32 #include "console/consoleTypes.h"
50 void Px3Body::_releaseActor()
55 mWorld
->releaseWriteLock();
57 mActor
->userData
= NULL
;
71 bool Px3Body::init( PhysicsCollision
*shape
,
77 AssertFatal( obj
, "Px3Body::init - Got a null scene object!" );
78 AssertFatal( world
, "Px3Body::init - Got a null world!" );
79 AssertFatal( dynamic_cast<Px3World
*>( world
), "Px3Body::init - The world is the wrong type!" );
80 AssertFatal( shape
, "Px3Body::init - Got a null collision shape!" );
81 AssertFatal( dynamic_cast<Px3Collision
*>( shape
), "Px3Body::init - The collision shape is the wrong type!" );
82 AssertFatal( !((Px3Collision
*)shape
)->getShapes().empty(), "Px3Body::init - Got empty collision shape!" );
84 // Cleanup any previous actor.
87 mWorld
= (Px3World
*)world
;
88 mColShape
= (Px3Collision
*)shape
;
89 mBodyFlags
= bodyFlags
;
91 const bool isKinematic
= mBodyFlags
& BF_KINEMATIC
;
92 const bool isTrigger
= mBodyFlags
& BF_TRIGGER
;
93 const bool isDebris
= mBodyFlags
& BF_DEBRIS
;
97 mActor
= gPhysics3SDK
->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY()));
98 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
99 actor
->setRigidDynamicFlag(physx::PxRigidDynamicFlag::eKINEMATIC
, true);
100 actor
->setMass(getMax( mass
, 1.0f
));
102 else if ( mass
> 0.0f
)
104 mActor
= gPhysics3SDK
->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY()));
108 mActor
= gPhysics3SDK
->createRigidStatic(physx::PxTransform(physx::PxIDENTITY()));
112 mMaterial
= gPhysics3SDK
->createMaterial(0.6f
,0.4f
,0.1f
);
114 // Add all the shapes.
115 const Vector
<Px3CollisionDesc
*> &shapes
= mColShape
->getShapes();
116 for ( U32 i
=0; i
< shapes
.size(); i
++ )
118 Px3CollisionDesc
* desc
= shapes
[i
];
121 if(desc
->pGeometry
->getType() == physx::PxGeometryType::eTRIANGLEMESH
)
123 Con::errorf("PhysX3 Dynamic Triangle Mesh is not supported.");
126 physx::PxShape
* pShape
= mActor
->createShape(*desc
->pGeometry
,*mMaterial
);
127 physx::PxFilterData colData
;
129 colData
.word0
= PX3_DEBRIS
;
131 colData
.word0
= PX3_TRIGGER
;
133 colData
.word0
= PX3_DEFAULT
;
135 //set local pose - actor->createShape with a local pose is deprecated in physx 3.3
136 pShape
->setLocalPose(desc
->pose
);
138 pShape
->setContactOffset(0.01f
);
139 pShape
->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE
, !isTrigger
);
140 pShape
->setFlag(physx::PxShapeFlag::eSCENE_QUERY_SHAPE
,true);
141 pShape
->setSimulationFilterData(colData
);
142 pShape
->setQueryFilterData(colData
);
145 //mass & intertia has to be set after creating the shape
148 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
149 physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor
,mass
);
152 // This sucks, but it has to happen if we want
153 // to avoid write lock errors from PhysX right now.
154 mWorld
->releaseWriteLock();
156 mWorld
->getScene()->addActor(*mActor
);
160 mActor
->setDominanceGroup( 31 );
162 mUserData
.setObject( obj
);
163 mUserData
.setBody( this );
164 mActor
->userData
= &mUserData
;
169 void Px3Body::setMaterial( F32 restitution
,
173 AssertFatal( mActor
, "Px3Body::setMaterial - The actor is null!" );
177 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
181 mMaterial
->setRestitution(restitution
);
182 mMaterial
->setStaticFriction(staticFriction
);
183 mMaterial
->setDynamicFriction(friction
);
187 void Px3Body::setSleepThreshold( F32 linear
, F32 angular
)
189 AssertFatal( mActor
, "Px3Body::setSleepThreshold - The actor is null!" );
194 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
195 physx::PxF32 massNormalized
= (linear
*linear
+angular
*angular
)/2.0f
;
196 actor
->setSleepThreshold(massNormalized
);
199 void Px3Body::setDamping( F32 linear
, F32 angular
)
201 AssertFatal( mActor
, "Px3Body::setDamping - The actor is null!" );
205 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
206 actor
->setLinearDamping( linear
);
207 actor
->setAngularDamping( angular
);
210 void Px3Body::getState( PhysicsState
*outState
)
212 AssertFatal( mActor
, "Px3Body::getState - The actor is null!" );
213 AssertFatal( isDynamic(), "Px3Body::getState - This call is only for dynamics!" );
215 outState
->position
= px3Cast
<Point3F
>( mActor
->getGlobalPose().p
);
216 outState
->orientation
= px3Cast
<QuatF
>( mActor
->getGlobalPose().q
);
218 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
219 outState
->linVelocity
= px3Cast
<Point3F
>( actor
->getLinearVelocity() );
220 outState
->angVelocity
= px3Cast
<Point3F
>( actor
->getAngularVelocity() );
221 outState
->sleeping
= actor
->isSleeping();
222 outState
->momentum
= px3Cast
<Point3F
>( (1.0f
/actor
->getMass()) * actor
->getLinearVelocity() );
226 F32
Px3Body::getMass() const
228 AssertFatal( mActor
, "PxBody::getCMassPosition - The actor is null!" );
232 const physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
233 return actor
->getMass();
236 Point3F
Px3Body::getCMassPosition() const
238 AssertFatal( mActor
, "Px3Body::getCMassPosition - The actor is null!" );
240 return px3Cast
<Point3F
>(mActor
->getGlobalPose().p
);
242 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
243 physx::PxTransform pose
= actor
->getGlobalPose() * actor
->getCMassLocalPose();
244 return px3Cast
<Point3F
>(pose
.p
);
247 void Px3Body::setLinVelocity( const Point3F
&vel
)
249 AssertFatal( mActor
, "Px3Body::setLinVelocity - The actor is null!" );
250 AssertFatal( isDynamic(), "Px3Body::setLinVelocity - This call is only for dynamics!" );
252 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
253 actor
->setLinearVelocity( px3Cast
<physx::PxVec3
>( vel
) );
256 void Px3Body::setAngVelocity( const Point3F
&vel
)
258 AssertFatal( mActor
, "Px3Body::setAngVelocity - The actor is null!" );
259 AssertFatal( isDynamic(), "Px3Body::setAngVelocity - This call is only for dynamics!" );
261 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
262 actor
->setAngularVelocity(px3Cast
<physx::PxVec3
>( vel
) );
265 Point3F
Px3Body::getLinVelocity() const
267 AssertFatal( mActor
, "Px3Body::getLinVelocity - The actor is null!" );
268 AssertFatal( isDynamic(), "Px3Body::getLinVelocity - This call is only for dynamics!" );
270 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
271 return px3Cast
<Point3F
>( actor
->getLinearVelocity() );
274 Point3F
Px3Body::getAngVelocity() const
276 AssertFatal( mActor
, "Px3Body::getAngVelocity - The actor is null!" );
277 AssertFatal( isDynamic(), "Px3Body::getAngVelocity - This call is only for dynamics!" );
279 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
280 return px3Cast
<Point3F
>( actor
->getAngularVelocity() );
283 void Px3Body::setSleeping( bool sleeping
)
285 AssertFatal( mActor
, "Px3Body::setSleeping - The actor is null!" );
286 AssertFatal( isDynamic(), "Px3Body::setSleeping - This call is only for dynamics!" );
288 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
295 bool Px3Body::isDynamic() const
297 AssertFatal( mActor
, "PxBody::isDynamic - The actor is null!" );
298 return !mIsStatic
&& ( mBodyFlags
& BF_KINEMATIC
) == 0;
301 PhysicsWorld
* Px3Body::getWorld()
306 PhysicsCollision
* Px3Body::getColShape()
311 MatrixF
& Px3Body::getTransform( MatrixF
*outMatrix
)
313 AssertFatal( mActor
, "Px3Body::getTransform - The actor is null!" );
315 *outMatrix
= px3Cast
<MatrixF
>(mActor
->getGlobalPose());
319 Box3F
Px3Body::getWorldBounds()
321 AssertFatal( mActor
, "Px3Body::getTransform - The actor is null!" );
323 physx::PxBounds3 bounds
;
325 physx::PxBounds3 shapeBounds
;
328 U32 shapeCount
= mActor
->getNbShapes();
329 physx::PxShape
**shapes
= new physx::PxShape
*[shapeCount
];
330 mActor
->getShapes(shapes
, shapeCount
);
331 for ( U32 i
= 0; i
< shapeCount
; i
++ )
333 // Get the shape's bounds.
334 shapeBounds
= physx::PxShapeExt::getWorldBounds(*shapes
[i
],*mActor
);
335 // Combine them into the total bounds.
336 bounds
.include( shapeBounds
);
341 return px3Cast
<Box3F
>( bounds
);
344 void Px3Body::setSimulationEnabled( bool enabled
)
346 if ( mIsEnabled
== enabled
)
349 //Don't need to enable/disable eSIMULATION_SHAPE for trigger,it's disabled permanently
350 if(mBodyFlags
& BF_TRIGGER
)
353 // This sucks, but it has to happen if we want
354 // to avoid write lock errors from PhysX right now.
355 mWorld
->releaseWriteLock();
357 U32 shapeCount
= mActor
->getNbShapes();
358 physx::PxShape
**shapes
= new physx::PxShape
*[shapeCount
];
359 mActor
->getShapes(shapes
, shapeCount
);
360 for ( S32 i
= 0; i
< mActor
->getNbShapes(); i
++ )
362 shapes
[i
]->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE
,!mIsEnabled
);//?????
367 void Px3Body::setTransform( const MatrixF
&transform
)
369 AssertFatal( mActor
, "Px3Body::setTransform - The actor is null!" );
372 // This sucks, but it has to happen if we want
373 // to avoid write lock errors from PhysX right now.
374 mWorld
->releaseWriteLock();
377 mActor
->setGlobalPose(px3Cast
<physx::PxTransform
>(transform
),false);
382 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
383 bool kinematic
= actor
->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC
;
384 // If its dynamic we have more to do.
385 if ( isDynamic() && !kinematic
)
387 actor
->setLinearVelocity( physx::PxVec3(0) );
388 actor
->setAngularVelocity( physx::PxVec3(0) );
393 void Px3Body::applyCorrection( const MatrixF
&transform
)
395 AssertFatal( mActor
, "Px3Body::applyCorrection - The actor is null!" );
396 AssertFatal( isDynamic(), "Px3Body::applyCorrection - This call is only for dynamics!" );
398 // This sucks, but it has to happen if we want
399 // to avoid write lock errors from PhysX right now.
400 mWorld
->releaseWriteLock();
402 mActor
->setGlobalPose( px3Cast
<physx::PxTransform
>(transform
) );
405 void Px3Body::applyImpulse( const Point3F
&origin
, const Point3F
&force
)
407 AssertFatal( mActor
, "Px3Body::applyImpulse - The actor is null!" );
409 // This sucks, but it has to happen if we want
410 // to avoid write lock errors from PhysX right now.
411 mWorld
->releaseWriteLock();
412 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
413 if ( mIsEnabled
&& isDynamic() )
414 physx::PxRigidBodyExt::addForceAtPos(*actor
,px3Cast
<physx::PxVec3
>(force
),
415 px3Cast
<physx::PxVec3
>(origin
),
416 physx::PxForceMode::eIMPULSE
);
420 void Px3Body::applyTorque( const Point3F
&torque
)
422 AssertFatal(mActor
, "Px3Body::applyImpulse - The actor is null!");
424 mWorld
->releaseWriteLock();
425 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
426 if (mIsEnabled
&& isDynamic())
427 actor
->addTorque( px3Cast
<physx::PxVec3
>(torque
), physx::PxForceMode::eFORCE
, true);
430 void Px3Body::findContact(SceneObject
**contactObject
,
431 VectorF
*contactNormal
,
432 Vector
<SceneObject
*> *outOverlapObjects
) const
436 void Px3Body::moveKinematicTo(const MatrixF
&transform
)
438 AssertFatal(mActor
, "Px3Body::moveKinematicTo - The actor is null!");
440 const bool isKinematic
= mBodyFlags
& BF_KINEMATIC
;
443 Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies.");
449 physx::PxRigidDynamic
*actor
= mActor
->is
<physx::PxRigidDynamic
>();
450 actor
->setKinematicTarget(px3Cast
<physx::PxTransform
>(transform
));
452 mWorld
->unlockScene();