px3Body.cpp
Engine/source/T3D/physics/physx3/px3Body.cpp
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