From 215ae090b47534a477ea33094f20592a647103d4 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Wed, 4 Jan 2017 13:34:33 +1000 Subject: [PATCH] Physx 2.8 removal --- Engine/source/T3D/physics/physx/px.h | 80 - Engine/source/T3D/physics/physx/pxBody.cpp | 404 --- Engine/source/T3D/physics/physx/pxBody.h | 114 - Engine/source/T3D/physics/physx/pxCasts.h | 150 - Engine/source/T3D/physics/physx/pxCloth.cpp | 923 ------ Engine/source/T3D/physics/physx/pxCloth.h | 176 -- .../source/T3D/physics/physx/pxCollision.cpp | 291 -- Engine/source/T3D/physics/physx/pxCollision.h | 78 - .../T3D/physics/physx/pxContactReporter.cpp | 108 - .../T3D/physics/physx/pxContactReporter.h | 54 - Engine/source/T3D/physics/physx/pxFluid.cpp | 310 -- Engine/source/T3D/physics/physx/pxFluid.h | 107 - .../source/T3D/physics/physx/pxMaterial.cpp | 150 - Engine/source/T3D/physics/physx/pxMaterial.h | 69 - .../source/T3D/physics/physx/pxMultiActor.cpp | 2651 ----------------- .../source/T3D/physics/physx/pxMultiActor.h | 398 --- Engine/source/T3D/physics/physx/pxPlayer.cpp | 428 --- Engine/source/T3D/physics/physx/pxPlayer.h | 106 - Engine/source/T3D/physics/physx/pxPlugin.cpp | 297 -- Engine/source/T3D/physics/physx/pxPlugin.h | 59 - Engine/source/T3D/physics/physx/pxStream.cpp | 174 -- Engine/source/T3D/physics/physx/pxStream.h | 78 - Engine/source/T3D/physics/physx/pxUtils.cpp | 109 - Engine/source/T3D/physics/physx/pxUtils.h | 38 - Engine/source/T3D/physics/physx/pxWorld.cpp | 876 ------ Engine/source/T3D/physics/physx/pxWorld.h | 193 -- 26 files changed, 8421 deletions(-) delete mode 100644 Engine/source/T3D/physics/physx/px.h delete mode 100644 Engine/source/T3D/physics/physx/pxBody.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxBody.h delete mode 100644 Engine/source/T3D/physics/physx/pxCasts.h delete mode 100644 Engine/source/T3D/physics/physx/pxCloth.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxCloth.h delete mode 100644 Engine/source/T3D/physics/physx/pxCollision.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxCollision.h delete mode 100644 Engine/source/T3D/physics/physx/pxContactReporter.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxContactReporter.h delete mode 100644 Engine/source/T3D/physics/physx/pxFluid.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxFluid.h delete mode 100644 Engine/source/T3D/physics/physx/pxMaterial.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxMaterial.h delete mode 100644 Engine/source/T3D/physics/physx/pxMultiActor.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxMultiActor.h delete mode 100644 Engine/source/T3D/physics/physx/pxPlayer.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxPlayer.h delete mode 100644 Engine/source/T3D/physics/physx/pxPlugin.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxPlugin.h delete mode 100644 Engine/source/T3D/physics/physx/pxStream.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxStream.h delete mode 100644 Engine/source/T3D/physics/physx/pxUtils.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxUtils.h delete mode 100644 Engine/source/T3D/physics/physx/pxWorld.cpp delete mode 100644 Engine/source/T3D/physics/physx/pxWorld.h diff --git a/Engine/source/T3D/physics/physx/px.h b/Engine/source/T3D/physics/physx/px.h deleted file mode 100644 index 856035cf7..000000000 --- a/Engine/source/T3D/physics/physx/px.h +++ /dev/null @@ -1,80 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -// -// This PhysX implementation for Torque was originally based on -// the "PhysX in TGEA" resource written by Shannon Scarvaci. -// -// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=12711 -// - -#ifndef _PHYSX_H_ -#define _PHYSX_H_ - -/* -#ifndef _TORQUE_TYPES_H_ -# include "platform/types.h" -#endif -*/ - -#include "platform/tmm_off.h" - -#ifdef TORQUE_DEBUG -#include -#endif - -#if defined(TORQUE_OS_MAC) && !defined(__APPLE__) - #define __APPLE__ -#elif defined(TORQUE_OS_LINUX) && !defined(LINUX) - #define LINUX -#elif defined(TORQUE_OS_WIN) && !defined(WIN32) - #define WIN32 -#endif - -#ifndef NX_PHYSICS_NXPHYSICS -#include -#endif -#ifndef NX_FOUNDATION_NXSTREAM -#include -#endif -#ifndef NX_COOKING_H -#include -#endif -#ifndef NX_FOUNDATION_NXUSEROUTPUTSTREAM -#include -#endif -#ifndef NX_PHYSICS_NXBIG -#include "NxExtended.h" -#endif -#include -#include -#include -#include -#include -#include - -/// The single global physx sdk object for this process. -extern NxPhysicsSDK *gPhysicsSDK; - -#include "platform/tmm_on.h" - -#endif // _PHYSX_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxBody.cpp b/Engine/source/T3D/physics/physx/pxBody.cpp deleted file mode 100644 index de889139c..000000000 --- a/Engine/source/T3D/physics/physx/pxBody.cpp +++ /dev/null @@ -1,404 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxBody.h" - -#include "T3D/physics/physX/px.h" -#include "T3D/physics/physX/pxCasts.h" -#include "T3D/physics/physX/pxWorld.h" -#include "T3D/physics/physX/pxCollision.h" - - -PxBody::PxBody() : - mActor( NULL ), - mMaterial( NULL ), - mWorld( NULL ), - mBodyFlags( 0 ), - mIsEnabled( true ) -{ -} - -PxBody::~PxBody() -{ - _releaseActor(); -} - -void PxBody::_releaseActor() -{ - if ( !mActor ) - return; - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - - mActor->userData = NULL; - - mWorld->releaseActor( *mActor ); - mActor = NULL; - mBodyFlags = 0; - - if ( mMaterial ) - { - mWorld->releaseMaterial( *mMaterial ); - mMaterial = NULL; - } - - mColShape = NULL; -} - -bool PxBody::init( PhysicsCollision *shape, - F32 mass, - U32 bodyFlags, - SceneObject *obj, - PhysicsWorld *world ) -{ - AssertFatal( obj, "PxBody::init - Got a null scene object!" ); - AssertFatal( world, "PxBody::init - Got a null world!" ); - AssertFatal( dynamic_cast( world ), "PxBody::init - The world is the wrong type!" ); - AssertFatal( shape, "PxBody::init - Got a null collision shape!" ); - AssertFatal( dynamic_cast( shape ), "PxBody::init - The collision shape is the wrong type!" ); - AssertFatal( !((PxCollision*)shape)->getShapes().empty(), "PxBody::init - Got empty collision shape!" ); - - // Cleanup any previous actor. - _releaseActor(); - - mWorld = (PxWorld*)world; - mColShape = (PxCollision*)shape; - mBodyFlags = bodyFlags; - - NxActorDesc actorDesc; - NxBodyDesc bodyDesc; - - const bool isKinematic = mBodyFlags & BF_KINEMATIC; - const bool isTrigger = mBodyFlags & BF_TRIGGER; - const bool isDebris = mBodyFlags & BF_DEBRIS; - - if ( isKinematic ) - { - // Kinematics are dynamics... so they need - // a body description. - actorDesc.body = &bodyDesc; - bodyDesc.mass = getMax( mass, 1.0f ); - bodyDesc.flags |= NX_BF_KINEMATIC; - } - else if ( mass > 0.0f ) - { - // We have mass so its a dynamic. - actorDesc.body = &bodyDesc; - bodyDesc.mass = mass; - } - - if ( isTrigger ) - actorDesc.flags |= NX_AF_DISABLE_RESPONSE; - - // Add all the shapes. - const Vector &shapes = mColShape->getShapes(); - for ( U32 i=0; i < shapes.size(); i++ ) - { - NxShapeDesc *desc = shapes[i]; - - // If this hits then something is broken with - // this descrption... check all the fields to be - // sure their values are correctly filled out. - AssertFatal( desc->isValid(), "PxBody::init - Got invalid shape description!" ); - - if ( isTrigger ) - desc->group = 31; - - if ( isDebris ) - desc->group = 30; - - actorDesc.shapes.push_back( desc ); - } - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - - mActor = mWorld->getScene()->createActor( actorDesc ); - mIsEnabled = true; - - if ( isDebris ) - mActor->setDominanceGroup( 31 ); - - mUserData.setObject( obj ); - mUserData.setBody( this ); - mActor->userData = &mUserData; - - return true; -} - -void PxBody::setMaterial( F32 restitution, - F32 friction, - F32 staticFriction ) -{ - AssertFatal( mActor, "PxBody::setMaterial - The actor is null!" ); - - // If the body is dynamic then wake it up as - // it may need to change behavior. - if ( isDynamic() ) - mActor->wakeUp(); - - NxMaterialDesc desc; - desc.restitution = restitution; - desc.dynamicFriction = friction; - desc.staticFriction = staticFriction; - - // If we have a material then just update it as the shapes - // should already have them mapped. - if ( mMaterial ) - { - mMaterial->loadFromDesc( desc ); - return; - } - - // If we got here then create a new material and - // assign it to all our shapes. - mMaterial = mWorld->createMaterial( desc ); - U32 matIndex = mMaterial->getMaterialIndex(); - U32 count = mActor->getNbShapes(); - NxShape*const* shapes = mActor->getShapes(); - for ( U32 i=0; i < count; i++ ) - shapes[i]->setMaterial( matIndex ); -} - -void PxBody::setSleepThreshold( F32 linear, F32 angular ) -{ - AssertFatal( mActor, "PxBody::setSleepThreshold - The actor is null!" ); - - mActor->setSleepLinearVelocity( linear ); - mActor->setSleepAngularVelocity( angular ); -} - -void PxBody::setDamping( F32 linear, F32 angular ) -{ - AssertFatal( mActor, "PxBody::setDamping - The actor is null!" ); - mActor->setLinearDamping( linear ); - mActor->setAngularDamping( angular ); -} - -void PxBody::getState( PhysicsState *outState ) -{ - AssertFatal( mActor, "PxBody::getState - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::getState - This call is only for dynamics!" ); - - // TODO: Fix this to do what we intended... to return - // false so that the caller can early out of the state - // hasn't changed since the last tick. - - outState->position = pxCast( mActor->getGlobalPosition() ); - outState->orientation = pxCast( mActor->getGlobalOrientationQuat() ); - outState->linVelocity = pxCast( mActor->getLinearVelocity() ); - outState->angVelocity = pxCast( mActor->getAngularVelocity() ); - outState->sleeping = mActor->isSleeping(); - outState->momentum = pxCast( mActor->getLinearMomentum() ); -} - -F32 PxBody::getMass() const -{ - AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" ); - return mActor->getMass(); -} - -Point3F PxBody::getCMassPosition() const -{ - AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" ); - return pxCast( mActor->getCMassGlobalPosition() ); -} - -void PxBody::setLinVelocity( const Point3F &vel ) -{ - AssertFatal( mActor, "PxBody::setLinVelocity - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::setLinVelocity - This call is only for dynamics!" ); - - mActor->setLinearVelocity( pxCast( vel ) ); -} - -void PxBody::setAngVelocity( const Point3F &vel ) -{ - AssertFatal( mActor, "PxBody::setAngVelocity - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::setAngVelocity - This call is only for dynamics!" ); - - mActor->setAngularVelocity( pxCast( vel ) ); -} - -Point3F PxBody::getLinVelocity() const -{ - AssertFatal( mActor, "PxBody::getLinVelocity - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::getLinVelocity - This call is only for dynamics!" ); - - return pxCast( mActor->getLinearVelocity() ); -} - -Point3F PxBody::getAngVelocity() const -{ - AssertFatal( mActor, "PxBody::getAngVelocity - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::getAngVelocity - This call is only for dynamics!" ); - - return pxCast( mActor->getAngularVelocity() ); -} - -void PxBody::setSleeping( bool sleeping ) -{ - AssertFatal( mActor, "PxBody::setSleeping - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::setSleeping - This call is only for dynamics!" ); - - if ( sleeping ) - mActor->putToSleep(); - else - mActor->wakeUp(); -} - -bool PxBody::isDynamic() const -{ - AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" ); - return mActor->isDynamic() && ( mBodyFlags & BF_KINEMATIC ) == 0; -} - -PhysicsWorld* PxBody::getWorld() -{ - return mWorld; -} - -PhysicsCollision* PxBody::getColShape() -{ - return mColShape; -} - -MatrixF& PxBody::getTransform( MatrixF *outMatrix ) -{ - AssertFatal( mActor, "PxBody::getTransform - The actor is null!" ); - - mActor->getGlobalPose().getRowMajor44( *outMatrix ); - - return *outMatrix; -} - -Box3F PxBody::getWorldBounds() -{ - AssertFatal( mActor, "PxBody::getTransform - The actor is null!" ); - - NxBounds3 bounds; - bounds.setEmpty(); - NxBounds3 shapeBounds; - - NxShape *const* pShapeArray = mActor->getShapes(); - U32 shapeCount = mActor->getNbShapes(); - - for ( U32 i = 0; i < shapeCount; i++ ) - { - // Get the shape's bounds. - pShapeArray[i]->getWorldBounds( shapeBounds ); - - // Combine them into the total bounds. - bounds.combine( shapeBounds ); - } - - return pxCast( bounds ); -} - -void PxBody::setSimulationEnabled( bool enabled ) -{ - if ( mIsEnabled == enabled ) - return; - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - - if ( enabled ) - { - mIsEnabled = true; - mActor->clearActorFlag( NX_AF_DISABLE_RESPONSE ); - mActor->clearActorFlag( NX_AF_DISABLE_COLLISION ); - - // Don't clear the flag if its supposed to be kinematic. - if ( !(mBodyFlags & BF_KINEMATIC) ) - mActor->clearBodyFlag( NX_BF_KINEMATIC ); - - if ( isDynamic() ) - mActor->wakeUp(); - } - else - { - mIsEnabled = false; - mActor->raiseActorFlag( NX_AF_DISABLE_RESPONSE ); - mActor->raiseActorFlag( NX_AF_DISABLE_COLLISION ); - mActor->raiseBodyFlag( NX_BF_KINEMATIC ); - } - - NxShape *const* shapes = mActor->getShapes(); - for ( S32 i = 0; i < mActor->getNbShapes(); i++ ) - shapes[i]->setFlag( NX_SF_DISABLE_RAYCASTING, !mIsEnabled ); -} - -void PxBody::setTransform( const MatrixF &transform ) -{ - AssertFatal( mActor, "PxBody::setTransform - The actor is null!" ); - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - - NxMat34 xfm; - xfm.setRowMajor44( transform ); - mActor->setGlobalPose( xfm ); - - // If its dynamic we have more to do. - if ( mActor->isDynamic() && !mActor->readBodyFlag( NX_BF_KINEMATIC ) ) - { - mActor->setLinearVelocity( NxVec3( 0, 0, 0 ) ); - mActor->setAngularVelocity( NxVec3( 0, 0, 0 ) ); - mActor->wakeUp(); - } -} - -void PxBody::applyCorrection( const MatrixF &transform ) -{ - AssertFatal( mActor, "PxBody::applyCorrection - The actor is null!" ); - AssertFatal( isDynamic(), "PxBody::applyCorrection - This call is only for dynamics!" ); - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - - NxMat34 xfm; - xfm.setRowMajor44( transform ); - mActor->setGlobalPose( xfm ); -} - -void PxBody::applyImpulse( const Point3F &origin, const Point3F &force ) -{ - AssertFatal( mActor, "PxBody::applyImpulse - The actor is null!" ); - - // This sucks, but it has to happen if we want - // to avoid write lock errors from PhysX right now. - mWorld->releaseWriteLock(); - - if ( mIsEnabled && isDynamic() ) - mActor->addForceAtPos( pxCast( force ), - pxCast( origin ), - NX_IMPULSE ); -} - diff --git a/Engine/source/T3D/physics/physx/pxBody.h b/Engine/source/T3D/physics/physx/pxBody.h deleted file mode 100644 index 2aeec6e0f..000000000 --- a/Engine/source/T3D/physics/physx/pxBody.h +++ /dev/null @@ -1,114 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _T3D_PHYSICS_PXBODY_H_ -#define _T3D_PHYSICS_PXBODY_H_ - -#ifndef _T3D_PHYSICS_PHYSICSBODY_H_ -#include "T3D/physics/physicsBody.h" -#endif -#ifndef _PHYSICS_PHYSICSUSERDATA_H_ -#include "T3D/physics/physicsUserData.h" -#endif -#ifndef _REFBASE_H_ -#include "core/util/refBase.h" -#endif -#ifndef _MMATRIX_H_ -#include "math/mMatrix.h" -#endif - -class PxWorld; -class NxActor; -class PxCollision; -class NxMaterial; - - -class PxBody : public PhysicsBody -{ -protected: - - /// The physics world we are in. - PxWorld *mWorld; - - /// The physics actor. - NxActor *mActor; - - /// The unshared local material used on all the - /// shapes on this actor. - NxMaterial *mMaterial; - - /// We hold the collision reference as it contains - /// allocated objects that we own and must free. - StrongRefPtr mColShape; - - /// - MatrixF mInternalTransform; - - /// The body flags set at creation time. - U32 mBodyFlags; - - /// Is true if this body is enabled and active - /// in the simulation of the scene. - bool mIsEnabled; - - /// - void _releaseActor(); - -public: - - PxBody(); - virtual ~PxBody(); - - // PhysicsObject - virtual PhysicsWorld* getWorld(); - virtual void setTransform( const MatrixF &xfm ); - virtual MatrixF& getTransform( MatrixF *outMatrix ); - virtual Box3F getWorldBounds(); - virtual void setSimulationEnabled( bool enabled ); - virtual bool isSimulationEnabled() { return mIsEnabled; } - - // PhysicsBody - virtual bool init( PhysicsCollision *shape, - F32 mass, - U32 bodyFlags, - SceneObject *obj, - PhysicsWorld *world ); - virtual bool isDynamic() const; - virtual PhysicsCollision* getColShape(); - virtual void setSleepThreshold( F32 linear, F32 angular ); - virtual void setDamping( F32 linear, F32 angular ); - virtual void getState( PhysicsState *outState ); - virtual F32 getMass() const; - virtual Point3F getCMassPosition() const; - virtual void setLinVelocity( const Point3F &vel ); - virtual void setAngVelocity( const Point3F &vel ); - virtual Point3F getLinVelocity() const; - virtual Point3F getAngVelocity() const; - virtual void setSleeping( bool sleeping ); - virtual void setMaterial( F32 restitution, - F32 friction, - F32 staticFriction ); - virtual void applyCorrection( const MatrixF &xfm ); - virtual void applyImpulse( const Point3F &origin, const Point3F &force ); -}; - -#endif // _T3D_PHYSICS_PXBODY_H_ diff --git a/Engine/source/T3D/physics/physx/pxCasts.h b/Engine/source/T3D/physics/physx/pxCasts.h deleted file mode 100644 index ee9555702..000000000 --- a/Engine/source/T3D/physics/physx/pxCasts.h +++ /dev/null @@ -1,150 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PHYSX_CASTS_H_ -#define _PHYSX_CASTS_H_ - -#ifndef _MPOINT3_H_ -#include "math/mPoint3.h" -#endif -#ifndef _MBOX_H_ -#include "math/mBox.h" -#endif -#ifndef _MQUAT_H_ -#include "math/mQuat.h" -#endif - - -template inline T pxCast( const F &from ); - -//------------------------------------------------------------------------- - -template<> -inline Point3F pxCast( const NxVec3 &vec ) -{ - return Point3F( vec.x, vec.y, vec.z ); -} - -template<> -inline NxVec3 pxCast( const Point3F &point ) -{ - return NxVec3( point.x, point.y, point.z ); -} - -//------------------------------------------------------------------------- - -template<> -inline QuatF pxCast( const NxQuat &quat ) -{ - /// The Torque quat has the opposite winding order. - return QuatF( -quat.x, -quat.y, -quat.z, quat.w ); -} - -template<> -inline NxQuat pxCast( const QuatF &quat ) -{ - /// The Torque quat has the opposite winding order. - NxQuat result; - result.setWXYZ( quat.w, -quat.x, -quat.y, -quat.z ); - return result; -} - -//------------------------------------------------------------------------- - -template<> -inline NxBounds3 pxCast( const Box3F &box ) -{ - NxBounds3 bounds; - bounds.set( box.minExtents.x, - box.minExtents.y, - box.minExtents.z, - box.maxExtents.x, - box.maxExtents.y, - box.maxExtents.z ); - return bounds; -} - -template<> -inline Box3F pxCast( const NxBounds3 &bounds ) -{ - return Box3F( bounds.min.x, - bounds.min.y, - bounds.min.z, - bounds.max.x, - bounds.max.y, - bounds.max.z ); -} - -//------------------------------------------------------------------------- - -template<> -inline NxVec3 pxCast( const NxExtendedVec3 &xvec ) -{ - return NxVec3( xvec.x, xvec.y, xvec.z ); -} - -template<> -inline NxExtendedVec3 pxCast( const NxVec3 &vec ) -{ - return NxExtendedVec3( vec.x, vec.y, vec.z ); -} - -//------------------------------------------------------------------------- - -template<> -inline NxExtendedVec3 pxCast( const Point3F &point ) -{ - return NxExtendedVec3( point.x, point.y, point.z ); -} - -template<> -inline Point3F pxCast( const NxExtendedVec3 &xvec ) -{ - return Point3F( xvec.x, xvec.y, xvec.z ); -} - -//------------------------------------------------------------------------- - -template<> -inline NxBox pxCast( const NxExtendedBounds3 &exBounds ) -{ - NxExtendedVec3 center; - exBounds.getCenter( center ); - NxVec3 extents; - exBounds.getExtents( extents ); - - NxBox box; - box.center.set( center.x, center.y, center.z ); - box.extents = extents; - box.rot.id(); - - return box; -} - -template<> -inline NxExtendedBounds3 pxCast( const NxBox &box ) -{ - AssertFatal( false, "Casting a NxBox to NxExtendedBounds3 is impossible without losing rotation data!" ); - return NxExtendedBounds3(); -} - -#endif // _PHYSX_CASTS_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxCloth.cpp b/Engine/source/T3D/physics/physx/pxCloth.cpp deleted file mode 100644 index 723e71b67..000000000 --- a/Engine/source/T3D/physics/physx/pxCloth.cpp +++ /dev/null @@ -1,923 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxCloth.h" - -#include "console/consoleTypes.h" -#include "scene/sceneManager.h" -#include "scene/sceneRenderState.h" -#include "renderInstance/renderPassManager.h" -#include "lighting/lightQuery.h" -#include "T3D/physics/physicsPlugin.h" -#include "T3D/physics/physx/pxWorld.h" -#include "T3D/physics/physx/pxStream.h" -#include "T3D/physics/physx/pxCasts.h" -#include "gfx/gfxDrawUtil.h" -#include "math/mathIO.h" -#include "core/stream/bitStream.h" -#include "materials/materialManager.h" -#include "materials/baseMatInstance.h" - - -IMPLEMENT_CO_NETOBJECT_V1( PxCloth ); - -ConsoleDocClass( PxCloth, - - "@brief Rectangular patch of cloth simulated by PhysX.\n\n" - - "PxCloth is affected by other objects in the simulation but does not itself " - "affect others, it is essentially a visual effect. Eg, shooting at cloth will " - "disturb it but will not explode the projectile.\n\n" - - "Be careful with the cloth size and resolution because it can easily become " - "performance intensive to simulate. A single piece of cloth that is very " - "large or high resolution is also much more expensive than multiple pieces " - "that add up to the same number of verts.\n\n" - - "Note that most field docs have been copied from their PhysX counterpart.\n\n" - - "@ingroup Physics" -); - -enum PxClothAttachment {}; -DefineBitfieldType( PxClothAttachment ); - -ImplementBitfieldType( PxClothAttachment, - "Soon to be deprecated\n" - "@internal" ) - { 0, "Bottom Right" }, - { 1, "Bottom Left" }, - { 2, "Top Right" }, - { 3, "Top Left" }, - { 4, "Top Center" }, - { 5, "Bottom Center" }, - { 6, "Right Center" }, - { 7, "Left Center" }, - { 8, "Top Edge" }, - { 9, "Bottom Edge" }, - { 10, "Right Edge" }, - { 11, "Left Edge" } -EndImplementBitfieldType; - - -PxCloth::PxCloth() - : mWorld( NULL ), - mScene( NULL ), - mMatInst( NULL ) -{ - mVertexRenderBuffer = NULL; - mIndexRenderBuffer = NULL; - - mMaxVertices = 0; - mMaxIndices = 0; - - mClothMesh = NULL; - mCloth = NULL; - - mPatchVerts.set( 8, 8 ); - mPatchSize.set( 8.0f, 8.0f ); - - mNetFlags.set( Ghostable | ScopeAlways ); - mTypeMask |= StaticObjectType | StaticShapeObjectType; - - mReceiveBuffers.setToDefault(); - - mBendingEnabled = false; - mDampingEnabled = false; - mTriangleCollisionEnabled = false; - mSelfCollisionEnabled = false; - - mDensity = 1.0f; - mThickness = 0.1f; - mFriction = 0.25f; - mBendingStiffness = 0.5f; - mDampingCoefficient = 0.25f; - - mAttachmentMask = 0; -} - -PxCloth::~PxCloth() -{ -} - -bool PxCloth::onAdd() -{ - if ( !Parent::onAdd() ) - return false; - - // Cloth is only created on the client. - if ( isClientObject() ) - { - mWorld = dynamic_cast( PHYSICSMGR->getWorld( "client" ) ); - - if ( !mWorld || !mWorld->getScene() ) - { - Con::errorf( "PxCloth::onAdd() - PhysXWorld not initialized... cloth disabled!" ); - return true; - } - - mScene = mWorld->getScene(); - - mResetXfm = getTransform(); - - _createClothPatch(); - - PhysicsPlugin::getPhysicsResetSignal().notify( this, &PxCloth::onPhysicsReset, 1053.0f ); - } - - // On the server we use the static update - // to setup the bounds of the cloth. - if ( isServerObject() ) - _updateStaticCloth(); - - addToScene(); - - // Also the server object never ticks. - if ( isServerObject() ) - setProcessTick( false ); - - return true; -} - -void PxCloth::onRemove() -{ - SAFE_DELETE( mMatInst ); - - if ( isClientObject() ) - { - _releaseCloth(); - _releaseMesh(); - - PhysicsPlugin::getPhysicsResetSignal().remove( this, &PxCloth::onPhysicsReset ); - } - - removeFromScene(); - - Parent::onRemove(); -} - -void PxCloth::onPhysicsReset( PhysicsResetEvent reset ) -{ - // Store the reset transform for later use. - if ( reset == PhysicsResetEvent_Store ) - mResetXfm = getTransform(); - - // Recreate the cloth at the last reset position. - _recreateCloth( mResetXfm ); -} - -void PxCloth::initPersistFields() -{ - Parent::initPersistFields(); - - addField( "material", TypeMaterialName, Offset( mMaterialName, PxCloth ), - "@brief Name of the material to render.\n\n" ); - - addField( "samples", TypePoint2I, Offset( mPatchVerts, PxCloth ), - "@brief The number of cloth vertices in width and length.\n\n" - "At least two verts should be defined.\n\n"); - - addField( "size", TypePoint2F, Offset( mPatchSize, PxCloth ), - "@brief The width and height of the cloth.\n\n" ); - - addField( "bending", TypeBool, Offset( mBendingEnabled, PxCloth ), - "@brief Enables or disables bending resistance.\n\n" - "Set the bending resistance through PxCloth::bendingStiffness." ); - - addField( "damping", TypeBool, Offset( mDampingEnabled, PxCloth ), - "@brief Enable/disable damping of internal velocities.\n\n" ); - - addField( "triangleCollision", TypeBool, Offset( mTriangleCollisionEnabled, PxCloth ), - "@brief Not supported in current release (according to PhysX docs).\n\n" - "Enables or disables collision detection of cloth triangles against the scene. " - "If not set, only collisions of cloth particles are detected. If set, " - "collisions of cloth triangles are detected as well." ); - - addField( "selfCollision", TypeBool, Offset( mSelfCollisionEnabled, PxCloth ), - "@brief Enables or disables self-collision handling within a single piece of cloth.\n\n" ); - - addField( "density", TypeF32, Offset( mDensity, PxCloth ), - "@brief Density of the cloth (Mass per Area).\n\n" ); - - addField( "thickness", TypeF32, Offset( mThickness, PxCloth ), - "@brief Value representing how thick the cloth is.\n\n" - "The thickness is usually a fraction of the overall extent of the cloth and " - "should not be set to a value greater than that. A good value is the maximal " - "distance between two adjacent cloth particles in their rest pose. Visual " - "artifacts or collision problems may appear if the thickness is too small.\n\n" ); - - addField( "friction", TypeF32, Offset( mFriction, PxCloth ), - "@brief Friction coefficient in the range 0 to 1.\n\n" - "Defines the damping of the velocities of cloth particles that are in contact." ); - - addField( "bendingStiffness", TypeF32, Offset( mBendingStiffness, PxCloth ), - "@brief Bending stiffness of the cloth in the range 0 to 1.\n\n" ); - - addField( "dampingCoefficient", TypeF32, Offset( mDampingCoefficient, PxCloth ), - "@brief Spring damping of the cloth in the range 0 to 1.\n\n" ); - - addField( "attachments", TYPEID< PxClothAttachment >(), Offset( mAttachmentMask, PxCloth ), - "@brief Optional way to specify cloth verts that will be attached to the world position " - "it is created at.\n\n" ); - - // Cloth doesn't support scale. - removeField( "scale" ); -} - -void PxCloth::inspectPostApply() -{ - Parent::inspectPostApply(); - - // Must have at least 2 verts. - mPatchVerts.x = getMax( 2, mPatchVerts.x ); - mPatchVerts.y = getMax( 2, mPatchVerts.y ); - if ( isServerObject() ) - _updateStaticCloth(); - - setMaskBits( TransformMask | MaterialMask | ClothMask ); -} - -U32 PxCloth::packUpdate( NetConnection *conn, U32 mask, BitStream *stream ) -{ - U32 retMask = Parent::packUpdate( conn, mask, stream ); - - if ( stream->writeFlag( mask & TransformMask ) ) - mathWrite( *stream, getTransform() ); - - if ( stream->writeFlag( mask & MaterialMask ) ) - stream->write( mMaterialName ); - - if ( stream->writeFlag( mask & ClothMask ) ) - { - mathWrite( *stream, mPatchVerts ); - mathWrite( *stream, mPatchSize ); - - stream->write( mAttachmentMask ); - - stream->writeFlag( mBendingEnabled ); - stream->writeFlag( mDampingEnabled ); - stream->writeFlag( mTriangleCollisionEnabled ); - stream->writeFlag( mSelfCollisionEnabled ); - stream->write( mThickness ); - stream->write( mFriction ); - stream->write( mBendingStiffness ); - stream->write( mDampingCoefficient ); - - stream->write( mDensity ); - } - - return retMask; -} - -void PxCloth::unpackUpdate( NetConnection *conn, BitStream *stream ) -{ - Parent::unpackUpdate( conn, stream ); - - // TransformMask - if ( stream->readFlag() ) - { - MatrixF mat; - mathRead( *stream, &mat ); - setTransform( mat ); - } - - // MaterialMask - if ( stream->readFlag() ) - { - stream->read( &mMaterialName ); - SAFE_DELETE( mMatInst ); - } - - // ClothMask - if ( stream->readFlag() ) - { - Point2I patchVerts; - Point2F patchSize; - mathRead( *stream, &patchVerts ); - mathRead( *stream, &patchSize ); - - if ( patchVerts != mPatchVerts || - !patchSize.equal( mPatchSize ) ) - { - mPatchVerts = patchVerts; - mPatchSize = patchSize; - _releaseMesh(); - } - - U32 attachMask; - stream->read( &attachMask ); - if ( attachMask != mAttachmentMask ) - { - mAttachmentMask = attachMask; - _releaseCloth(); - } - - mBendingEnabled = stream->readFlag(); - mDampingEnabled = stream->readFlag(); - mTriangleCollisionEnabled = stream->readFlag(); - mSelfCollisionEnabled = stream->readFlag(); - stream->read( &mThickness ); - stream->read( &mFriction ); - stream->read( &mBendingStiffness ); - stream->read( &mDampingCoefficient ); - - F32 density; - stream->read( &density ); - if ( density != mDensity ) - { - mDensity = density; - _releaseCloth(); - } - - if ( isClientObject() && - isProperlyAdded() && - mWorld && - !mCloth ) - { - _createClothPatch(); - } - - _updateClothProperties(); - } -} - -void PxCloth::_recreateCloth( const MatrixF &transform ) -{ - if ( !mWorld ) - return; - - mWorld->getPhysicsResults(); - - Parent::setTransform( transform ); - - _createClothPatch(); -} - -void PxCloth::setTransform( const MatrixF &mat ) -{ - Parent::setTransform( mat ); - setMaskBits( TransformMask ); - - // Only need to do this if we're on the server - // or if we're not currently ticking physics. - if ( !mWorld || !mWorld->isEnabled() ) - _updateStaticCloth(); -} - -void PxCloth::setScale( const VectorF &scale ) -{ - // Cloth doesn't support scale as it has plenty - // of complications... sharing meshes, thickness, - // transform origin, etc. - return; -} - -void PxCloth::prepRenderImage( SceneRenderState *state ) -{ - if ( mIsVBDirty ) - _updateVBIB(); - - // Recreate the material if we need to. - if ( !mMatInst ) - _initMaterial(); - - // If we don't have a material instance after the override then - // we can skip rendering all together. - BaseMatInstance *matInst = state->getOverrideMaterial( mMatInst ); - if ( !matInst ) - return; - - MeshRenderInst *ri = state->getRenderPass()->allocInst(); - - // If we need lights then set them up. - if ( matInst->isForwardLit() ) - { - LightQuery query; - query.init( getWorldSphere() ); - query.getLights( ri->lights, 8 ); - } - - ri->projection = state->getRenderPass()->allocSharedXform(RenderPassManager::Projection); - ri->objectToWorld = &MatrixF::Identity; - - ri->worldToCamera = state->getRenderPass()->allocSharedXform(RenderPassManager::View); - ri->type = RenderPassManager::RIT_Mesh; - - ri->primBuff = &mPrimBuffer; - ri->vertBuff = &mVB; - - ri->matInst = matInst; - ri->prim = state->getRenderPass()->allocPrim(); - ri->prim->type = GFXTriangleList; - ri->prim->minIndex = 0; - ri->prim->startIndex = 0; - ri->prim->numPrimitives = mNumIndices / 3; - - ri->prim->startVertex = 0; - ri->prim->numVertices = mNumVertices; - - ri->defaultKey = matInst->getStateHint(); - ri->defaultKey2 = (U32)ri->vertBuff; - - state->getRenderPass()->addInst( ri ); -} - -void PxCloth::_releaseMesh() -{ - if ( !mClothMesh ) - return; - - _releaseCloth(); - - mWorld->releaseClothMesh( *mClothMesh ); - mClothMesh = NULL; - - delete [] mVertexRenderBuffer; - mVertexRenderBuffer = NULL; - delete [] mIndexRenderBuffer; - mIndexRenderBuffer = NULL; -} - -void PxCloth::_releaseCloth() -{ - if ( !mCloth ) - return; - - mWorld->releaseCloth( *mCloth ); - mCloth = NULL; -} - -void PxCloth::_initClothMesh() -{ - // Make sure we can change the world. - mWorld->releaseWriteLock(); - - _releaseMesh(); - - // Must have at least 2 verts. - mPatchVerts.x = getMax( 2, mPatchVerts.x ); - mPatchVerts.y = getMax( 2, mPatchVerts.y ); - - // Generate a uniform cloth patch, - // w and h are the width and height, - // d is the distance between vertices. - mNumVertices = mPatchVerts.x * mPatchVerts.y; - mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2; - - NxClothMeshDesc desc; - desc.numVertices = mNumVertices; - desc.numTriangles = mNumIndices; - desc.pointStrideBytes = sizeof(NxVec3); - desc.triangleStrideBytes = 3*sizeof(NxU32); - desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices); - desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3); - desc.flags = 0; - - U32 i,j; - NxVec3 *p = (NxVec3*)desc.points; - - F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 ); - F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 ); - - for (i = 0; i < mPatchVerts.y; i++) - { - for (j = 0; j < mPatchVerts.x; j++) - { - p->set( patchWidth * j, 0.0f, patchHeight * i ); - p++; - } - } - - NxU32 *id = (NxU32*)desc.triangles; - - for (i = 0; i < mPatchVerts.y-1; i++) - { - for (j = 0; j < mPatchVerts.x-1; j++) - { - NxU32 i0 = i * mPatchVerts.x + j; - NxU32 i1 = i0 + 1; - NxU32 i2 = i0 + mPatchVerts.x; - NxU32 i3 = i2 + 1; - if ( (j+i) % 2 ) - { - *id++ = i0; - *id++ = i2; - *id++ = i1; - *id++ = i1; - *id++ = i2; - *id++ = i3; - } - else - { - *id++ = i0; - *id++ = i2; - *id++ = i3; - *id++ = i0; - *id++ = i3; - *id++ = i1; - } - } - } - - NxCookingInterface *cooker = PxWorld::getCooking(); - cooker->NxInitCooking(); - - // Ok... cook the mesh! - NxCookingParams params; - params.targetPlatform = PLATFORM_PC; - params.skinWidth = 0.01f; - params.hintCollisionSpeed = false; - - cooker->NxSetCookingParams( params ); - - PxMemStream cooked; - - if ( cooker->NxCookClothMesh( desc, cooked ) ) - { - cooked.resetPosition(); - mClothMesh = gPhysicsSDK->createClothMesh( cooked ); - } - - cooker->NxCloseCooking(); - - NxVec3 *ppoints = (NxVec3*)desc.points; - NxU32 *triangs = (NxU32*)desc.triangles; - - dFree( ppoints ); - dFree( triangs ); - - if ( mClothMesh ) - _initReceiveBuffers(); -} - -void PxCloth::_initReceiveBuffers() -{ - // here we setup the buffers through which the SDK returns the dynamic cloth data - // we reserve more memory for vertices than the initial mesh takes - // because tearing creates new vertices - // the SDK only tears cloth as long as there is room in these buffers - - mMaxVertices = 3 * mNumVertices; - mMaxIndices = 3 * mNumIndices; - - // Allocate Render Buffer for Vertices if it hasn't been done before - mVertexRenderBuffer = new GFXVertexPNTT[mMaxVertices]; - mIndexRenderBuffer = new U16[mMaxIndices]; - - mReceiveBuffers.verticesPosBegin = &(mVertexRenderBuffer[0].point); - mReceiveBuffers.verticesNormalBegin = &(mVertexRenderBuffer[0].normal); - mReceiveBuffers.verticesPosByteStride = sizeof(GFXVertexPNTT); - mReceiveBuffers.verticesNormalByteStride = sizeof(GFXVertexPNTT); - mReceiveBuffers.maxVertices = mMaxVertices; - mReceiveBuffers.numVerticesPtr = &mNumVertices; - - // the number of triangles is constant, even if the cloth is torn - mReceiveBuffers.indicesBegin = &mIndexRenderBuffer[0]; - mReceiveBuffers.indicesByteStride = sizeof(NxU16); - mReceiveBuffers.maxIndices = mMaxIndices; - mReceiveBuffers.numIndicesPtr = &mNumIndices; - - // Set up texture coords. - - F32 dx = 1.0f / (F32)(mPatchVerts.x-1); - F32 dy = 1.0f / (F32)(mPatchVerts.y-1); - - F32 *coord = (F32*)&mVertexRenderBuffer[0].texCoord; - for ( U32 i = 0; i < mPatchVerts.y; i++) - { - for ( U32 j = 0; j < mPatchVerts.x; j++) - { - coord[0] = j*dx; - coord[1] = i*-dy; - coord += sizeof( GFXVertexPNTT ) / sizeof( F32 ); - } - } - - // the parent index information would be needed if we used textured cloth - //mReceiveBuffers.parentIndicesBegin = (U32*)malloc(sizeof(U32)*mMaxVertices); - //mReceiveBuffers.parentIndicesByteStride = sizeof(U32); - //mReceiveBuffers.maxParentIndices = mMaxVertices; - //mReceiveBuffers.numParentIndicesPtr = &mNumParentIndices; - - mMeshDirtyFlags = 0; - mReceiveBuffers.dirtyBufferFlagsPtr = &mMeshDirtyFlags; - - // init the buffers in case we want to draw the mesh - // before the SDK as filled in the correct values - - mReceiveBuffers.flags |= NX_MDF_16_BIT_INDICES; -} - -bool PxCloth::_createClothPatch() -{ - // Make sure we have a mesh. - if ( !mClothMesh ) - { - _initClothMesh(); - if ( !mClothMesh ) - return false; - } - - // Make sure we can change the world. - mWorld->releaseWriteLock(); - - _releaseCloth(); - - NxClothDesc desc; - desc.globalPose.setRowMajor44( getTransform() ); - desc.thickness = mThickness; - desc.density = mDensity; - desc.bendingStiffness = mBendingStiffness; - desc.dampingCoefficient = mDampingCoefficient; - desc.friction = mFriction; - - if ( mBendingEnabled ) - desc.flags |= NX_CLF_BENDING; - if ( mDampingEnabled ) - desc.flags |= NX_CLF_DAMPING; - if ( mTriangleCollisionEnabled ) - desc.flags |= NX_CLF_TRIANGLE_COLLISION; - if ( mSelfCollisionEnabled ) - desc.flags |= NX_CLF_SELFCOLLISION; - - desc.clothMesh = mClothMesh; - desc.meshData = mReceiveBuffers; - - if ( !desc.isValid() ) - return false; - - mCloth = mScene->createCloth( desc ); - mIsVBDirty = true; - - _updateStaticCloth(); - _setupAttachments(); - - return true; -} - -void PxCloth::_updateClothProperties() -{ - if ( !mCloth ) - return; - - mCloth->setThickness( mThickness ); - mCloth->setBendingStiffness( mBendingStiffness ); - mCloth->setDampingCoefficient( mDampingCoefficient ); - mCloth->setFriction( mFriction ); - - NxU32 flags = NX_CLF_GRAVITY; // TODO: Expose this? - if ( mBendingEnabled ) - flags |= NX_CLF_BENDING; - if ( mDampingEnabled ) - flags |= NX_CLF_DAMPING; - if ( mTriangleCollisionEnabled ) - flags |= NX_CLF_TRIANGLE_COLLISION; - if ( mSelfCollisionEnabled ) - flags |= NX_CLF_SELFCOLLISION; - mCloth->setFlags( flags ); -} - -void PxCloth::_initMaterial() -{ - SAFE_DELETE( mMatInst ); - - Material *material = NULL; - if (mMaterialName.isNotEmpty() ) - Sim::findObject( mMaterialName, material ); - - if ( material ) - mMatInst = material->createMatInstance(); - else - mMatInst = MATMGR->createMatInstance( "WarningMaterial" ); - - GFXStateBlockDesc desc; - desc.setCullMode( GFXCullNone ); - mMatInst->addStateBlockDesc( desc ); - - mMatInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat() ); -} - -void PxCloth::_updateVBIB() -{ - PROFILE_SCOPE( PxCloth_UpdateVBIB ); - - mIsVBDirty = false; - - // Don't set the VB if the vertex count is the same! - if ( mVB.isNull() || mVB->mNumVerts < mNumVertices ) - mVB.set( GFX, mNumVertices, GFXBufferTypeDynamic ); - - GFXVertexPNTT *vert = mVertexRenderBuffer; - GFXVertexPNTT *secondVert = NULL; - - for ( U32 i = 0; i < mNumVertices; i++ ) - { - if ( i % (U32)mPatchSize.x == 0 && i != 0 ) - { - secondVert = vert; - secondVert--; - vert->tangent = -(vert->point - secondVert->point); - } - else - { - secondVert = vert; - secondVert++; - vert->tangent = vert->point - secondVert->point; - } - - vert->tangent.normalize(); - vert++; - } - - GFXVertexPNTT *vpPtr = mVB.lock(); - dMemcpy( vpPtr, mVertexRenderBuffer, sizeof( GFXVertexPNTT ) * mNumVertices ); - mVB.unlock(); - - if ( mPrimBuffer.isNull() || mPrimBuffer->mIndexCount < mNumIndices ) - mPrimBuffer.set( GFX, mNumIndices, 0, GFXBufferTypeDynamic ); - - U16 *pbPtr; - mPrimBuffer.lock( &pbPtr ); - dMemcpy( pbPtr, mIndexRenderBuffer, sizeof( U16 ) * mNumIndices ); - mPrimBuffer.unlock(); -} - -void PxCloth::_updateStaticCloth() -{ - // Setup the unsimulated world bounds. - mObjBox.set( 0, mThickness * -0.5f, 0, - mPatchSize.x, mThickness * 0.5f, mPatchSize.y ); - resetWorldBox(); - - // If we don't have render buffers then we're done. - if ( !mVertexRenderBuffer || !mIndexRenderBuffer ) - return; - - // Make sure the VBs are updated. - mIsVBDirty = true; - - F32 patchWidth = mPatchSize.x / (F32)(mPatchVerts.x-1); - F32 patchHeight = mPatchSize.y / (F32)(mPatchVerts.y-1); - - Point3F normal( 0, 1, 0 ); - getTransform().mulV( normal ); - - GFXVertexPNTT *vert = mVertexRenderBuffer; - - for (U32 y = 0; y < mPatchVerts.y; y++) - { - for (U32 x = 0; x < mPatchVerts.x; x++) - { - vert->point.set( patchWidth * x, 0.0f, patchHeight * y ); - getTransform().mulP( vert->point ); - vert->normal = normal; - vert++; - } - } - - U16 *index = mIndexRenderBuffer; - mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 6; - U16 yOffset = mPatchVerts.x; - - for (U32 y = 0; y < mPatchVerts.y-1; y++) - { - for (U32 x = 0; x < mPatchVerts.x-1; x++) - { - U16 base = x + ( yOffset * y ); - - index[0] = base; - index[1] = base + 1; - index[2] = base + 1 + yOffset; - - index[3] = base + 1 + yOffset; - index[4] = base + yOffset; - index[5] = base; - - index += 6; - } - } -} - -void PxCloth::processTick( const Move *move ) -{ - // Make sure the cloth is created. - if ( !mCloth ) - return; - - // TODO: Remove this hack! - const bool enableWind = Con::getBoolVariable( "$PxCloth::enableWind", false ); - - if ( enableWind ) - { - NxVec3 windVec( 25.0f + NxMath::rand(-5.0f, 5.0f), - NxMath::rand(-5.0f, 5.0f), - NxMath::rand(-5.0f, 5.0f) ); - - mCloth->setWindAcceleration( windVec ); - - // Wake the cloth! - mCloth->wakeUp(); - } - else - mCloth->setWindAcceleration( NxVec3( 0, 0, 0 ) ); - - // Update bounds. - if ( mWorld->getEnabled() ) - { - NxBounds3 box; - mCloth->getWorldBounds( box ); - - Point3F min = pxCast( box.min ); - Point3F max = pxCast( box.max ); - - mWorldBox.set( min, max ); - mObjBox = mWorldBox; - - getWorldTransform().mul( mObjBox ); - } - else - { - mObjBox.set( 0, mThickness * -0.5f, 0, - mPatchSize.x, mThickness * 0.5f, mPatchSize.y ); - } - - resetWorldBox(); - - // Update the VB on the next render. - mIsVBDirty = true; -} - -void PxCloth::interpolateTick( F32 delta ) -{ - // Nothing to do for now! -} - -bool PxCloth::onNewDataBlock( GameBaseData *dptr, bool reload ) -{ - return false; -} - -void PxCloth::_setupAttachments() -{ - if ( !mCloth || !mWorld ) - return; - - // Set up attachments - // Bottom right = bit 0 - // Bottom left = bit 1 - // Top right = bit 2 - // Top left = bit 3 - - if ( mAttachmentMask & BIT( 0 ) ) - mCloth->attachVertexToGlobalPosition( 0, mCloth->getPosition( 0 ) ); - if ( mAttachmentMask & BIT( 1 ) ) - mCloth->attachVertexToGlobalPosition( mPatchVerts.x-1, mCloth->getPosition( mPatchVerts.x-1 ) ); - if ( mAttachmentMask & BIT( 2 ) ) - mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x ) ); - if ( mAttachmentMask & BIT( 3 ) ) - mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - 1, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - 1 ) ); - if ( mAttachmentMask & BIT( 4 ) ) - mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2), mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2) ) ); - if ( mAttachmentMask & BIT( 5 ) ) - mCloth->attachVertexToGlobalPosition( (mPatchVerts.x/2), mCloth->getPosition( (mPatchVerts.x/2) ) ); - if ( mAttachmentMask & BIT( 6 ) ) - mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) ) ); - if ( mAttachmentMask & BIT( 7 ) ) - mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1) ) ); - - if ( mAttachmentMask & BIT( 8 ) ) - for ( U32 i = mPatchVerts.x * mPatchVerts.y - mPatchVerts.x; i < mPatchVerts.x * mPatchVerts.y; i++ ) - mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) ); - - if ( mAttachmentMask & BIT( 9 ) ) - for ( U32 i = 0; i < mPatchVerts.x; i++ ) - mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) ); - - if ( mAttachmentMask & BIT( 10 ) ) - for ( U32 i = 0; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x ) - mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) ); - - if ( mAttachmentMask & BIT( 11 ) ) - for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x ) - mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) ); -} \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxCloth.h b/Engine/source/T3D/physics/physx/pxCloth.h deleted file mode 100644 index 5df158861..000000000 --- a/Engine/source/T3D/physics/physx/pxCloth.h +++ /dev/null @@ -1,176 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PXCLOTH_H_ -#define _PXCLOTH_H_ - -#ifndef _GAMEBASE_H_ -#include "T3D/gameBase/gameBase.h" -#endif -#ifndef _GFXPRIMITIVEBUFFER_H_ -#include "gfx/gfxPrimitiveBuffer.h" -#endif -#ifndef _GFXVERTEXBUFFER_H_ -#include "gfx/gfxVertexBuffer.h" -#endif -#ifndef _PHYSX_H_ -#include "T3D/physics/physx/px.h" -#endif -#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_ -#include "T3D/physics/physicsPlugin.h" -#endif - -class Material; -class BaseMatInstance; -class PxWorld; -class NxScene; -class NxClothMesh; -class NxCloth; - - -class PxCloth : public GameBase -{ - typedef GameBase Parent; - - enum MaskBits - { - TransformMask = Parent::NextFreeMask << 0, - ClothMask = Parent::NextFreeMask << 1, - MaterialMask = Parent::NextFreeMask << 3, - NextFreeMask = Parent::NextFreeMask << 4 - }; - -public: - - PxCloth(); - virtual ~PxCloth(); - - DECLARE_CONOBJECT( PxCloth ); - - // SimObject - virtual bool onAdd(); - virtual void onRemove(); - static void initPersistFields(); - virtual void inspectPostApply(); - void onPhysicsReset( PhysicsResetEvent reset ); - - // NetObject - virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream ); - virtual void unpackUpdate( NetConnection *conn, BitStream *stream ); - - // SceneObject - virtual void setTransform( const MatrixF &mat ); - virtual void setScale( const VectorF &scale ); - virtual void prepRenderImage( SceneRenderState *state ); - - // GameBase - virtual bool onNewDataBlock( GameBaseData *dptr, bool reload ); - virtual void processTick( const Move *move ); - virtual void interpolateTick( F32 delta ); - -protected: - - PxWorld *mWorld; - - NxScene *mScene; - - /// Cooked cloth collision mesh. - NxClothMesh *mClothMesh; - - /// The cloth actor used - NxCloth *mCloth; - - NxMeshData mReceiveBuffers; - - bool mBendingEnabled; - bool mDampingEnabled; - bool mTriangleCollisionEnabled; - bool mSelfCollisionEnabled; - - F32 mDensity; - F32 mThickness; - F32 mFriction; - F32 mBendingStiffness; - F32 mStretchingStiffness; - F32 mDampingCoefficient; - F32 mCollisionResponseCoefficient; - F32 mAttachmentResponseCoefficient; - - U32 mAttachmentMask; - - static EnumTable mAttachmentFlagTable; - - String mMaterialName; - SimObjectPtr mMaterial; - BaseMatInstance *mMatInst; - - String lookupName; - - /// The output verts from the PhysX simulation. - GFXVertexPNTT *mVertexRenderBuffer; - - /// The output indices from the PhysX simulation. - U16 *mIndexRenderBuffer; - - U32 mMaxVertices; - U32 mMaxIndices; - - /// The number of indices in the cloth which - /// is updated by the PhysX simulation. - U32 mNumIndices; - - /// The number of verts in the cloth which - /// is updated by the PhysX simulation. - U32 mNumVertices; - - U32 mMeshDirtyFlags; - bool mIsVBDirty; - - GFXPrimitiveBufferHandle mPrimBuffer; - GFXVertexBufferHandle mVB; - - Point2I mPatchVerts; - Point2F mPatchSize; - - MatrixF mResetXfm; - - void _initMaterial(); - - void _releaseMesh(); - void _releaseCloth(); - - bool _createClothPatch(); - - void _recreateCloth( const MatrixF &transform ); - - void _updateClothProperties(); - - void _initClothMesh(); - void _initReceiveBuffers(); - void _setupAttachments(); - - void _updateStaticCloth(); - - void _updateVBIB(); -}; - -#endif // _PXCLOTH_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxCollision.cpp b/Engine/source/T3D/physics/physx/pxCollision.cpp deleted file mode 100644 index b08636d64..000000000 --- a/Engine/source/T3D/physics/physx/pxCollision.cpp +++ /dev/null @@ -1,291 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxCollision.h" - -#include "math/mPoint3.h" -#include "math/mMatrix.h" -#include "T3D/physics/physX/px.h" -#include "T3D/physics/physX/pxCasts.h" -#include "T3D/physics/physX/pxWorld.h" -#include "T3D/physics/physX/pxStream.h" - - -PxCollision::PxCollision() -{ -} - -PxCollision::~PxCollision() -{ - // We may be deleteting SDK data... so make - // sure we have the the scene write lock. - PxWorld::releaseWriteLocks(); - - for ( U32 i=0; i < mColShapes.size(); i++ ) - { - // Check for special types which need cleanup. - NxShapeDesc *desc = mColShapes[i]; - - if ( desc->getType() == NX_SHAPE_CONVEX ) - gPhysicsSDK->releaseConvexMesh( *((NxConvexShapeDesc*)desc)->meshData ); - else if ( desc->getType() == NX_SHAPE_MESH ) - gPhysicsSDK->releaseTriangleMesh( *((NxTriangleMeshShapeDesc*)desc)->meshData ); - else if ( desc->getType() == NX_SHAPE_HEIGHTFIELD ) - gPhysicsSDK->releaseHeightField( *((NxHeightFieldShapeDesc*)desc)->heightField ); - - // Delete the descriptor. - delete desc; - } - - mColShapes.clear(); -} - -void PxCollision::addPlane( const PlaneF &plane ) -{ - NxBoxShapeDesc *desc = new NxBoxShapeDesc; - desc->skinWidth = 0.01f; - desc->dimensions.set( 10000.0f, 10000.0f, 100.0f ); - desc->localPose.t.z = -100.0f; - - // TODO: Fix rotation to match plane normal! - //boxDesc->localPose.M.setColumn( 0, NxVec3( plane.x, plane.y, plane.z ) ); - //boxDesc->localPose.M.setColumn( 1, NxVec3( plane.x, plane.y, plane.z ) ); - //boxDesc->localPose.M.setColumn( 2, NxVec3( plane.x, plane.y, plane.z ) ); - - mColShapes.push_back( desc ); -} - -void PxCollision::addBox( const Point3F &halfWidth, - const MatrixF &localXfm ) -{ - NxBoxShapeDesc *desc = new NxBoxShapeDesc; - desc->skinWidth = 0.01f; - desc->dimensions.set( halfWidth.x, halfWidth.y, halfWidth.z ); - desc->localPose.setRowMajor44( localXfm ); - mColShapes.push_back( desc ); -} - -void PxCollision::addSphere( F32 radius, - const MatrixF &localXfm ) -{ - NxSphereShapeDesc *desc = new NxSphereShapeDesc; - desc->skinWidth = 0.01f; - desc->radius = radius; - desc->localPose.setRowMajor44( localXfm ); - mColShapes.push_back( desc ); -} - -void PxCollision::addCapsule( F32 radius, - F32 height, - const MatrixF &localXfm ) -{ - NxCapsuleShapeDesc *desc = new NxCapsuleShapeDesc; - desc->skinWidth = 0.01f; - desc->radius = radius; - desc->height = height; - desc->localPose.setRowMajor44( localXfm ); - mColShapes.push_back( desc ); -} - -bool PxCollision::addConvex( const Point3F *points, - U32 count, - const MatrixF &localXfm ) -{ - // Mesh cooking requires that both - // scenes not be write locked! - PxWorld::releaseWriteLocks(); - - NxCookingInterface *cooker = PxWorld::getCooking(); - cooker->NxInitCooking(); - - NxConvexMeshDesc meshDesc; - meshDesc.numVertices = count; - meshDesc.pointStrideBytes = sizeof(Point3F); - meshDesc.points = points; - meshDesc.flags = NX_CF_COMPUTE_CONVEX | NX_CF_INFLATE_CONVEX; - - // Cook it! - NxCookingParams params; - #ifdef TORQUE_OS_XENON - params.targetPlatform = PLATFORM_XENON; - #else - params.targetPlatform = PLATFORM_PC; - #endif - params.skinWidth = 0.01f; - params.hintCollisionSpeed = true; - cooker->NxSetCookingParams( params ); - - PxMemStream stream; - bool cooked = cooker->NxCookConvexMesh( meshDesc, stream ); - cooker->NxCloseCooking(); - - if ( !cooked ) - return false; - - stream.resetPosition(); - NxConvexMesh *meshData = gPhysicsSDK->createConvexMesh( stream ); - if ( !meshData ) - return false; - - NxConvexShapeDesc *desc = new NxConvexShapeDesc; - desc->skinWidth = 0.01f; - desc->meshData = meshData; - desc->localPose.setRowMajor44( localXfm ); - mColShapes.push_back( desc ); - - return true; -} - -bool PxCollision::addTriangleMesh( const Point3F *vert, - U32 vertCount, - const U32 *index, - U32 triCount, - const MatrixF &localXfm ) -{ - // Mesh cooking requires that both - // scenes not be write locked! - PxWorld::releaseWriteLocks(); - - NxCookingInterface *cooker = PxWorld::getCooking(); - cooker->NxInitCooking(); - - NxTriangleMeshDesc meshDesc; - meshDesc.numVertices = vertCount; - meshDesc.numTriangles = triCount; - meshDesc.pointStrideBytes = sizeof(Point3F); - meshDesc.triangleStrideBytes = 3*sizeof(U32); - meshDesc.points = vert; - meshDesc.triangles = index; - meshDesc.flags = NX_MF_FLIPNORMALS; - - // Cook it! - NxCookingParams params; - #ifdef TORQUE_OS_XENON - params.targetPlatform = PLATFORM_XENON; - #else - params.targetPlatform = PLATFORM_PC; - #endif - params.skinWidth = 0.01f; - params.hintCollisionSpeed = true; - cooker->NxSetCookingParams( params ); - - PxMemStream stream; - bool cooked = cooker->NxCookTriangleMesh( meshDesc, stream ); - cooker->NxCloseCooking(); - if ( !cooked ) - return false; - - stream.resetPosition(); - NxTriangleMesh *meshData = gPhysicsSDK->createTriangleMesh( stream ); - if ( !meshData ) - return false; - - NxTriangleMeshShapeDesc *desc = new NxTriangleMeshShapeDesc; - desc->skinWidth = 0.01f; - desc->meshData = meshData; - desc->localPose.setRowMajor44( localXfm ); - mColShapes.push_back( desc ); - - return true; -} - -bool PxCollision::addHeightfield( const U16 *heights, - const bool *holes, - U32 blockSize, - F32 metersPerSample, - const MatrixF &localXfm ) -{ - // Since we're creating SDK level data we - // have to have access to all active worlds. - PxWorld::releaseWriteLocks(); - - // Init the heightfield description. - NxHeightFieldDesc heightFieldDesc; - heightFieldDesc.nbColumns = blockSize; - heightFieldDesc.nbRows = blockSize; - heightFieldDesc.thickness = -10.0f; - heightFieldDesc.convexEdgeThreshold = 0; - - // Allocate the samples. - heightFieldDesc.samples = new NxU32[ blockSize * blockSize ]; - heightFieldDesc.sampleStride = sizeof(NxU32); - NxU8 *currentByte = (NxU8*)heightFieldDesc.samples; - - for ( U32 row = 0; row < blockSize; row++ ) - { - const U32 tess = ( row + 1 ) % 2; - - for ( U32 column = 0; column < blockSize; column++ ) - { - NxHeightFieldSample *currentSample = (NxHeightFieldSample*)currentByte; - - U32 index = ( blockSize - row - 1 ) + ( column * blockSize ); - currentSample->height = heights[ index ]; - - if ( holes && holes[ getMax( (S32)index - 1, 0 ) ] ) // row index for holes adjusted so PhysX collision shape better matches rendered terrain - { - currentSample->materialIndex0 = 0; - currentSample->materialIndex1 = 0; - } - else - { - currentSample->materialIndex0 = 1; //materialIds[0]; - currentSample->materialIndex1 = 1; //materialIds[0]; - } - - currentSample->tessFlag = ( column + tess ) % 2; - - currentByte += heightFieldDesc.sampleStride; - } - } - - // Build it. - NxHeightFieldShapeDesc *desc = new NxHeightFieldShapeDesc; - desc->heightField = gPhysicsSDK->createHeightField( heightFieldDesc ); - - // Destroy the temp sample array. - delete [] heightFieldDesc.samples; - - // TerrainBlock uses a 11.5 fixed point height format - // giving it a maximum height range of 0 to 2048. - desc->heightScale = 0.03125f; - - desc->rowScale = metersPerSample; - desc->columnScale = metersPerSample; - desc->materialIndexHighBits = 0; - desc->skinWidth = 0.01f; - - // Use the local pose to align the heightfield - // to what Torque will expect. - NxMat33 rotX; - rotX.rotX( Float_HalfPi ); - NxMat33 rotZ; - rotZ.rotZ( Float_Pi ); - NxMat34 rot; - rot.M.multiply( rotZ, rotX ); - rot.t.set( ( blockSize - 1 ) * metersPerSample, 0, 0 ); - desc->localPose = rot; - - mColShapes.push_back( desc ); - return true; -} diff --git a/Engine/source/T3D/physics/physx/pxCollision.h b/Engine/source/T3D/physics/physx/pxCollision.h deleted file mode 100644 index 54263b792..000000000 --- a/Engine/source/T3D/physics/physx/pxCollision.h +++ /dev/null @@ -1,78 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _T3D_PHYSICS_PXCOLLISION_H_ -#define _T3D_PHYSICS_PXCOLLISION_H_ - -#ifndef _T3D_PHYSICS_PHYSICSCOLLISION_H_ -#include "T3D/physics/physicsCollision.h" -#endif -#ifndef _TVECTOR_H_ -#include "core/util/tVector.h" -#endif - -class NxShapeDesc; - - -class PxCollision : public PhysicsCollision -{ -protected: - - /// The collision representation. - Vector mColShapes; - - /// Helper for adding shapes. - //void _addShape( btCollisionShape *shape, const MatrixF &localXfm ); - -public: - - PxCollision(); - virtual ~PxCollision(); - - /// Return the PhysX shape descriptions. - const Vector& getShapes() const { return mColShapes; } - - // PhysicsCollision - virtual void addPlane( const PlaneF &plane ); - virtual void addBox( const Point3F &halfWidth, - const MatrixF &localXfm ); - virtual void addSphere( F32 radius, - const MatrixF &localXfm ); - virtual void addCapsule( F32 radius, - F32 height, - const MatrixF &localXfm ); - virtual bool addConvex( const Point3F *points, - U32 count, - const MatrixF &localXfm ); - virtual bool addTriangleMesh( const Point3F *vert, - U32 vertCount, - const U32 *index, - U32 triCount, - const MatrixF &localXfm ); - virtual bool addHeightfield( const U16 *heights, - const bool *holes, - U32 blockSize, - F32 metersPerSample, - const MatrixF &localXfm ); -}; - -#endif // _T3D_PHYSICS_PXCOLLISION_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxContactReporter.cpp b/Engine/source/T3D/physics/physx/pxContactReporter.cpp deleted file mode 100644 index 33b1c3dab..000000000 --- a/Engine/source/T3D/physics/physx/pxContactReporter.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxContactReporter.h" - -#include "T3D/physics/physX/pxCasts.h" -#include "T3D/physics/physicsUserData.h" -#include "T3D/physics/physX/pxMultiActor.h" -#include "platform/profiler.h" - - -PxContactReporter::PxContactReporter() -{ -} - -PxContactReporter::~PxContactReporter() -{ -} - -void PxContactReporter::onContactNotify( NxContactPair &pair, NxU32 events ) -{ - PROFILE_SCOPE( PxContactReporter_OnContactNotify ); - - // For now we only care about start touch events. - if ( !( events & NX_NOTIFY_ON_START_TOUCH ) ) - return; - - // Skip if either actor is deleted. - if ( pair.isDeletedActor[0] || pair.isDeletedActor[1] ) - return; - - NxActor *actor0 = pair.actors[0]; - NxActor *actor1 = pair.actors[1]; - - PhysicsUserData *userData0 = PhysicsUserData::cast( actor0->userData ); - PhysicsUserData *userData1 = PhysicsUserData::cast( actor1->userData ); - - // Early out if we don't have user data or signals to notify. - if ( ( !userData0 || userData0->getContactSignal().isEmpty() ) && - ( !userData1 || userData1->getContactSignal().isEmpty() ) ) - return; - - // Get an average contact point. - U32 points = 0; - NxVec3 hitPoint( 0.0f ); - NxContactStreamIterator iter( pair.stream ); - while( iter.goNextPair() ) - { - while( iter.goNextPatch() ) - { - while( iter.goNextPoint() ) - { - hitPoint += iter.getPoint(); - ++points; - } - } - } - hitPoint /= (F32)points; - - if ( userData0 ) - userData0->getContactSignal().trigger( userData0, - userData1, - pxCast( hitPoint ), - pxCast( pair.sumNormalForce ) ); - - if ( userData1 ) - userData1->getContactSignal().trigger( userData1, - userData0, - pxCast( hitPoint ), - pxCast( -pair.sumNormalForce ) ); -} - -bool PxUserNotify::onJointBreak( NxReal breakingForce, NxJoint &brokenJoint ) -{ - PROFILE_SCOPE( PxUserNotify_OnJointBreak ); - - PxUserData *userData = PxUserData::getData( brokenJoint ); - - if ( userData ) - userData->getOnJointBreakSignal().trigger( breakingForce, brokenJoint ); - - // NOTE: Returning true here will tell the - // PhysX SDK to delete the joint, which will - // cause MANY problems if any of the user app's - // objects still hold references to it. - - return false; -} \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxContactReporter.h b/Engine/source/T3D/physics/physx/pxContactReporter.h deleted file mode 100644 index 883d61b9c..000000000 --- a/Engine/source/T3D/physics/physx/pxContactReporter.h +++ /dev/null @@ -1,54 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PXCONTACTREPORTER_H_ -#define _PXCONTACTREPORTER_H_ - -#ifndef _PHYSX_H_ -#include "T3D/physics/physX/px.h" -#endif - - -class PxContactReporter : public NxUserContactReport -{ -protected: - - virtual void onContactNotify( NxContactPair& pair, NxU32 events ); - -public: - - PxContactReporter(); - virtual ~PxContactReporter(); -}; - - - -class PxUserNotify : public NxUserNotify -{ -public: - virtual bool onJointBreak( NxReal breakingForce, NxJoint &brokenJoint ); - virtual void onWake( NxActor **actors, NxU32 count ) {} - virtual void onSleep ( NxActor **actors, NxU32 count ) {} -}; - - -#endif // _PXCONTACTREPORTER_H_ diff --git a/Engine/source/T3D/physics/physx/pxFluid.cpp b/Engine/source/T3D/physics/physx/pxFluid.cpp deleted file mode 100644 index efe5d453b..000000000 --- a/Engine/source/T3D/physics/physx/pxFluid.cpp +++ /dev/null @@ -1,310 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physx/pxFluid.h" - -#include "console/consoleTypes.h" -#include "scene/sceneRenderState.h" -#include "renderInstance/renderPassManager.h" -#include "T3D/physics/physicsPlugin.h" -#include "T3D/physics/physx/pxWorld.h" -#include "T3D/physics/physx/pxCasts.h" -#include "gfx/gfxDrawUtil.h" -#include "math/mathIO.h" -#include "core/stream/bitStream.h" - - -IMPLEMENT_CO_NETOBJECT_V1( PxFluid ); - -ConsoleDocClass( PxFluid, - "@brief Experimental and unfinished Torque wrapper class for NxFluid.\n\n" - "@internal\n" -); - -PxFluid::PxFluid() - : mWorld( NULL ), - mScene( NULL ), - mParticles( NULL ), - mFluid( NULL ), - mEmitter( NULL ), - mParticleCount( 0 ) -{ - mNetFlags.set( Ghostable | ScopeAlways ); - mTypeMask |= StaticObjectType | StaticShapeObjectType; -} - -PxFluid::~PxFluid() -{ - -} - -bool PxFluid::onAdd() -{ - if ( !Parent::onAdd() ) - return false; - - mWorld = dynamic_cast( PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ) ); - - if ( !mWorld || !mWorld->getScene() ) - { - Con::errorf( "PxMultiActor::onAdd() - PhysXWorld not initialized!" ); - return false; - } - - mScene = mWorld->getScene(); - - if ( isClientObject() ) - _createFluid(); - - Point3F halfScale = Point3F::One * 0.5f; - mObjBox.minExtents = -halfScale; - mObjBox.maxExtents = halfScale; - resetWorldBox(); - - addToScene(); - - return true; -} - -void PxFluid::onRemove() -{ - if ( isClientObject() ) - _destroyFluid(); - - removeFromScene(); - - Parent::onRemove(); -} - -void PxFluid::initPersistFields() -{ - Parent::initPersistFields(); -} - -void PxFluid::inspectPostApply() -{ - Parent::inspectPostApply(); - - setMaskBits( UpdateMask ); -} - -U32 PxFluid::packUpdate( NetConnection *conn, U32 mask, BitStream *stream ) -{ - U32 retMask = Parent::packUpdate( conn, mask, stream ); - - if ( stream->writeFlag( mask & UpdateMask ) ) - { - mathWrite( *stream, getTransform() ); - mathWrite( *stream, getScale() ); - - stream->write( mEmitter ? mEmitter->getRate() : 0 ); - } - - stream->writeFlag( isProperlyAdded() && mask & ResetMask ); - - return retMask; -} - -void PxFluid::unpackUpdate( NetConnection *conn, BitStream *stream ) -{ - Parent::unpackUpdate( conn, stream ); - - // UpdateMask - if ( stream->readFlag() ) - { - MatrixF mat; - mathRead( *stream, &mat ); - Point3F scale; - mathRead( *stream, &scale ); - - setScale( scale ); - setTransform( mat ); - - F32 rate; - stream->read( &rate ); - setRate( rate ); - } - - // ResetMask - if ( stream->readFlag() ) - resetParticles(); -} - -void PxFluid::setTransform( const MatrixF &mat ) -{ - Parent::setTransform( mat ); - - if ( mEmitter ) - { - NxMat34 nxMat; - nxMat.setRowMajor44( mat ); - mEmitter->setGlobalPose( nxMat ); - } -} - -void PxFluid::setScale( const VectorF &scale ) -{ - Point3F lastScale = getScale(); - - Point3F halfScale = Point3F::One * 0.5f; - mObjBox.minExtents = -halfScale; - mObjBox.maxExtents = halfScale; - resetWorldBox(); - - Parent::setScale( scale ); - - if ( lastScale != getScale() && - mEmitter ) - { - _destroyFluid(); - _createFluid(); - } -} - -void PxFluid::prepRenderImage( SceneRenderState *state ) -{ - if ( !state->isDiffusePass() ) - return; - - ObjectRenderInst *ri = state->getRenderPass()->allocInst(); - ri->renderDelegate.bind( this, &PxFluid::renderObject ); - ri->type = RenderPassManager::RIT_Object; - state->getRenderPass()->addInst( ri ); -} - -void PxFluid::resetParticles() -{ - if ( mEmitter ) - mEmitter->resetEmission( MAX_PARTICLES ); - setMaskBits( ResetMask ); -} - -void PxFluid::setRate( F32 rate ) -{ - if ( mEmitter ) - mEmitter->setRate( rate ); - setMaskBits( UpdateMask ); -} - -void PxFluid::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) -{ - GFXStateBlockDesc desc; - desc.setBlend( true ); - desc.setZReadWrite( true, false ); - - for ( U32 i = 0; i < mParticleCount; i++ ) - { - FluidParticle &particle = mParticles[i]; - Point3F pnt = pxCast( particle.position ); - - Box3F box( 0.2f ); - box.minExtents += pnt; - box.maxExtents += pnt; - - GFX->getDrawUtil()->drawCube( desc, box, ColorI::BLUE ); - } -} - -void PxFluid::_createFluid() -{ - /* - // Set structure to pass particles, and receive them after every simulation step - NxParticleData particleData; - particleData.numParticlesPtr = &mParticleCount; - particleData.bufferPos = &mParticles[0].position.x; - particleData.bufferPosByteStride = sizeof(FluidParticle); - particleData.bufferVel = &mParticles[0].velocity.x; - particleData.bufferVelByteStride = sizeof(FluidParticle); - particleData.bufferLife = &mParticles[0].lifetime; - particleData.bufferLifeByteStride = sizeof(FluidParticle); - - // Create a fluid descriptor - NxFluidDesc fluidDesc; - fluidDesc.kernelRadiusMultiplier = 2.3f; - fluidDesc.restParticlesPerMeter = 10.0f; - fluidDesc.stiffness = 200.0f; - fluidDesc.viscosity = 22.0f; - fluidDesc.restDensity = 1000.0f; - fluidDesc.damping = 0.0f; - fluidDesc.simulationMethod = NX_F_SPH; - fluidDesc.initialParticleData = particleData; - fluidDesc.particlesWriteData = particleData; - */ - - NxFluidDesc fluidDesc; - fluidDesc.setToDefault(); - fluidDesc.simulationMethod = NX_F_SPH; - fluidDesc.maxParticles = MAX_PARTICLES; - fluidDesc.restParticlesPerMeter = 50; - fluidDesc.stiffness = 1; - fluidDesc.viscosity = 6; - fluidDesc.flags = NX_FF_VISUALIZATION|NX_FF_ENABLED; - - mParticles = new FluidParticle[MAX_PARTICLES]; - dMemset( mParticles, 0, sizeof(FluidParticle) * MAX_PARTICLES ); - - NxParticleData &particleData = fluidDesc.particlesWriteData; - - particleData.numParticlesPtr = &mParticleCount; - particleData.bufferPos = &mParticles[0].position.x; - particleData.bufferPosByteStride = sizeof(FluidParticle); - particleData.bufferVel = &mParticles[0].velocity.x; - particleData.bufferVelByteStride = sizeof(FluidParticle); - particleData.bufferLife = &mParticles[0].lifetime; - particleData.bufferLifeByteStride = sizeof(FluidParticle); - - mFluid = mScene->createFluid( fluidDesc ); - - - //Create Emitter. - NxFluidEmitterDesc emitterDesc; - emitterDesc.setToDefault(); - emitterDesc.dimensionX = getScale().x; - emitterDesc.dimensionY = getScale().y; - emitterDesc.relPose.setColumnMajor44( getTransform() ); - emitterDesc.rate = 5.0f; - emitterDesc.randomAngle = 0.1f; - emitterDesc.fluidVelocityMagnitude = 6.5f; - emitterDesc.maxParticles = 0; - emitterDesc.particleLifetime = 4.0f; - emitterDesc.type = NX_FE_CONSTANT_FLOW_RATE; - emitterDesc.shape = NX_FE_ELLIPSE; - mEmitter = mFluid->createEmitter(emitterDesc); -} - -void PxFluid::_destroyFluid() -{ - delete[] mParticles; - mScene->releaseFluid( *mFluid ); - mEmitter = NULL; -} - -ConsoleMethod( PxFluid, resetParticles, void, 2, 2, "" ) -{ - object->resetParticles(); -} - -ConsoleMethod( PxFluid, setRate, void, 2, 2, "" ) -{ - object->setRate( dAtof(argv[2]) ); -} \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxFluid.h b/Engine/source/T3D/physics/physx/pxFluid.h deleted file mode 100644 index ae7fe4f3c..000000000 --- a/Engine/source/T3D/physics/physx/pxFluid.h +++ /dev/null @@ -1,107 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PXFLUID_H_ -#define _PXFLUID_H_ - -#ifndef _SCENEOBJECT_H_ -#include "scene/sceneObject.h" -#endif -#ifndef _PHYSX_H_ -#include "T3D/physics/physx/px.h" -#endif - -class BaseMatInstance; -class PxWorld; -class NxScene; - - -class PxFluid : public SceneObject -{ - typedef SceneObject Parent; - -protected: - - enum NetMasks - { - UpdateMask = Parent::NextFreeMask, - ResetMask = Parent::NextFreeMask << 1, - NextFreeMask = Parent::NextFreeMask << 2 - }; - - struct FluidParticle - { - NxVec3 position; - NxVec3 velocity; - NxReal density; - NxReal lifetime; - NxU32 id; - NxVec3 collisionNormal; - }; - - #define MAX_PARTICLES 100 - -public: - - PxFluid(); - virtual ~PxFluid(); - - DECLARE_CONOBJECT( PxFluid ); - - // SimObject - virtual bool onAdd(); - virtual void onRemove(); - static void initPersistFields(); - virtual void inspectPostApply(); - - // NetObject - virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream ); - virtual void unpackUpdate( NetConnection *conn, BitStream *stream ); - - // SceneObject - virtual void setTransform( const MatrixF &mat ); - virtual void setScale( const VectorF &scale ); - virtual void prepRenderImage( SceneRenderState *state ); - - void resetParticles(); - void setRate( F32 rate ); - -protected: - - void renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - - void _createFluid(); - void _destroyFluid(); - -protected: - - PxWorld *mWorld; - NxScene *mScene; - - FluidParticle *mParticles; - //NxParticleData *mParticleData; - NxFluid *mFluid; - U32 mParticleCount; - NxFluidEmitter *mEmitter; -}; - -#endif // _PXFLUID_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxMaterial.cpp b/Engine/source/T3D/physics/physx/pxMaterial.cpp deleted file mode 100644 index 9a5656394..000000000 --- a/Engine/source/T3D/physics/physx/pxMaterial.cpp +++ /dev/null @@ -1,150 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/px.h" - -#include "T3D/physics/physX/pxMaterial.h" - -#include "T3D/physics/physX/pxWorld.h" -#include "T3D/physics/physicsPlugin.h" -#include "console/consoleTypes.h" -#include "core/stream/bitStream.h" - - -IMPLEMENT_CO_DATABLOCK_V1( PxMaterial ); - -ConsoleDocClass( PxMaterial, - - "@brief Defines a PhysX material assignable to a PxMaterial.\n\n" - - "When two actors collide, the collision behavior that results depends on the material properties " - "of the actors' surfaces. For example, the surface properties determine if the actors will or will " - "not bounce, or if they will slide or stick. Currently, the only special feature supported by materials " - "is anisotropic friction, but according to Nvidia, other effects such as moving surfaces and more types " - "of friction are slotted for future release.\n\n" - - "For more information, refer to Nvidia's PhysX docs.\n\n" - - "@ingroup Physics" -); - -PxMaterial::PxMaterial() -: mNxMat( NULL ), - mNxMatId( -1 ), - restitution( 0.0f ), - staticFriction( 0.1f ), - dynamicFriction( 0.95f ), - mServer( false ) -{ -} - -PxMaterial::~PxMaterial() -{ -} - -void PxMaterial::consoleInit() -{ - Parent::consoleInit(); -} - -void PxMaterial::initPersistFields() -{ - Parent::initPersistFields(); - - addGroup("PxMaterial"); - - addField( "restitution", TypeF32, Offset( restitution, PxMaterial ), - "@brief Coeffecient of a bounce applied to the shape in response to a collision.\n\n" - "A value of 0 makes the object bounce as little as possible, while higher values up to 1.0 result in more bounce.\n\n" - "@note Values close to or above 1.0 may cause stability problems and/or increasing energy."); - addField( "staticFriction", TypeF32, Offset( staticFriction, PxMaterial ), - "@brief Coefficient of static %friction to be applied.\n\n" - "Static %friction determines the force needed to start moving an at-rest object in contact with a surface. " - "If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. " - "A higher coefficient will require a larger force to start motion. " - "@note This value should be larger than 0.\n\n"); - addField( "dynamicFriction", TypeF32, Offset( dynamicFriction, PxMaterial ), - "@brief Coefficient of dynamic %friction to be applied.\n\n" - "Dynamic %friction reduces the velocity of a moving object while it is in contact with a surface. " - "A higher coefficient will result in a larger reduction in velocity. " - "A shape's dynamicFriction should be equal to or larger than 0.\n\n"); - - endGroup("PxMaterial"); -} - -void PxMaterial::onStaticModified( const char *slotName, const char *newValue ) -{ - if ( isProperlyAdded() && mNxMat != NULL ) - { - mNxMat->setRestitution( restitution ); - mNxMat->setStaticFriction( staticFriction ); - mNxMat->setDynamicFriction( dynamicFriction ); - } -} - -bool PxMaterial::preload( bool server, String &errorBuffer ) -{ - mServer = server; - - PxWorld *world = dynamic_cast( PHYSICSMGR->getWorld( server ? "server" : "client" ) ); - - if ( !world ) - { - // TODO: Error... in error buffer? - return false; - } - - NxMaterialDesc material; - material.restitution = restitution; - material.staticFriction = staticFriction; - material.dynamicFriction = dynamicFriction; - - mNxMat = world->createMaterial( material ); - mNxMatId = mNxMat->getMaterialIndex(); - - if ( mNxMatId == -1 ) - { - errorBuffer = "PxMaterial::preload() - unable to create material!"; - return false; - } - - return Parent::preload( server, errorBuffer ); -} - -void PxMaterial::packData( BitStream* stream ) -{ - Parent::packData( stream ); - - stream->write( restitution ); - stream->write( staticFriction ); - stream->write( dynamicFriction ); -} - -void PxMaterial::unpackData( BitStream* stream ) -{ - Parent::unpackData( stream ); - - stream->read( &restitution ); - stream->read( &staticFriction ); - stream->read( &dynamicFriction ); -} diff --git a/Engine/source/T3D/physics/physx/pxMaterial.h b/Engine/source/T3D/physics/physx/pxMaterial.h deleted file mode 100644 index b1e0dd7f0..000000000 --- a/Engine/source/T3D/physics/physx/pxMaterial.h +++ /dev/null @@ -1,69 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PHYSX_MATERIAL_H -#define _PHYSX_MATERIAL_H - -#ifndef _SIMBASE_H_ -#include "console/simBase.h" -#endif -#ifndef _DYNAMIC_CONSOLETYPES_H_ -#include "console/dynamicTypes.h" -#endif - -class NxMaterial; - -class PxMaterial : public SimDataBlock -{ - typedef SimDataBlock Parent; - -protected: - - F32 restitution; - F32 staticFriction; - F32 dynamicFriction; - - NxMaterial *mNxMat; - S32 mNxMatId; - - bool mServer; - -public: - - DECLARE_CONOBJECT( PxMaterial ); - - PxMaterial(); - ~PxMaterial(); - - static void consoleInit(); - static void initPersistFields(); - virtual void onStaticModified( const char *slotName, const char *newValue ); - - bool preload( bool server, String &errorBuffer ); - virtual void packData( BitStream* stream ); - virtual void unpackData( BitStream* stream ); - - S32 getMaterialId() const { return mNxMatId; } - -}; - -#endif // _PHYSX_MATERIAL_H \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxMultiActor.cpp b/Engine/source/T3D/physics/physx/pxMultiActor.cpp deleted file mode 100644 index 6abdcdaad..000000000 --- a/Engine/source/T3D/physics/physx/pxMultiActor.cpp +++ /dev/null @@ -1,2651 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxMultiActor.h" - -#include "console/consoleTypes.h" -#include "core/stream/fileStream.h" -#include "core/stream/bitStream.h" -#include "core/resourceManager.h" -#include "core/strings/stringUnit.h" -#include "sim/netConnection.h" -#include "math/mathIO.h" -#include "math/mathUtils.h" -#include "gfx/gfxTransformSaver.h" -#include "gfx/gfxDrawUtil.h" -#include "gfx/primBuilder.h" -#include "collision/collision.h" -#include "collision/abstractPolyList.h" -#include "ts/tsShapeInstance.h" -#include "ts/tsPartInstance.h" -#include "lighting/lightManager.h" -#include "scene/sceneManager.h" -#include "scene/sceneRenderState.h" -#include "scene/sceneObjectLightingPlugin.h" -#include "T3D/objectTypes.h" -#include "T3D/containerQuery.h" -#include "T3D/fx/particleEmitter.h" -#include "T3D/debris.h" -#include "renderInstance/renderPassManager.h" -#include "gui/worldEditor/editor.h" // For gEditingMission -#include "T3D/physics/physX/px.h" -#include "T3D/physics/physX/pxWorld.h" -#include "T3D/physics/physX/pxMaterial.h" -#include "T3D/physics/physX/pxCasts.h" -#include "T3D/physics/physx/pxUtils.h" -#include "sfx/sfxSystem.h" - -#include -#include -#include - - -class PxMultiActor_Notify : public NXU_userNotify -{ -protected: - - Vector mActors; - - Vector mShapes; - - Vector mJoints; - - const NxMat34 mTransform; - - const Point3F mScale; - - F32 mMassScale; - - NxCompartment *mCompartment; - - PxMaterial *mMaterial; - - Vector *mActorUserProperties; - - Vector *mJointUserProperties; - -public: - - void NXU_notifyJoint( NxJoint *joint, const char *userProperties ) - { - if ( mJointUserProperties ) - mJointUserProperties->push_back( userProperties ); - mJoints.push_back( joint ); - } - - bool NXU_preNotifyJoint( NxJointDesc &joint, const char *userProperties ) - { - joint.localAnchor[0].x *= mScale.x; - joint.localAnchor[0].y *= mScale.y; - joint.localAnchor[0].z *= mScale.z; - - joint.localAnchor[1].x *= mScale.x; - joint.localAnchor[1].y *= mScale.y; - joint.localAnchor[1].z *= mScale.z; - - // The PhysX exporter from 3dsMax doesn't allow creation - // of fixed joints. It also doesn't seem to export the - // joint names! So look for joints which all all the - // motion axes are locked... make those fixed joints. - if ( joint.getType() == NX_JOINT_D6 ) - { - NxD6JointDesc *d6Joint = static_cast( &joint ); - - if ( d6Joint->xMotion == NX_D6JOINT_MOTION_LOCKED && - d6Joint->yMotion == NX_D6JOINT_MOTION_LOCKED && - d6Joint->zMotion == NX_D6JOINT_MOTION_LOCKED && - d6Joint->swing1Motion == NX_D6JOINT_MOTION_LOCKED && - d6Joint->swing2Motion == NX_D6JOINT_MOTION_LOCKED && - d6Joint->twistMotion == NX_D6JOINT_MOTION_LOCKED ) - { - // Ok... build a new fixed joint. - NxFixedJointDesc fixed; - fixed.actor[0] = joint.actor[0]; - fixed.actor[1] = joint.actor[1]; - fixed.localNormal[0] = joint.localNormal[0]; - fixed.localNormal[1] = joint.localNormal[1]; - fixed.localAxis[0] = joint.localAxis[0]; - fixed.localAxis[1] = joint.localAxis[1]; - fixed.localAnchor[0] = joint.localAnchor[0]; - fixed.localAnchor[1] = joint.localAnchor[1]; - fixed.maxForce = joint.maxForce; - fixed.maxTorque = joint.maxTorque; - fixed.name = joint.name; - fixed.userData = joint.userData; - fixed.jointFlags = joint.jointFlags; - - // What scene are we adding this to? - NxActor *actor = fixed.actor[0] ? fixed.actor[0] : fixed.actor[1]; - NxScene &scene = actor->getScene(); - - NxJoint* theJoint = scene.createJoint( fixed ); - mJoints.push_back( theJoint ); - if ( mJointUserProperties ) - mJointUserProperties->push_back( userProperties ); - - // Don't generate this joint. - return false; - } - } - - return true; - } - - void NXU_notifyActor( NxActor *actor, const char *userProperties ) - { - mActors.push_back( actor ); - - // Save the shapes. - for ( U32 i=0; i < actor->getNbShapes(); i++ ) - mShapes.push_back( actor->getShapes()[i] ); - - mActorUserProperties->push_back( userProperties ); - }; - - bool NXU_preNotifyMaterial( NxMaterialDesc &t, const char *userProperties ) - { - // Don't generate materials if we have one defined! - return !mMaterial; - } - - bool NXU_preNotifyActor( NxActorDesc &actor, const char *userProperties ) - { - // Set the right compartment. - actor.compartment = mCompartment; - - if ( actor.shapes.size() == 0 ) - Con::warnf( "PxMultiActor_Notify::NXU_preNotifyActor, got an actor (%s) with no shapes, was this intentional?", actor.name ); - - // For every shape, cast to its particular type - // and apply the scale to size, mass and localPosition. - for( S32 i = 0; i < actor.shapes.size(); i++ ) - { - // If we have material then set it. - if ( mMaterial ) - actor.shapes[i]->materialIndex = mMaterial->getMaterialId(); - - switch( actor.shapes[i]->getType() ) - { - case NX_SHAPE_BOX: - { - NxBoxShapeDesc *boxDesc = (NxBoxShapeDesc*)actor.shapes[i]; - - boxDesc->mass *= mMassScale; - - boxDesc->dimensions.x *= mScale.x; - boxDesc->dimensions.y *= mScale.y; - boxDesc->dimensions.z *= mScale.z; - - boxDesc->localPose.t.x *= mScale.x; - boxDesc->localPose.t.y *= mScale.y; - boxDesc->localPose.t.z *= mScale.z; - break; - } - - case NX_SHAPE_SPHERE: - { - NxSphereShapeDesc *sphereDesc = (NxSphereShapeDesc*)actor.shapes[i]; - - sphereDesc->mass *= mMassScale; - - // TODO: Spheres do not work with non-uniform - // scales very well... how do we fix this? - sphereDesc->radius *= mScale.x; - - sphereDesc->localPose.t.x *= mScale.x; - sphereDesc->localPose.t.y *= mScale.y; - sphereDesc->localPose.t.z *= mScale.z; - break; - } - - case NX_SHAPE_CAPSULE: - { - NxCapsuleShapeDesc *capsuleDesc = (NxCapsuleShapeDesc*)actor.shapes[i]; - - capsuleDesc->mass *= mMassScale; - - // TODO: Capsules do not work with non-uniform - // scales very well... how do we fix this? - capsuleDesc->radius *= mScale.x; - capsuleDesc->height *= mScale.y; - - capsuleDesc->localPose.t.x *= mScale.x; - capsuleDesc->localPose.t.y *= mScale.y; - capsuleDesc->localPose.t.z *= mScale.z; - break; - } - - default: - { - static String lookup[] = - { - "PLANE", - "SPHERE", - "BOX", - "CAPSULE", - "WHEEL", - "CONVEX", - "MESH", - "HEIGHTFIELD" - }; - - Con::warnf( "PxMultiActor_Notify::NXU_preNotifyActor, unsupported shape type (%s), on Actor (%s)", lookup[actor.shapes[i]->getType()].c_str(), actor.name ); - - delete actor.shapes[i]; - actor.shapes.erase( actor.shapes.begin() + i ); - --i; - break; - } - } - } - - NxBodyDesc *body = const_cast( actor.body ); - if ( body ) - { - // Must scale all of these parameters, else there will be odd results! - body->mass *= mMassScale; - body->massLocalPose.t.multiply( mMassScale, body->massLocalPose.t ); - body->massSpaceInertia.multiply( mMassScale, body->massSpaceInertia ); - - // Ragdoll damping! - //body->sleepDamping = 1.7f; - //body->linearDamping = 0.4f; - //body->angularDamping = 0.08f; - //body->wakeUpCounter = 0.3f; - } - - return true; - }; - -public: - - PxMultiActor_Notify( NxCompartment *compartment, - PxMaterial *material, - const NxMat34& mat, - const Point3F& scale, - Vector *actorProps = NULL, - Vector *jointProps = NULL ) - : mCompartment( compartment ), - mMaterial( material ), - mScale( scale ), - mTransform( mat ), - mActorUserProperties( actorProps ), - mJointUserProperties( jointProps ) - { - const F32 unit = VectorF( 1.0f, 1.0f, 1.0f ).len(); - mMassScale = mScale.len() / unit; - } - - virtual ~PxMultiActor_Notify() - { - } - - const Vector& getActors() { return mActors; } - const Vector& getShapes() { return mShapes; } - const Vector& getJoints() { return mJoints; } -}; - -ConsoleDocClass( PxMultiActorData, - - "@brief Defines the properties of a type of PxMultiActor.\n\n" - - "Usually it is prefered to use PhysicsShape rather than PxMultiActor because " - "a PhysicsShape is not PhysX specific and can be much easier to setup.\n\n" - - "For more information, refer to Nvidia's PhysX docs.\n\n" - - "@ingroup Physics" -); - -IMPLEMENT_CO_DATABLOCK_V1(PxMultiActorData); - -PxMultiActorData::PxMultiActorData() - : material( NULL ), - collection( NULL ), - waterDragScale( 1.0f ), - buoyancyDensity( 1.0f ), - angularDrag( 0.0f ), - linearDrag( 0.0f ), - clientOnly( false ), - singlePlayerOnly( false ), - shapeName( StringTable->insert( "" ) ), - physXStream( StringTable->insert( "" ) ), - breakForce( 0.0f ) -{ - for ( S32 i = 0; i < MaxCorrectionNodes; i++ ) - correctionNodeNames[i] = StringTable->insert( "" ); - - for ( S32 i = 0; i < MaxCorrectionNodes; i++ ) - correctionNodes[i] = -1; - - for ( S32 i = 0; i < NumMountPoints; i++ ) - { - mountNodeNames[i] = StringTable->insert( "" ); - mountPointNode[i] = -1; - } -} - -PxMultiActorData::~PxMultiActorData() -{ - if ( collection ) - NXU::releaseCollection( collection ); -} - -void PxMultiActorData::initPersistFields() -{ - Parent::initPersistFields(); - - addGroup("Media"); - addField( "shapeName", TypeFilename, Offset( shapeName, PxMultiActorData ), - "@brief Path to the .DAE or .DTS file to render.\n\n"); - endGroup("Media"); - - // PhysX collision properties. - addGroup( "Physics" ); - - addField( "physXStream", TypeFilename, Offset( physXStream, PxMultiActorData ), - "@brief .XML file containing data such as actors, shapes, and joints.\n\n" - "These files can be created using a free PhysX plugin for 3DS Max.\n\n"); - addField( "material", TYPEID< PxMaterial >(), Offset( material, PxMultiActorData ), - "@brief An optional PxMaterial to be used for the PxMultiActor.\n\n" - "Defines properties such as friction and restitution. " - "Unrelated to the material used for rendering. The physXStream will contain " - "defined materials that can be customized in 3DS Max. " - "To override the material for all physics shapes in the physXStream, specify a material here.\n\n"); - - addField( "noCorrection", TypeBool, Offset( noCorrection, PxMultiActorData ), - "@hide" ); - - UTF8 buff[256]; - for ( S32 i=0; i < MaxCorrectionNodes; i++ ) - { - //dSprintf( buff, sizeof(buff), "correctionNode%d", i ); - addField( buff, TypeString, Offset( correctionNodeNames[i], PxMultiActorData ), "@hide" ); - } - - for ( S32 i=0; i < NumMountPoints; i++ ) - { - //dSprintf( buff, sizeof(buff), "mountNode%d", i ); - addField( buff, TypeString, Offset( mountNodeNames[i], PxMultiActorData ), "@hide" ); - } - - addField( "angularDrag", TypeF32, Offset( angularDrag, PxMultiActorData ), - "@brief Value used to help calculate rotational drag force while submerged in water.\n\n"); - addField( "linearDrag", TypeF32, Offset( linearDrag, PxMultiActorData ), - "@brief Value used to help calculate linear drag force while submerged in water.\n\n"); - addField( "waterDragScale", TypeF32, Offset( waterDragScale, PxMultiActorData ), - "@brief Scale to apply to linear and angular dampening while submerged in water.\n\n "); - addField( "buoyancyDensity", TypeF32, Offset( buoyancyDensity, PxMultiActorData ), - "@brief The density used to calculate buoyant forces.\n\n" - "The result of the calculated buoyancy is relative to the density of the WaterObject the PxMultiActor is within.\n\n" - "@note This value is necessary because Torque 3D does its own buoyancy simulation. It is not handled by PhysX." - "@see WaterObject::density"); - - endGroup( "Physics" ); - - addField( "clientOnly", TypeBool, Offset( clientOnly, PxMultiActorData ), - "@hide"); - addField( "singlePlayerOnly", TypeBool, Offset( singlePlayerOnly, PxMultiActorData ), - "@hide"); - addField( "breakForce", TypeF32, Offset( breakForce, PxMultiActorData ), - "@brief Force required to break an actor.\n\n" - "This value does not apply to joints. " - "If an actor is associated with a joint it will break whenever the joint does. " - "This allows an actor \"not\" associated with a joint to also be breakable.\n\n"); -} - -void PxMultiActorData::packData(BitStream* stream) -{ - Parent::packData(stream); - - stream->writeString( shapeName ); - stream->writeString( physXStream ); - - if( stream->writeFlag( material ) ) - stream->writeRangedU32( packed ? SimObjectId( material ) : material->getId(), - DataBlockObjectIdFirst, DataBlockObjectIdLast ); - - if ( !stream->writeFlag( noCorrection ) ) - { - // Write the correction node indices for the client. - for ( S32 i = 0; i < MaxCorrectionNodes; i++ ) - stream->write( correctionNodes[i] ); - } - - for ( S32 i = 0; i < NumMountPoints; i++ ) - stream->write( mountPointNode[i] ); - - stream->write( waterDragScale ); - stream->write( buoyancyDensity ); - stream->write( angularDrag ); - stream->write( linearDrag ); - - stream->writeFlag( clientOnly ); - stream->writeFlag( singlePlayerOnly ); - stream->write( breakForce ); -} - -void PxMultiActorData::unpackData(BitStream* stream) -{ - Parent::unpackData(stream); - - shapeName = stream->readSTString(); - physXStream = stream->readSTString(); - - if( stream->readFlag() ) - material = (PxMaterial*)stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); - - noCorrection = stream->readFlag(); - if ( !noCorrection ) - { - for ( S32 i = 0; i < MaxCorrectionNodes; i++ ) - stream->read( &correctionNodes[i] ); - } - - for ( S32 i = 0; i < NumMountPoints; i++ ) - stream->read( &mountPointNode[i] ); - - stream->read( &waterDragScale ); - stream->read( &buoyancyDensity ); - stream->read( &angularDrag ); - stream->read( &linearDrag ); - - clientOnly = stream->readFlag(); - singlePlayerOnly = stream->readFlag(); - stream->read( &breakForce ); -} - -bool PxMultiActorData::preload( bool server, String &errorBuffer ) -{ - if ( !Parent::preload( server, errorBuffer ) ) - return false; - - // If the stream is null, exit. - if ( !physXStream || !physXStream[0] ) - { - errorBuffer = "PxMultiActorData::preload: physXStream is unset!"; - return false; - } - - // Set up our buffer for the binary stream filename path. - UTF8 binPhysXStream[260] = { 0 }; - const UTF8* ext = dStrrchr( physXStream, '.' ); - - // Copy the xml stream path except for the extension. - if ( ext ) - dStrncpy( binPhysXStream, physXStream, getMin( 260, ext - physXStream ) ); - else - dStrncpy( binPhysXStream, physXStream, 260 ); - - // Concatenate the binary extension. - dStrcat( binPhysXStream, ".nxb" ); - - // Get the modified times of the two files. - FileTime xmlTime = {0}, binTime = {0}; - Platform::getFileTimes( physXStream, NULL, &xmlTime ); - Platform::getFileTimes( binPhysXStream, NULL, &binTime ); - - // If the binary is newer... load that. - if ( Platform::compareFileTimes( binTime, xmlTime ) >= 0 ) - _loadCollection( binPhysXStream, true ); - - // If the binary failed... then load the xml. - if ( !collection ) - { - _loadCollection( physXStream, false ); - - // If loaded... resave the xml in binary format - // for quicker subsequent loads. - if ( collection ) - NXU::saveCollection( collection, binPhysXStream, NXU::FT_BINARY ); - } - - // If it still isn't loaded then we've failed! - if ( !collection ) - { - errorBuffer = String::ToString( "PxMultiActorDatas::preload: could not load '%s'!", physXStream ); - return false; - } - - if (!shapeName || shapeName[0] == '\0') - { - errorBuffer = "PxMultiActorDatas::preload: no shape name!"; - return false; - } - - shape = ResourceManager::get().load( shapeName ); - - if (bool(shape) == false) - { - errorBuffer = String::ToString( "PxMultiActorData::preload: unable to load shape: %s", shapeName ); - return false; - } - - // Find the client side material. - if ( !server && material ) - Sim::findObject( SimObjectId(material), material ); - - // Get the ignore node indexes from the names. - for ( S32 i = 0; i < MaxCorrectionNodes; i++ ) - { - if( !correctionNodeNames[i] || !correctionNodeNames[i][0] ) - continue; - - correctionNodes[i] = shape->findNode( correctionNodeNames[i] ); - } - - // Resolve mount point node indexes - for ( S32 i = 0; i < NumMountPoints; i++) - { - char fullName[256]; - - if ( !mountNodeNames[i] || !mountNodeNames[i][0] ) - { - dSprintf(fullName,sizeof(fullName),"mount%d",i); - mountPointNode[i] = shape->findNode(fullName); - } - else - mountPointNode[i] = shape->findNode(mountNodeNames[i]); - } - - // Register for file change notification to reload the collection - if ( server ) - Torque::FS::AddChangeNotification( physXStream, this, &PxMultiActorData::_onFileChanged ); - - return true; -} - -void PxMultiActorData::_onFileChanged( const Torque::Path &path ) -{ - reload(); -} - -void PxMultiActorData::reload() -{ - bool result = _loadCollection( physXStream, false ); - - if ( !result ) - Con::errorf( "PxMultiActorData::reload(), _loadCollection failed..." ); - - // Inform MultiActors who use this datablock to reload. - mReloadSignal.trigger(); -} - -bool PxMultiActorData::_loadCollection( const UTF8 *path, bool isBinary ) -{ - if ( collection ) - { - NXU::releaseCollection( collection ); - collection = NULL; - } - - FileStream fs; - if ( !fs.open( path, Torque::FS::File::Read ) ) - return false; - - // Load the data into memory. - U32 size = fs.getStreamSize(); - FrameTemp buff( size ); - fs.read( size, buff ); - - // If the stream didn't read anything, there's a problem. - if ( size <= 0 ) - return false; - - // Ok... try to load it. - collection = NXU::loadCollection( path, - isBinary ? NXU::FT_BINARY : NXU::FT_XML, - buff, - size ); - - return collection != NULL; -} - - -bool PxMultiActorData::createActors( NxScene *scene, - NxCompartment *compartment, - const NxMat34 *nxMat, - const Point3F& scale, - Vector *outActors, - Vector *outShapes, - Vector *outJoints, - Vector *outActorUserProperties, - Vector *outJointUserProperties ) -{ - if ( !scene ) - { - Con::errorf( "PxMultiActorData::createActor() - returned null NxScene" ); - return NULL; - } - - PxMultiActor_Notify pxNotify( compartment, material, *nxMat, scale, outActorUserProperties, outJointUserProperties ); - - NXU::instantiateCollection( collection, *gPhysicsSDK, scene, nxMat, &pxNotify ); - - *outActors = pxNotify.getActors(); - *outJoints = pxNotify.getJoints(); - if ( outShapes ) - *outShapes = pxNotify.getShapes(); - - if ( outActors->empty() ) - { - Con::errorf( "PxMultiActorData::createActors() - NXUStream notifier returned empty actors or joints!" ); - return false; - } - - return true; -} - -ConsoleDocClass( PxMultiActor, - - "@brief Represents a destructible physical object simulated using PhysX.\n\n" - - "Usually it is prefered to use PhysicsShape and not PxMultiActor because " - "it is not PhysX specific and much easier to setup.\n" - - "@see PxMultiActorData.\n" - "@ingroup Physics" -); - -IMPLEMENT_CO_NETOBJECT_V1(PxMultiActor); - -PxMultiActor::PxMultiActor() - : mShapeInstance( NULL ), - mRootActor( NULL ), - mWorld( NULL ), - mStartImpulse( 0, 0, 0 ), - mResetXfm( true ), - mActorScale( 0, 0, 0 ), - mDebugRender( false ), - mIsDummy( false ), - mBroken( false ), - mDataBlock( NULL ) -{ - mNetFlags.set( Ghostable | ScopeAlways ); - - mTypeMask |= StaticObjectType | StaticShapeObjectType; - - //mUserData.setObject( this ); -} - -void PxMultiActor::initPersistFields() -{ - Parent::initPersistFields(); - - /* - // We're overloading these fields from SceneObject - // in order to force it to go thru setTransform! - removeField( "position" ); - removeField( "rotation" ); - removeField( "scale" ); - - addGroup( "Transform" ); - - addProtectedField( "position", TypeMatrixPosition, 0, - &PxMultiActor::_setPositionField, - &PxMultiActor::_getPositionField, - "" ); - - addProtectedField( "rotation", TypeMatrixRotation, 0, - &PxMultiActor::_setRotationField, - &PxMultiActor::_getRotationField, - "" ); - - addField( "scale", TypePoint3F, Offset( mObjScale, PxMultiActor ) ); - - endGroup( "Transform" ); - */ - - //addGroup("Physics"); - // addField( "AngularDrag", TypeF32, ) - //endGroup("Physics"); - - addGroup( "Debug" ); - addField( "debugRender", TypeBool, Offset( mDebugRender, PxMultiActor ), "@hide"); - addField( "broken", TypeBool, Offset( mBroken, PxMultiActor ), "@hide"); - endGroup( "Debug" ); - - //addGroup("Collision"); - //endGroup("Collision"); -} - -bool PxMultiActor::onAdd() -{ - PROFILE_SCOPE( PxMultiActor_OnAdd ); - - if (!Parent::onAdd() || !mDataBlock ) - return false; - - mIsDummy = isClientObject() && PHYSICSMGR->isSinglePlayer(); //&& mDataBlock->singlePlayerOnly; - - mShapeInstance = new TSShapeInstance( mDataBlock->shape, isClientObject() ); - - mObjBox = mDataBlock->shape->bounds; - resetWorldBox(); - - addToScene(); - - String worldName = isServerObject() ? "server" : "client"; - - // SinglePlayer objects only have server-side physics representations. - if ( mIsDummy ) - worldName = "server"; - - mWorld = dynamic_cast( PHYSICSMGR->getWorld( worldName ) ); - if ( !mWorld || !mWorld->getScene() ) - { - Con::errorf( "PxMultiActor::onAdd() - PhysXWorld not initialized!" ); - return false; - } - - applyWarp( getTransform(), true, false ); - mResetXfm = getTransform(); - - if ( !_createActors( getTransform() ) ) - { - Con::errorf( "PxMultiActor::onAdd(), _createActors failed" ); - return false; - } - - if ( !mIsDummy ) - mDataBlock->mReloadSignal.notify( this, &PxMultiActor::onFileNotify ); - - // If the editor is on... let it know! - //if ( gEditingMission ) - //onEditorEnable(); // TODO: Fix this up. - - PhysicsPlugin::getPhysicsResetSignal().notify( this, &PxMultiActor::onPhysicsReset, 1050.0f ); - - setAllBroken( false ); - - if ( isServerObject() ) - scriptOnAdd(); - - return true; -} - - -void PxMultiActor::onRemove() -{ - removeFromScene(); - - _destroyActors(); - mWorld = NULL; - - SAFE_DELETE( mShapeInstance ); - - PhysicsPlugin::getPhysicsResetSignal().remove( this, &PxMultiActor::onPhysicsReset ); - - if ( !mIsDummy && mDataBlock ) - mDataBlock->mReloadSignal.remove( this, &PxMultiActor::onFileNotify ); - - Parent::onRemove(); -} - -void PxMultiActor::_destroyActors() -{ - // Dummies don't have physics objects. - if ( mIsDummy || !mWorld ) - return; - - mWorld->releaseWriteLock(); - - // Clear the root actor. - mRootActor = NULL; - - // Clear the relative transforms. - //mRelXfms.clear(); - - // The shapes are owned by the actors, so - // we just need to clear them. - mShapes.clear(); - - // Release the joints first. - for( S32 i = 0; i < mJoints.size(); i++ ) - { - NxJoint *joint = mJoints[i]; - - if ( !joint ) - continue; - - // We allocate per joint userData and we must free it. - PxUserData *jointData = PxUserData::getData( *joint ); - if ( jointData ) - delete jointData; - - mWorld->releaseJoint( *joint ); - } - mJoints.clear(); - - // Now release the actors. - for( S32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - - PxUserData *actorData = PxUserData::getData( *actor ); - if ( actorData ) - delete actorData; - - if ( actor ) - mWorld->releaseActor( *actor ); - } - mActors.clear(); -} - -bool PxMultiActor::_createActors( const MatrixF &xfm ) -{ - if ( mIsDummy ) - { - // Dummies don't have physics objects, but - // they do handle actor deltas. - - PxMultiActor *serverObj = static_cast( mServerObject.getObject() ); - mActorDeltas.setSize( serverObj->mActors.size() ); - dMemset( mActorDeltas.address(), 0, mActorDeltas.memSize() ); - - return true; - } - - NxMat34 nxMat; - nxMat.setRowMajor44( xfm ); - - // Store the scale for comparison in setScale(). - mActorScale = getScale(); - - // Release the write lock so we can create actors. - mWorld->releaseWriteLock(); - - Vector actorUserProperties; - Vector jointUserProperties; - bool created = mDataBlock->createActors( mWorld->getScene(), - NULL, - &nxMat, - mActorScale, - &mActors, - &mShapes, - &mJoints, - &actorUserProperties, - &jointUserProperties ); - - // Debug output... - //for ( U32 i = 0; i < mJoints.size(); i++ ) - // Con::printf( "Joint0 name: '%s'", mJoints[i]->getName() ); - //for ( U32 i = 0; i < actorUserProperties.size(); i++ ) - //Con::printf( "actor%i UserProperties: '%s'", i, actorUserProperties[i].c_str() ); - //for ( U32 i = 0; i < jointUserProperties.size(); i++ ) - // Con::printf( "joint%i UserProperties: '%s'", i, jointUserProperties[i].c_str() ); - - if ( !created ) - { - Con::errorf( "PxMultiActor::_createActors() - failed!" ); - return false; - } - - // Make the first actor the root actor by default, but - // if we have a kinematic actor then use that. - mRootActor = mActors[0]; - for ( S32 i = 0; i < mActors.size(); i++ ) - { - if ( mActors[i]->readBodyFlag( NX_BF_KINEMATIC ) ) - { - mRootActor = mActors[i]; - break; - } - } - - mDelta.pos = mDelta.lastPos = getPosition(); - mDelta.rot = mDelta.lastRot = getTransform(); - - bool *usedActors = new bool[mActors.size()]; - dMemset( usedActors, 0, sizeof(bool) * mActors.size() ); - - TSShape *shape = mShapeInstance->getShape(); - - // Should already be done when actors are destroyed. - mMappedActors.clear(); - Vector mappedActorProperties; - - // Remap the actors to the shape instance's bone indices. - for( S32 i = 0; i < mShapeInstance->mNodeTransforms.size(); i++ ) - { - if ( !shape ) - break; - - UTF8 comparisonName[260] = { 0 }; - NxActor *actor = NULL; - NxActor *pushActor = NULL; - String actorProperties; - - S32 nodeNameIdx = shape->nodes[i].nameIndex; - const UTF8 *nodeName = shape->getName( nodeNameIdx ); - - S32 dl = -1; - dStrcpy( comparisonName, String::GetTrailingNumber( nodeName, dl ) ); //, ext - nodeName ); - dSprintf( comparisonName, sizeof( comparisonName ), "%s_pxactor", comparisonName ); - - //String test( nodeName ); - //AssertFatal( test.find("gableone",0,String::NoCase) == String::NPos, "found it" ); - - // If we find an actor that corresponds to this node we will - // push it back into the remappedActors vector, otherwise - // we will push back NULL. - for ( S32 j = 0; j < mActors.size(); j++ ) - { - actor = mActors[j]; - const UTF8 *actorName = actor->getName(); - - if ( dStricmp( comparisonName, actorName ) == 0 ) - { - pushActor = actor; - actorProperties = actorUserProperties[j]; - usedActors[j] = true; - break; - } - } - - mMappedActors.push_back( pushActor ); - mappedActorProperties.push_back( actorProperties ); - if ( !pushActor ) - dl = -1; - mMappedActorDL.push_back( dl ); - - // Increase the sleep tolerance. - if ( pushActor ) - { - //pushActor->raiseBodyFlag( NX_BF_ENERGY_SLEEP_TEST ); - //pushActor->setSleepEnergyThreshold( 2 ); - //pushActor->userData = NULL; - } - } - - // Delete any unused/orphaned actors. - for ( S32 i = 0; i < mActors.size(); i++ ) - { - if ( usedActors[i] ) - continue; - - NxActor *actor = mActors[i]; - - Con::errorf( "PxMultiActor::_createActors() - Orphan NxActor - '%s'!", actor->getName() ); - - if ( actor == mRootActor ) - { - Con::errorf( "PxMultiActor::_createActors() - root actor (%s) was orphan, cannot continue.", actor->getName() ); - return false; - } - - // Remove references to shapes of the deleted actor. - for ( S32 i = 0; i < mShapes.size(); i++ ) - { - if ( &(mShapes[i]->getActor()) == actor ) - { - mShapes.erase_fast(i); - i--; - } - } - - mWorld->releaseActor( *actor ); - } - - // Done with this helper. - delete [] usedActors; - - // Repopulate mActors with one entry per real actor we own. - mActors.clear(); - mMappedToActorIndex.clear(); - actorUserProperties.clear(); - for ( S32 i = 0; i < mMappedActors.size(); i++ ) - { - S32 index = -1; - if ( mMappedActors[i] ) - { - index = mActors.push_back_unique( mMappedActors[i] ); - while ( index >= actorUserProperties.size() ) - actorUserProperties.push_back( String::EmptyString ); - actorUserProperties[index] = mappedActorProperties[i]; - } - mMappedToActorIndex.push_back( index ); - } - - if ( mActors.size() == 0 ) - { - Con::errorf( "PxMultiActor::_createActors, got zero actors! Were all actors orphans?" ); - return false; - } - - // Initialize the actor deltas. - mActorDeltas.setSize( mActors.size() ); - dMemset( mActorDeltas.address(), 0, mActorDeltas.memSize() ); - - // Assign user data for actors. - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - if ( !actor ) - continue; - - actor->userData = _createActorUserData( actor, actorUserProperties[i] ); - } - - //NxActor *actor1; - //NxActor *actor2; - //PxUserData *pUserData; - - // Allocate user data for joints. - for ( U32 i = 0; i < mJoints.size(); i++ ) - { - NxJoint *joint = mJoints[i]; - if ( !joint ) - continue; - - joint->userData = _createJointUserData( joint, jointUserProperties[i] ); - - /* - // Set actors attached to joints as not-pushable (by the player). - joint->getActors( &actor1, &actor2 ); - if ( actor1 ) - { - pUserData = PxUserData::getData( *actor1 ); - if ( pUserData ) - pUserData->mCanPush = false; - } - if ( actor2 ) - { - pUserData = PxUserData::getData( *actor2 ); - if ( pUserData ) - pUserData->mCanPush = false; - } - */ - } - - // Set actors and meshes to the unbroken state. - setAllBroken( false ); - - return true; -} - -PxUserData* PxMultiActor::_createActorUserData( NxActor *actor, String &userProperties ) -{ - PxUserData *actorData = new PxUserData(); - actorData->setObject( this ); - - // We use this for saving relative xfms for 'broken' actors. - NxMat34 actorPose = actor->getGlobalPose(); - NxMat34 actorSpaceXfm; - actorPose.getInverse( actorSpaceXfm ); - - const String actorName( actor->getName() ); - - static const String showStr( "PxBrokenShow" ); - static const String hideStr( "PxBrokenHide" ); - - // 3DSMax saves out double newlines, replace them with one. - userProperties.replace( "\r\n", "\n" ); - - U32 propertyCount = StringUnit::getUnitCount( userProperties, "\n" ); - for ( U32 i = 0; i < propertyCount; i++ ) - { - String propertyStr = StringUnit::getUnit( userProperties, i, "\n" ); - U32 wordCount = StringUnit::getUnitCount( propertyStr, "=" ); - - if ( wordCount == 0 ) - { - // We sometimes get empty lines between properties, - // which doesn't break anything. - continue; - } - - if ( wordCount != 2 ) - { - Con::warnf( "PxMultiActor::_createActorUserData, malformed UserProperty string (%s) for actor (%s)", propertyStr.c_str(), actorName.c_str() ); - continue; - } - - String propertyName = StringUnit::getUnit( propertyStr, 0, "=" ); - String propertyValue = StringUnit::getUnit( propertyStr, 1, "=" ); - - Vector *dstVector = NULL; - if ( propertyName.equal( showStr, String::NoCase ) ) - dstVector = &actorData->mBrokenActors; - else if ( propertyName.equal( hideStr, String::NoCase ) ) - dstVector = &actorData->mUnbrokenActors; - - if ( !dstVector ) - continue; - - U32 valueCount = StringUnit::getUnitCount( propertyValue, "," ); - for ( U32 j = 0; j < valueCount; j++ ) - { - String val = StringUnit::getUnit( propertyValue, j, "," ); - - NxActor *pActor = _findActor( val ); - if ( !pActor ) - Con::warnf( "PxMultiActor::_createActorUserData, actor (%s) was not found when parsing UserProperties for actor (%s)", val.c_str(), actorName.c_str() ); - else - { - dstVector->push_back( pActor ); - - if ( dstVector == &actorData->mBrokenActors ) - { - NxMat34 relXfm = pActor->getGlobalPose(); - relXfm.multiply( relXfm, actorSpaceXfm ); - actorData->mRelXfm.push_back( relXfm ); - } - } - } - } - - // Only add a contact signal to this actor if - // we have objects we can break. - if ( actorData->mBrokenActors.size() > 0 && - mDataBlock->breakForce > 0.0f ) - { - actor->setContactReportFlags( NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD | NX_NOTIFY_FORCES ); - actor->setContactReportThreshold( mDataBlock->breakForce ); - actorData->getContactSignal().notify( this, &PxMultiActor::_onContact ); - } - - return actorData; -} - -PxUserData* PxMultiActor::_createJointUserData( NxJoint *joint, String &userProperties ) -{ - PxUserData *jointData = new PxUserData(); - jointData->setObject( this ); - - // We use this for saving relative xfms for 'broken' actors. - NxActor *actor0; - NxActor *actor1; - joint->getActors( &actor0, &actor1 ); - NxMat34 actorPose = actor0->getGlobalPose(); - NxMat34 actorSpaceXfm; - actorPose.getInverse( actorSpaceXfm ); - - // The PxMultiActor will live longer than the joint - // so this notify shouldn't ever need to be removed. Although if someone - // other than this multiactor were to register for this notify and their - // lifetime could be shorter, then 'they' might have to. - jointData->getOnJointBreakSignal().notify( this, &PxMultiActor::_onJointBreak ); - - // JCFHACK: put this in userProperties too. - Sim::findObject( "JointBreakEmitter", jointData->mParticleEmitterData ); - - String showStr( "PxBrokenShow" ); - String hideStr( "PxBrokenHide" ); - - // Max saves out double newlines, replace them with one. - userProperties.replace( "\r\n", "\n" ); - - U32 propertyCount = StringUnit::getUnitCount( userProperties, "\n" ); - for ( U32 i = 0; i < propertyCount; i++ ) - { - String propertyStr = StringUnit::getUnit( userProperties, i, "\n" ); - U32 wordCount = StringUnit::getUnitCount( propertyStr, "=" ); - - if ( wordCount == 0 ) - { - // We sometimes get empty lines between properties, - // which doesn't break anything. - continue; - } - - if ( wordCount != 2 ) - { - Con::warnf( "PxMultiActor::_createJointUserData, malformed UserProperty string (%s) for joint (%s)", propertyStr.c_str(), joint->getName() ); - continue; - } - - String propertyName = StringUnit::getUnit( propertyStr, 0, "=" ); - String propertyValue = StringUnit::getUnit( propertyStr, 1, "=" ); - - Vector *dstVector = NULL; - if ( propertyName.equal( showStr, String::NoCase ) ) - dstVector = &jointData->mBrokenActors; - else if ( propertyName.equal( hideStr, String::NoCase ) ) - dstVector = &jointData->mUnbrokenActors; - - if ( !dstVector ) - continue; - - U32 valueCount = StringUnit::getUnitCount( propertyValue, "," ); - for ( U32 j = 0; j < valueCount; j++ ) - { - String val = StringUnit::getUnit( propertyValue, j, "," ); - - NxActor *pActor = _findActor( val ); - if ( !pActor ) - Con::warnf( "PxMultiActor::_createJointUserData, actor (%s) was not found when parsing UserProperties for joint (%s)", val.c_str(), joint->getName() ); - else - { - dstVector->push_back( pActor ); - - if ( dstVector == &jointData->mBrokenActors ) - { - NxMat34 relXfm = pActor->getGlobalPose(); - relXfm.multiply( relXfm, actorSpaceXfm ); - jointData->mRelXfm.push_back( relXfm ); - } - } - } - } - - return jointData; -} - -NxActor* PxMultiActor::_findActor( const String &actorName ) const -{ - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - if ( !actor ) - continue; - - if ( dStricmp( actor->getName(), actorName ) == 0 ) - return actor; - } - - return NULL; -} - -String PxMultiActor::_getMeshName( const NxActor *actor ) const -{ - String meshName = actor->getName(); - meshName.replace( "_pxactor", "" ); - //meshName = StringUnit::getUnit( meshName, 0, "_" ); - return meshName; -} - -bool PxMultiActor::onNewDataBlock( GameBaseData *dptr, bool reload ) -{ - mDataBlock = dynamic_cast(dptr); - - if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) ) - return false; - - // JCF: if we supported it, we would recalculate the value of mIsDummy now, - // but that would really hose everything since an object that was a dummy - // wouldn't have any actors and would need to create them, etc... - - scriptOnNewDataBlock(); - - return true; -} - -void PxMultiActor::inspectPostApply() -{ - // Make sure we call the parent... else - // we won't get transform and scale updates! - Parent::inspectPostApply(); - - //setMaskBits( LightMask ); - setMaskBits( UpdateMask ); -} - -void PxMultiActor::onStaticModified( const char *slotName, const char *newValue ) -{ - if ( isProperlyAdded() && dStricmp( slotName, "broken" ) == 0 ) - setAllBroken( dAtob(newValue) ); -} - -void PxMultiActor::onDeleteNotify( SimObject *obj ) -{ - Parent::onDeleteNotify(obj); - if ( obj == mMount.object ) - unmount(); -} - -void PxMultiActor::onFileNotify() -{ - // Destroy the existing actors and recreate them... - - mWorld->getPhysicsResults(); - _destroyActors(); - _createActors( mResetXfm ); -} - -void PxMultiActor::onPhysicsReset( PhysicsResetEvent reset ) -{ - // Dummies don't create or destroy actors, they just reuse the - // server object's ones. - if ( mIsDummy ) - return; - - // Store the reset transform for later use. - if ( reset == PhysicsResetEvent_Store ) - { - mRootActor->getGlobalPose().getRowMajor44( mResetXfm ); - } - else if ( reset == PhysicsResetEvent_Restore ) - { - // Destroy the existing actors and recreate them to - // ensure they are in the proper mission startup state. - mWorld->getPhysicsResults(); - - _destroyActors(); - _createActors( mResetXfm ); - } - - for ( U32 i = 0; i < mActors.size(); i++ ) - { - if ( !mActors[i] ) - continue; - - mActors[i]->wakeUp(); - } -} - -void PxMultiActor::prepRenderImage( SceneRenderState *state ) -{ - PROFILE_SCOPE( PxMultiActor_PrepRenderImage ); - - if ( !mShapeInstance ) - return; - - Point3F cameraOffset; - getTransform().getColumn(3,&cameraOffset); - cameraOffset -= state->getDiffuseCameraPosition(); - F32 dist = cameraOffset.len(); - if ( dist < 0.01f ) - dist = 0.01f; - - F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); - - S32 dl = mShapeInstance->setDetailFromDistance( state, dist * invScale ); - if ( dl < 0 ) - return; - - GFXTransformSaver saver; - - // Set up our TS render state here. - TSRenderState rdata; - rdata.setSceneState( state ); - - // We might have some forward lit materials - // so pass down a query to gather lights. - LightQuery query; - query.init( getWorldSphere() ); - rdata.setLightQuery( &query ); - - MatrixF mat = getRenderTransform(); - mat.scale( getScale() ); - GFX->setWorldMatrix( mat ); - - if ( mDebugRender || Con::getBoolVariable( "$PxDebug::render", false ) ) - { - ObjectRenderInst *ri = state->getRenderPass()->allocInst(); - ri->renderDelegate.bind( this, &PxMultiActor::_debugRender ); - ri->type = RenderPassManager::RIT_Object; - state->getRenderPass()->addInst( ri ); - } - else - mShapeInstance->render( rdata ); -} - -void PxMultiActor::_debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ) -{ - if ( mShapeInstance ) - { - GFXTransformSaver saver; - - MatrixF mat = getRenderTransform(); - mat.scale( mObjScale ); - GFX->multWorld( mat ); - - //mShapeInstance->renderDebugNodes(); - } - - Vector *actors = &mActors; - if ( mIsDummy ) - { - PxMultiActor *serverObj = static_cast( mServerObject.getObject() ); - if ( serverObj ) - actors = &serverObj->mActors; - } - - if ( !actors ) - return; - - for ( U32 i = 0; i < actors->size(); i++ ) - { - NxActor *pActor = (*actors)[i]; - if ( !pActor ) - continue; - - PxUtils::drawActor( pActor ); - } -} - -void PxMultiActor::_onJointBreak( NxReal breakForce, NxJoint &brokenJoint ) -{ - // Dummies do not have physics objects - // and shouldn't receive this callback. - if ( mIsDummy ) - return; - - NxActor *actor0 = NULL; - NxActor *actor1 = NULL; - brokenJoint.getActors( &actor0, &actor1 ); - NxMat34 parentPose = actor0->getGlobalPose(); - - Point3F jointPos = pxCast( brokenJoint.getGlobalAnchor() ); - - PxUserData *jointData = PxUserData::getData( brokenJoint ); - setBroken( parentPose, NxVec3( 0.0f ), jointData, true ); - - // NOTE: We do not NULL the joint in the list, - // or release it here, as we allow it to be released - // by the _destroyActors function on a reset or destruction - // of the PxMultiActor. -} - -void PxMultiActor::_onContact( PhysicsUserData *us, - PhysicsUserData *them, - const Point3F &hitPoint, - const Point3F &hitForce ) -{ - PxUserData *data = (PxUserData*)us; - if ( data && - !data->mIsBroken && - hitForce.len() > mDataBlock->breakForce ) - setAllBroken( true ); -} - -U32 PxMultiActor::packUpdate(NetConnection *con, U32 mask, BitStream *stream) -{ - U32 retMask = Parent::packUpdate(con, mask, stream); - - stream->writeFlag( mDebugRender ); - - stream->writeFlag( mask & SleepMask ); - - if ( stream->writeFlag( mask & WarpMask ) ) - { - stream->writeAffineTransform( getTransform() ); - } - else if ( stream->writeFlag( mask & MoveMask ) ) - { - /* - stream->writeAffineTransform( getTransform() ); - - NxActor *actor = mActors[ mDataBlock->correctionNodes[0] ]; - - const NxVec3& linVel = actor->getLinearVelocity(); - stream->write( linVel.x ); - stream->write( linVel.y ); - stream->write( linVel.z ); - */ - } - - // This internally uses the mask passed to it. - if ( mLightPlugin ) - retMask |= mLightPlugin->packUpdate( this, LightMask, con, mask, stream ); - - return retMask; -} - - -void PxMultiActor::unpackUpdate(NetConnection *con, BitStream *stream) -{ - Parent::unpackUpdate(con, stream); - - mDebugRender = stream->readFlag(); - - if ( stream->readFlag() ) // SleepMask - { - for ( S32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - - if ( !actor ) - continue; - - if ( actor ) - actor->putToSleep(); - } - } - - if ( stream->readFlag() ) // WarpMask - { - // If we set a warp mask, - // we need to instantly move - // the actor to the new position - // without applying any corrections. - MatrixF mat; - stream->readAffineTransform( &mat ); - - applyWarp( mat, true, false ); - } - else if ( stream->readFlag() ) // MoveMask - { - /* - MatrixF mat; - stream->readAffineTransform( &mat ); - - NxVec3 linVel, angVel; - stream->read( &linVel.x ); - stream->read( &linVel.y ); - stream->read( &linVel.z ); - - applyCorrection( mat, linVel, angVel ); - */ - } -/* - if ( stream->readFlag() ) // ImpulseMask - { - // TODO : Set up correction nodes. - - NxVec3 linVel; - stream->read( &linVel.x ); - stream->read( &linVel.y ); - stream->read( &linVel.z ); - - NxActor *actor = mActors[ mDataBlock->correctionNodes[0] ]; - - if ( actor ) - { - mWorld->releaseWriteLock(); - actor->setLinearVelocity( linVel ); - mStartImpulse.zero(); - } - else - mStartImpulse.set( linVel.x, linVel.y, linVel.z ); - } -*/ - if ( mLightPlugin ) - mLightPlugin->unpackUpdate( this, con, stream ); -} - -void PxMultiActor::setScale( const VectorF& scale ) -{ - if ( scale == getScale() ) - return; - - // This is so that the level - // designer can change the scale - // of a PhysXSingleActor in the editor - // and have the PhysX representation updated properly. - - // First we call the parent's setScale - // so that the ScaleMask can be set. - Parent::setScale( scale ); - - // Check to see if the scale has really changed. - if ( !isProperlyAdded() || mActorScale.equal( scale ) ) - return; - - // Recreate the physics actors. - _destroyActors(); - _createActors( getTransform() ); -} - -void PxMultiActor::applyWarp( const MatrixF& newMat, bool interpRender, bool sweep ) -{ - // Do we have actors to move? - if ( mRootActor ) - { - // Get ready to change the physics state. - mWorld->releaseWriteLock(); - - /// Convert the new transform to nx. - NxMat34 destXfm; - destXfm.setRowMajor44( newMat ); - - // Get the inverse of the root actor transform - // so we can move all the actors relative to it. - NxMat34 rootInverseXfm; - mRootActor->getGlobalPose().getInverse( rootInverseXfm ); - - // Offset all the actors. - MatrixF tMat; - NxMat34 newXfm, relXfm; - for ( S32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - if ( !actor ) - continue; - - const bool isKinematic = actor->readBodyFlag( NX_BF_KINEMATIC ); - - // Stop any velocity on it. - if ( !isKinematic ) - { - actor->setAngularVelocity( NxVec3( 0.0f ) ); - actor->setLinearVelocity( NxVec3( 0.0f ) ); - } - - // Get the transform relative to the current root. - relXfm.multiply( actor->getGlobalPose(), rootInverseXfm ); - - /* - if ( sweep ) - { - actor->getGl obalPose().getRowMajor44( mResetPos[i] ); - sweepTest( &newMat ); - } - */ - - // - newXfm.multiply( relXfm, destXfm ); - //if ( isKinematic ) - //actor->moveGlobalPose( newXfm ); - //else - actor->setGlobalPose( newXfm ); - - // Reset the delta. - Delta &delta = mActorDeltas[i]; - delta.pos = pxCast( newXfm.t ); - newXfm.getRowMajor44( tMat ); - delta.rot.set( tMat ); - - if ( !interpRender ) - { - mActorDeltas[i].lastPos = mActorDeltas[i].pos; - mActorDeltas[i].lastRot = mActorDeltas[i].rot; - } - } - } - - Parent::setTransform( newMat ); - - mDelta.pos = newMat.getPosition(); - mDelta.rot = newMat; - - if ( !interpRender ) - { - mDelta.lastPos = mDelta.pos; - mDelta.lastRot = mDelta.rot; - } -} - -/* -bool PxMultiActor::_setPositionField( void *obj, const char *data ) -{ - PxMultiActor *object = reinterpret_cast( obj ); - - MatrixF transform( object->getTransform() ); - Con::setData( TypeMatrixPosition, &transform, 0, 1, &data ); - - object->setTransform( transform ); - - return false; -} - -const char* PxMultiActor::_getPositionField( void *obj, const char *data ) -{ - PxMultiActor *object = reinterpret_cast( obj ); - return Con::getData( TypeMatrixPosition, - &object->mObjToWorld, - 0 ); -} - -bool PxMultiActor::_setRotationField( void *obj, const char *data ) -{ - PxMultiActor *object = reinterpret_cast( obj ); - - MatrixF transform( object->getTransform() ); - Con::setData( TypeMatrixRotation, &transform, 0, 1, &data ); - - object->setTransform( transform ); - - return false; -} - -const char* PxMultiActor::_getRotationField( void *obj, const char *data ) -{ - PxMultiActor *object = reinterpret_cast( obj ); - return Con::getData( TypeMatrixRotation, - &object->mObjToWorld, - 0 ); -} -*/ - -void PxMultiActor::setTransform( const MatrixF& mat ) -{ - applyWarp( mat, false, true ); - setMaskBits( WarpMask ); -} - -void PxMultiActor::mountObject( SceneObject *obj, U32 node ) -{ - if (obj->getObjectMount()) - obj->unmount(); - - obj->mountObject( this, (node >= 0 && node < PxMultiActorData::NumMountPoints) ? node: 0 ); -} - - -void PxMultiActor::unmountObject( SceneObject *obj ) -{ - obj->unmountObject( this ); -} - -bool PxMultiActor::_getNodeTransform( U32 nodeIdx, MatrixF *outXfm ) -{ - if ( !mShapeInstance ) - return false; - - PxMultiActor *actorOwner = this; - if ( mIsDummy ) - { - actorOwner = static_cast( mServerObject.getObject() ); - if ( !actorOwner ) - return false; - } - - TSShape *shape = mShapeInstance->getShape(); - String nodeName = shape->getNodeName( nodeIdx ); - - NxActor *pActor = NULL; - UTF8 comparisonName[260] = { 0 }; - S32 dummy = -1; - - // Convert the passed node name to a valid actor name. - dStrcpy( comparisonName, String::GetTrailingNumber( nodeName, dummy ) ); - dSprintf( comparisonName, sizeof( comparisonName ), "%s_pxactor", comparisonName ); - - // If we have an actor with that name, we are done. - pActor = actorOwner->_findActor( comparisonName ); - if ( pActor ) - { - pActor->getGlobalPose().getRowMajor44( *outXfm ); - return true; - } - - // Check if the parent node has an actor... - - S32 parentIdx = shape->nodes[nodeIdx].parentIndex; - if ( parentIdx == -1 ) - return false; - - const String &parentName = shape->getNodeName( parentIdx ); - dStrcpy( comparisonName, String::GetTrailingNumber( parentName, dummy ) ); - dSprintf( comparisonName, sizeof( comparisonName ), "%s_pxactor", comparisonName ); - - pActor = actorOwner->_findActor( comparisonName ); - if ( !pActor ) - return false; - - MatrixF actorMat; - pActor->getGlobalPose().getRowMajor44( actorMat ); - - MatrixF nmat; - QuatF q; - TSTransform::setMatrix( shape->defaultRotations[nodeIdx].getQuatF(&q),shape->defaultTranslations[nodeIdx],&nmat); - *outXfm->mul( actorMat, nmat ); - - return true; -} - -void PxMultiActor::getMountTransform(U32 mountPoint,MatrixF* mat) -{ - // Returns mount point to world space transform - if (mountPoint < PxMultiActorData::NumMountPoints) { - S32 ni = mDataBlock->mountPointNode[mountPoint]; - if (ni != -1) { - if ( _getNodeTransform( ni, mat ) ) - return; - } - } - *mat = mObjToWorld; -} - -void PxMultiActor::getRenderMountTransform(U32 mountPoint,MatrixF* mat) -{ - // Returns mount point to world space transform - if (mountPoint < PxMultiActorData::NumMountPoints) { - S32 ni = mDataBlock->mountPointNode[mountPoint]; - if (ni != -1) { - if ( _getNodeTransform( ni, mat ) ) - return; - } - } - *mat = getRenderTransform(); -} - -void PxMultiActor::processTick( const Move *move ) -{ - PROFILE_SCOPE( PxMultiActor_ProcessTick ); - - // Set the last pos/rot to the - // values of the previous tick for interpolateTick. - mDelta.lastPos = mDelta.pos; - mDelta.lastRot = mDelta.rot; - - /* - NxActor *corrActor = mActors[ mDataBlock->correctionNodes[0] ]; - - if ( corrActor->isSleeping() || corrActor->readBodyFlag( NX_BF_FROZEN ) ) - { - if ( !mSleepingLastTick ) - setMaskBits( WarpMask | SleepMask ); - - mSleepingLastTick = true; - - // HACK! Refactor sleeping so that we don't - // sleep when only one correction actor does. - _updateBounds(); - - return; - } - - mSleepingLastTick = false; - */ - - MatrixF mat; - Vector *actors; - - if ( mIsDummy ) - { - PxMultiActor *serverObj = static_cast( mServerObject.getObject() ); - if ( !serverObj ) - return; - - mat = serverObj->getTransform(); - actors = &serverObj->mActors; - } - else - { - // Container buoyancy & drag - _updateContainerForces(); - - // Save the transform from the root actor. - mRootActor->getGlobalPose().getRowMajor44( mat ); - actors = &mActors; - } - - // Update the transform and the root delta. - Parent::setTransform( mat ); - mDelta.pos = mat.getPosition(); - mDelta.rot.set( mat ); - - // On the client we update the individual - // actor deltas as well for interpolation. - if ( isClientObject() ) - { - PROFILE_SCOPE( PxMultiActor_ProcessTick_UpdateDeltas ); - - for ( U32 i = 0; i < mActorDeltas.size(); i++ ) - { - if ( !(*actors)[i] ) - continue; - - Delta &delta = mActorDeltas[i]; - - // Store the last position. - delta.lastPos = delta.pos; - delta.lastRot = delta.rot; - - // Get the new position. - (*actors)[i]->getGlobalPose().getRowMajor44( (NxF32*)mat ); - - // Calculate the delta between the current - // global pose and the last global pose. - delta.pos = mat.getPosition(); - delta.rot.set( mat ); - } - } - - // Update the bounding box to match the physics. - _updateBounds(); - - // Set the MoveMask so this will be updated to the client. - //setMaskBits( MoveMask ); -} - -void PxMultiActor::interpolateTick( F32 delta ) -{ - PROFILE_SCOPE( PxMultiActor_InterpolateTick ); - - Point3F interpPos; - QuatF interpRot; - { - // Interpolate the position based on the delta. - interpPos.interpolate( mDelta.pos, mDelta.lastPos, delta ); - - // Interpolate the rotation based on the delta. - interpRot.interpolate( mDelta.rot, mDelta.lastRot, delta ); - - // Set up the interpolated transform. - MatrixF interpMat; - interpRot.setMatrix( &interpMat ); - interpMat.setPosition( interpPos ); - - Parent::setRenderTransform( interpMat ); - } - - PxMultiActor *srcObj = NULL; - if ( mIsDummy ) - srcObj = static_cast( mServerObject.getObject() ); - else - srcObj = this; - - // JCF: to disable applying NxActor positions to the renderable mesh - // you can uncomment this line. - //srcObj = NULL; - if ( mShapeInstance && srcObj != NULL ) - { - mShapeInstance->animate(); - getDynamicXfms( srcObj, delta ); - } -} - -/* -void PxMultiActor::sweepTest( MatrixF *mat ) -{ - NxVec3 nxCurrPos = getPosition(); - - // If the position is zero, - // the parent hasn't been updated yet - // and we don't even need to do the sweep test. - // This is a fix for a problem that was happening - // where on the add of the PhysXSingleActor, it would - // set the position to a very small value because it would be getting a hit - // even though the current position was 0. - if ( nxCurrPos.isZero() ) - return; - - // Set up the flags and the query structure. - NxU32 flags = NX_SF_STATICS | NX_SF_DYNAMICS; - - NxSweepQueryHit sweepResult; - dMemset( &sweepResult, 0, sizeof( sweepResult ) ); - - NxVec3 nxNewPos = mat->getPosition(); - - // Get the velocity which will be our sweep direction and distance. - NxVec3 nxDir = nxNewPos - nxCurrPos; - if ( nxDir.isZero() ) - return; - - NxActor *corrActor = mActors[ mDataBlock->correctionNodes[0] ]; - - // Get the scene and do the sweep. - corrActor->wakeUp(); - corrActor->linearSweep( nxDir, flags, NULL, 1, &sweepResult, NULL ); - - if ( sweepResult.hitShape && sweepResult.t < nxDir.magnitude() ) - { - nxDir.normalize(); - nxDir *= sweepResult.t; - nxCurrPos += nxDir; - - mat->setPosition( Point3F( nxCurrPos.x, nxCurrPos.y, nxCurrPos.z ) ); - } -} -*/ - -/* -void PxMultiActor::applyCorrection( const MatrixF& mat, const NxVec3& linVel, const NxVec3& angVel ) -{ - // Sometimes the actor hasn't been - // created yet during the call from unpackUpdate. - NxActor *corrActor = mActors[ mDataBlock->correctionNodes[0] ]; - - if ( !corrActor || mForceSleep ) - return; - - NxVec3 newPos = mat.getPosition(); - NxVec3 currPos = getPosition(); - - NxVec3 offset = newPos - currPos; - - // If the difference isn't large enough, - // just set the new transform, no correction. - if ( offset.magnitude() > 0.3f ) - { - // If we're going to set the linear or angular velocity, - // we do it before we add a corrective force, since it would be overwritten otherwise. - NxVec3 currLinVel, currAngVel; - currLinVel = corrActor->getLinearVelocity(); - currAngVel = corrActor->getAngularVelocity(); - - // Scale the corrective force by half, - // otherwise it will over correct and oscillate. - NxVec3 massCent = corrActor->getCMassGlobalPosition(); - corrActor->addForceAtPos( offset, massCent, NX_SMOOTH_VELOCITY_CHANGE ); - - // If the linear velocity is divergent enough, change to server linear velocity. - if ( (linVel - currLinVel).magnitude() > 0.3f ) - corrActor->setLinearVelocity( linVel ); - // Same for angular. - if ( (angVel - currAngVel).magnitude() > 0.3f ) - corrActor->setAngularVelocity( angVel ); - } - - Parent::setTransform( mat ); -} -*/ - -void PxMultiActor::_updateBounds() -{ - PROFILE_SCOPE( PxMultiActor_UpdateBounds ); - - if ( mIsDummy ) - { - PxMultiActor *serverObj = static_cast( mServerObject.getObject() ); - if ( !serverObj ) - return; - - mWorldBox = serverObj->getWorldBox(); - mWorldSphere = serverObj->getWorldSphere(); - mObjBox = serverObj->getObjBox(); - mRenderWorldBox = serverObj->getRenderWorldBox(); - mRenderWorldSphere = mWorldSphere; - - return; - } - - NxBounds3 bounds; - bounds.setEmpty(); - - NxBounds3 shapeBounds; - - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *pActor = mActors[i]; - - if ( !pActor || pActor->readActorFlag( NX_AF_DISABLE_COLLISION ) ) - continue; - - NxShape *const* pShapeArray = pActor->getShapes(); - U32 shapeCount = pActor->getNbShapes(); - for ( U32 i = 0; i < shapeCount; i++ ) - { - // Get the shape's bounds. - pShapeArray[i]->getWorldBounds( shapeBounds ); - - // Combine them into the total bounds. - bounds.combine( shapeBounds ); - } - } - - mWorldBox = pxCast( bounds ); - - mWorldBox.getCenter(&mWorldSphere.center); - mWorldSphere.radius = (mWorldBox.maxExtents - mWorldSphere.center).len(); - - mObjBox = mWorldBox; - mWorldToObj.mul(mObjBox); - - mRenderWorldBox = mWorldBox; - mRenderWorldSphere = mWorldSphere; -} - -void PxMultiActor::getDynamicXfms( PxMultiActor *srcObj, F32 dt ) -{ - PROFILE_SCOPE( PxMultiActor_getDynamicXfms ); - - Vector *torqueXfms = &mShapeInstance->mNodeTransforms; - const MatrixF &objectXfm = getRenderWorldTransform(); - - AssertFatal( torqueXfms->size() == srcObj->mMappedActors.size(), "The two skeletons are different!" ); - - TSShape *shape = mShapeInstance->getShape(); - - // TODO: We're currently preparing deltas and getting - // dynamic xforms even if the object isn't visible. - // we should probably try to delay all this until - // we're about to render. - // - /* - // TODO: Set up deltas! - if ( mCurrPos.empty() || mCurrRot.empty() ) - _prepareDeltas(); - */ - - MatrixF globalXfm; - MatrixF mat, tmp; - QuatF newRot; - Point3F newPos; - - S32 dl = mShapeInstance->getCurrentDetail(); - if ( dl < 0 ) - return; - - const String &detailName = shape->getName( shape->details[dl].nameIndex ); - S32 detailSize = -1; - String::GetTrailingNumber( detailName, detailSize ); - - for( S32 i = 0; i < srcObj->mMappedActors.size(); i++ ) - { - NxActor *actor = srcObj->mMappedActors[i]; - - if ( !actor || actor->readBodyFlag( NX_BF_KINEMATIC ) ) - continue; - - // see if the node at this index is part of the - // currently visible detail level. - if ( srcObj->mMappedActorDL[i] != detailSize ) - continue; - - // Get the right actor delta structure. - U32 index = srcObj->mMappedToActorIndex[i]; - const Delta &delta = mActorDeltas[index]; - - // Do the interpolation. - newRot.interpolate( delta.rot, delta.lastRot, dt ); - newRot.setMatrix( &globalXfm ); - newPos.interpolate( delta.pos, delta.lastPos, dt ); - globalXfm.setPosition( newPos ); - - (*torqueXfms)[i].mul( objectXfm, globalXfm ); - } -} - -void PxMultiActor::applyImpulse( const Point3F &pos, const VectorF &vec ) -{ - // TODO : Implement this based on correction nodes. - /* - if ( !mWorld || !mActor ) - return; - - mWorld->releaseWriteLock(); - - NxVec3 linVel = mActor->getLinearVelocity(); - NxVec3 nxVel( vel.x, vel.y, vel.z ); - - mActor->setLinearVelocity(linVel + nxVel); - */ - - // JCF: something more complex is required to apply forces / breakage - // on only individual actors, and we don't have enough data to do that - // within this method. - - if ( vec.len() > mDataBlock->breakForce ) - setAllBroken( true ); - - NxVec3 nxvec = pxCast( vec ); - NxVec3 nxpos = pxCast( pos ); - - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - if ( actor->isDynamic() && - !actor->readBodyFlag( NX_BF_KINEMATIC ) && - !actor->readActorFlag( NX_AF_DISABLE_COLLISION ) ) - { - actor->addForceAtPos( nxvec, nxpos, NX_IMPULSE ); - } - } - - //setMaskBits( ImpulseMask ); -} - -void PxMultiActor::applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude ) -{ - mWorld->releaseWriteLock(); - - // Find all currently enabled actors hit by the impulse radius... - Vector hitActors; - NxVec3 nxorigin = pxCast(origin); - NxSphere impulseSphere( nxorigin, radius ); - - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *pActor = mActors[i]; - - if ( pActor->readActorFlag( NX_AF_DISABLE_COLLISION ) || - !pActor->isDynamic() || - pActor->readBodyFlag( NX_BF_KINEMATIC ) ) - continue; - - U32 numShapes = pActor->getNbShapes(); - NxShape *const* pShapeArray = pActor->getShapes(); - - for ( U32 j = 0; j < numShapes; j++ ) - { - const NxShape *pShape = pShapeArray[j]; - - if ( pShape->checkOverlapSphere( impulseSphere ) ) - { - hitActors.push_back( pActor ); - break; - } - } - } - - // Apply forces to hit actors, but swap out for broken - // actors first if appropriate... - for ( U32 i = 0; i < hitActors.size(); i++ ) - { - NxActor *pActor = hitActors[i]; - - PxUserData *pUserData = PxUserData::getData( *pActor ); - - // TODO: We should calculate the real force accounting - // for falloff before we break things with it. - - // If we have enough force, and this is an actor that - // can be 'broken' by impacts, break it now. - if ( pUserData && - //pUserData->mCanPush && - pUserData->mBrokenActors.size() > 0 && - magnitude > mDataBlock->breakForce ) - { - setBroken( pActor->getGlobalPose(), - pActor->getLinearVelocity(), - pUserData, - true ); - - // apply force that would have been applied to this actor - // to the broken actors we just enabled. - - for ( U32 j = 0; j < pUserData->mBrokenActors.size(); j++ ) - { - NxActor *pBrokenActor = pUserData->mBrokenActors[j]; - _applyActorRadialForce( pBrokenActor, nxorigin, radius, magnitude ); - } - } - else - { - // Apply force to the actor. - _applyActorRadialForce( pActor, nxorigin, radius, magnitude ); - } - } -} - -void PxMultiActor::_applyActorRadialForce( NxActor *inActor, const NxVec3 &origin, F32 radius, F32 magnitude ) -{ - // TODO: We're not getting a good torque force - // out of explosions because we're not picking - // the nearest point on the actor to the origin - // of the radial force. - - NxVec3 force = inActor->getCMassGlobalPosition() - origin; - NxF32 dist = force.magnitude(); - force.normalize(); - - if ( dist == 0.0f ) - force *= magnitude; - else - force *= mClampF( radius / dist, 0.0f, 1.0f ) * magnitude; - - // HACK: Make the position we push the force thru between the - // actor pos and its center of mass. This gives us some - // rotational force as well as make the covered structure - // explode better. - NxVec3 forcePos = ( inActor->getGlobalPosition() + inActor->getCMassGlobalPosition() ) / 2.0f; - inActor->addForceAtPos( force, forcePos, NX_VELOCITY_CHANGE ); -} - -void PxMultiActor::_updateContainerForces() -{ - if ( !mWorld->getEnabled() ) - return; - - PROFILE_SCOPE( PxMultiActor_updateContainerForces ); - - // Update container drag and buoyancy properties ( for each Actor ) - - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *pActor = mActors[i]; - - if ( !pActor || - pActor->readBodyFlag(NX_BF_KINEMATIC) || - pActor->readActorFlag(NX_AF_DISABLE_COLLISION) ) - continue; - - // Get world bounds of this actor ( the combination of all shape bounds ) - NxShape *const* shapes = pActor->getShapes(); - NxBounds3 bounds; - bounds.setEmpty(); - NxBounds3 shapeBounds; - - for ( U32 i = 0; i < pActor->getNbShapes(); i++ ) - { - NxShape *pShape = shapes[i]; - pShape->getWorldBounds(shapeBounds); - - bounds.combine( shapeBounds ); - } - - Box3F boundsBox = pxCast(bounds); - - ContainerQueryInfo info; - info.box = boundsBox; - info.mass = pActor->getMass(); - - // Find and retreive physics info from intersecting WaterObject(s) - mContainer->findObjects( boundsBox, WaterObjectType|PhysicalZoneObjectType, findRouter, &info ); - - // Calculate buoyancy and drag - F32 angDrag = mDataBlock->angularDrag; - F32 linDrag = mDataBlock->linearDrag; - F32 buoyancy = 0.0f; - - if ( true ) //info.waterCoverage >= 0.1f) - { - F32 waterDragScale = info.waterViscosity * mDataBlock->waterDragScale; - F32 powCoverage = mPow( info.waterCoverage, 0.25f ); - - if ( info.waterCoverage > 0.0f ) - { - //angDrag = mBuildAngDrag * waterDragScale; - //linDrag = mBuildLinDrag * waterDragScale; - angDrag = mLerp( angDrag, angDrag * waterDragScale, powCoverage ); - linDrag = mLerp( linDrag, linDrag * waterDragScale, powCoverage ); - } - - buoyancy = ( info.waterDensity / mDataBlock->buoyancyDensity ) * mPow( info.waterCoverage, 2.0f ); - } - - // Apply drag (dampening) - pActor->setLinearDamping( linDrag ); - pActor->setAngularDamping( angDrag ); - - // Apply buoyancy force - if ( buoyancy != 0 ) - { - // A little hackery to prevent oscillation - // Based on this blog post: - // (http://reinot.blogspot.com/2005/11/oh-yes-they-float-georgie-they-all.html) - // JCF: disabled! - NxVec3 gravity; - mWorld->getScene()->getGravity(gravity); - //NxVec3 velocity = pActor->getLinearVelocity(); - - NxVec3 buoyancyForce = buoyancy * -gravity * TickSec * pActor->getMass(); - //F32 currHeight = getPosition().z; - //const F32 C = 2.0f; - //const F32 M = 0.1f; - - //if ( currHeight + velocity.z * TickSec * C > info.waterHeight ) - // buoyancyForce *= M; - - pActor->addForceAtPos( buoyancyForce, pActor->getCMassGlobalPosition(), NX_IMPULSE ); - } - - // Apply physical zone forces - if ( info.appliedForce.len() > 0.001f ) - pActor->addForceAtPos( pxCast(info.appliedForce), pActor->getCMassGlobalPosition(), NX_IMPULSE ); - } -} - -/* -ConsoleMethod( PxMultiActor, applyImpulse, void, 3, 3, "applyImpulse - takes a velocity vector to apply") -{ - VectorF vec; - dSscanf( argv[2],"%g %g %g", - &vec.x,&vec.y,&vec.z ); - - object->applyImpulse( vec ); -} -*/ - -void PxMultiActor::setAllBroken( bool isBroken ) -{ - PROFILE_SCOPE( PxMultiActor_SetAllBroken ); - - if ( mIsDummy ) - { - PxMultiActor *serverObj = static_cast( mServerObject.getObject() ); - serverObj->setAllBroken( isBroken ); - return; - } - - mWorld->releaseWriteLock(); - - NxActor *actor0 = NULL; - NxActor *actor1 = NULL; - NxMat34 parentPose; - - for ( U32 i = 0; i < mJoints.size(); i++ ) - { - NxJoint *joint = mJoints[i]; - if ( !joint ) - continue; - - PxUserData *jointData = PxUserData::getData( *joint ); - if ( !jointData ) - continue; - - joint->getActors( &actor0, &actor1 ); - parentPose = actor0->getGlobalPose(); - - setBroken( parentPose, NxVec3(0.0f), jointData, isBroken ); - } - - for ( U32 i = 0; i < mActors.size(); i++ ) - { - NxActor *actor = mActors[i]; - if ( !actor ) - continue; - - PxUserData *actorData = PxUserData::getData( *actor ); - if ( !actorData ) - continue; - - setBroken( actor->getGlobalPose(), - actor->getLinearVelocity(), - actorData, - isBroken ); - } -} - -void PxMultiActor::setBroken( const NxMat34 &parentPose, - const NxVec3 &parentVel, - PxUserData *userData, - bool isBroken ) -{ - PROFILE_SCOPE( PxMultiActor_SetBroken ); - - // TODO: This function is highly inefficent and - // way too complex to follow... the hacked single - // player mode doesn't help. - - // Be careful not to set something broken twice. - if ( isBroken && - userData->mIsBroken == isBroken ) - return; - - userData->mIsBroken = isBroken; - - Vector *hideActors = NULL; - Vector *showActors = NULL; - - if ( isBroken ) - { - hideActors = &userData->mUnbrokenActors; - showActors = &userData->mBrokenActors; - } - else - { - hideActors = &userData->mBrokenActors; - showActors = &userData->mUnbrokenActors; - } - - NxActor *pActor = NULL; - MatrixF tMat; - for ( U32 i = 0; i < hideActors->size(); i++ ) - { - pActor = (*hideActors)[i]; - - pActor->raiseActorFlag( NX_AF_DISABLE_COLLISION ); - pActor->raiseBodyFlag( NX_BF_KINEMATIC ); - pActor->putToSleep(); - - NxShape *const* pShapeArray = pActor->getShapes(); - U32 shapeCount = pActor->getNbShapes(); - for ( U32 i = 0; i < shapeCount; i++ ) - pShapeArray[i]->setFlag( NX_SF_DISABLE_RAYCASTING, true ); - - setMeshHidden( _getMeshName( pActor ), true ); - } - - // Get the client side delta array. - Vector *actorDeltas = NULL; - if ( isClientObject() ) - actorDeltas = &mActorDeltas; - else if ( isServerObject() && PHYSICSMGR->isSinglePlayer() ) - { - PxMultiActor *clientObj = static_cast( getClientObject() ); - if ( clientObj ) - actorDeltas = &clientObj->mActorDeltas; - } - U32 index; - - for ( U32 i = 0; i < showActors->size(); i++ ) - { - pActor = (*showActors)[i]; - - if ( showActors == &userData->mBrokenActors ) - { - NxMat34 pose; - pose.multiply( parentPose, userData->mRelXfm[i] ); - pActor->setGlobalPose( pose ); - - if ( actorDeltas ) - { - for ( U32 j=0; j < mMappedActors.size(); j++ ) - { - if ( mMappedActors[j] == pActor ) - { - index = mMappedToActorIndex[j]; - - // Reset the delta. - Delta &delta = (*actorDeltas)[index]; - delta.pos = pxCast( pose.t ); - pose.getRowMajor44( tMat ); - delta.rot.set( tMat ); - delta.lastPos = delta.pos; - delta.lastRot = delta.rot; - - break; - } - } - } - } - - pActor->clearActorFlag( NX_AF_DISABLE_COLLISION ); - pActor->clearBodyFlag( NX_BF_KINEMATIC ); - pActor->setLinearVelocity( parentVel ); - pActor->wakeUp(); - - NxShape *const* pShapeArray = pActor->getShapes(); - U32 shapeCount = pActor->getNbShapes(); - for ( U32 i = 0; i < shapeCount; i++ ) - pShapeArray[i]->setFlag( NX_SF_DISABLE_RAYCASTING, false ); - - setMeshHidden( _getMeshName(pActor), false ); - } -} - -void PxMultiActor::setAllHidden( bool hide ) -{ - for ( U32 i = 0; i < mShapeInstance->mMeshObjects.size(); i++ ) - mShapeInstance->setMeshForceHidden( i, hide ); -} - -ConsoleMethod( PxMultiActor, setAllHidden, void, 3, 3, "( bool )" - "@brief Hides or unhides all meshes contained in the PxMultiActor.\n\n" - "Hidden meshes will not be rendered.") -{ - object->setAllHidden( dAtob(argv[2]) ); -} - -void PxMultiActor::setMeshHidden( String namePrefix, bool hidden ) -{ - if ( isServerObject() && PHYSICSMGR->isSinglePlayer() ) - { - PxMultiActor *clientObj = static_cast( getClientObject() ); - if ( clientObj ) - clientObj->setMeshHidden( namePrefix, hidden ); - } - - for ( U32 i = 0; i < mShapeInstance->mMeshObjects.size(); i++ ) - { - String meshName = mShapeInstance->getShape()->getMeshName( i ); - - if ( meshName.find( namePrefix ) != String::NPos ) - { - mShapeInstance->setMeshForceHidden( i, hidden ); - return; - } - } - - Con::warnf( "PxMultiActor::setMeshHidden - could not find mesh containing substring (%s)", namePrefix.c_str() ); -} - -ConsoleMethod( PxMultiActor, setBroken, void, 3, 3, "( bool )" - "@brief Sets the PxMultiActor to a broken or unbroken state.\n\n") -{ - object->setAllBroken( dAtob( argv[2] ) ); -} - -void PxMultiActorData::dumpModel() -{ - TSShapeInstance *inst = new TSShapeInstance( shape, true ); - - String path = Platform::getMainDotCsDir(); - path += "/model.dump"; - - FileStream *st; - if((st = FileStream::createAndOpen( path, Torque::FS::File::Write )) != NULL) - { - if ( inst ) - inst->dump( *st ); - else - Con::errorf( "PxMultiActor::dumpModel, no ShapeInstance." ); - - delete st; - } - else - Con::errorf( "PxMultiActor::dumpModel, error opening dump file." ); -} - -ConsoleMethod( PxMultiActorData, dumpModel, void, 2, 2, - "@brief Dumps model hierarchy and details to a file.\n\n" - "The file will be created as \'model.dump\' in the game folder. " - "If model.dump already exists, it will be overwritten.\n\n") -{ - object->dumpModel(); -} - -ConsoleMethod( PxMultiActor, setMeshHidden, void, 4, 4, "(string meshName, bool isHidden)" - "@brief Prevents the provided mesh from being rendered.\n\n") -{ - object->setMeshHidden( argv[2], dAtob( argv[3] ) ); -} - -void PxMultiActor::listMeshes( const String &state ) const -{ - if ( mShapeInstance ) - mShapeInstance->listMeshes( state ); -} - -ConsoleMethod( PxMultiActor, listMeshes, void, 3, 3, "(enum Hidden/Shown/All)" - "@brief Lists all meshes of the provided type in the console window.\n\n" - "@param All Lists all of the %PxMultiActor's meshes.\n" - "@param Hidden Lists all of the %PxMultiActor's hidden meshes.\n" - "@param Shown Lists all of the %PxMultiActor's visible meshes.\n") -{ - object->listMeshes( argv[2] ); -}; - -ConsoleMethod( PxMultiActorData, reload, void, 2, 2, "" - "@brief Reloads all data used for the PxMultiActorData.\n\n" - "If the reload sucessfully completes, all PxMultiActor's will be notified.\n\n") -{ - object->reload(); -} diff --git a/Engine/source/T3D/physics/physx/pxMultiActor.h b/Engine/source/T3D/physics/physx/pxMultiActor.h deleted file mode 100644 index 891ca4ac8..000000000 --- a/Engine/source/T3D/physics/physx/pxMultiActor.h +++ /dev/null @@ -1,398 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PXMULTIACTOR_H -#define _PXMULTIACTOR_H - -#ifndef _GAMEBASE_H_ -#include "T3D/gameBase/gameBase.h" -#endif -#ifndef __RESOURCE_H__ -#include "core/resource.h" -#endif -#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_ -#include "T3D/physics/physicsPlugin.h" -#endif -#ifndef _PHYSX_H_ -#include "T3D/physics/physx/px.h" -#endif -#ifndef _STRINGUNIT_H_ -#include "core/strings/stringUnit.h" -#endif -#ifndef _PHYSICS_PHYSICSUSERDATA_H_ -#include "T3D/physics/physicsUserData.h" -#endif -#ifndef _TSSHAPE_H_ -#include "ts/tsShape.h" -#endif - - -class TSShapeInstance; -class BaseMatInstance; -class PxMultiActor; -class PxWorld; -class PxMaterial; -class NxScene; -class NxActor; -class NxShape; -class NxCompartment; -class NxJoint; -class NxMat34; -class NxVec3; -class ParticleEmitterData; - - -namespace NXU -{ - class NxuPhysicsCollection; -} - - -class PxUserData : public PhysicsUserData -{ -public: - - /// The constructor. - PxUserData() - : PhysicsUserData(), - mIsBroken( false ), - mParticleEmitterData( NULL ) - { - } - - static PxUserData* getData( const NxActor &actor ) - { - PxUserData *result = (PxUserData*)actor.userData; - - AssertFatal( !result || typeid( *result ) == typeid( PxUserData ), - "PxUserData::getData - The pointer is the wrong type!" ); - - return result; - } - - static PxUserData* getData( const NxJoint &joint ) - { - PxUserData *result = (PxUserData*)joint.userData; - - AssertFatal( !result || typeid( *result ) == typeid( PxUserData ), - "PxUserData::getData - The pointer is the wrong type!" ); - - return result; - } - - typedef Signal JointBreakSignal; - - JointBreakSignal& getOnJointBreakSignal() { return mOnJointBreakSignal; } - - // Breakable stuff... - Vector mUnbrokenActors; - Vector mBrokenActors; - Vector mRelXfm; - ParticleEmitterData *mParticleEmitterData; - bool mIsBroken; - JointBreakSignal mOnJointBreakSignal; -}; - - -class ParticleEmitterData; - -class PxMultiActorData : public GameBaseData -{ - typedef GameBaseData Parent; - -public: - - PxMultiActorData(); - virtual ~PxMultiActorData(); - - DECLARE_CONOBJECT(PxMultiActorData); - - static void initPersistFields(); - - void packData(BitStream* stream); - void unpackData(BitStream* stream); - - bool preload( bool server, String &errorBuffer ); - //bool onAdd(); - - void allocPrimBuffer( S32 overrideSize = -1 ); - - bool _loadCollection( const UTF8 *path, bool isBinary ); - - void _onFileChanged( const Torque::Path &path ); - - void reload(); - - void dumpModel(); - - Signal mReloadSignal; - -public: - - // Rendering - StringTableEntry shapeName; - Resource shape; - - PxMaterial *material; - - /// Filename to load the physics actor from. - StringTableEntry physXStream; - - enum - { - NumMountPoints = 32, - MaxCorrectionNodes = 2 - }; - - StringTableEntry correctionNodeNames[MaxCorrectionNodes]; - StringTableEntry mountNodeNames[NumMountPoints]; - S32 correctionNodes[MaxCorrectionNodes]; - S32 mountPointNode[NumMountPoints]; ///< Node index of mountPoint - - /// If true no network corrections will - /// be done during gameplay. - bool noCorrection; - - /// Physics collection that holds the actor - /// and all associated shapes and data. - NXU::NxuPhysicsCollection *collection; - - bool createActors( NxScene *scene, - NxCompartment *compartment, - const NxMat34 *nxMat, - const Point3F& scale, - Vector *outActors, - Vector *outShapes, - Vector *outJoints, - Vector *outActorUserProperties, - Vector *outJointUserProperties ); - - /// Angular and Linear Drag (dampening) is scaled by this when in water. - F32 waterDragScale; - - /// The density of this object (for purposes of buoyancy calculation only). - F32 buoyancyDensity; - - F32 angularDrag; - F32 linearDrag; - - /// If this flag is set to true, - /// the physics actors will only be - /// created on the client, and the server - /// object is only responsible for ghosting. - /// Objects with this flag set will never stop - /// the physics player from moving through them. - bool clientOnly; - - bool singlePlayerOnly; - - /// When applyImpulse is passed a force of this magnitude or greater - /// any actors hit by the force vector that have broken versions - /// will become 'broken'. - F32 breakForce; -}; - - -class PxMultiActor : public GameBase -{ - typedef GameBase Parent; - - enum MaskBits - { - MoveMask = Parent::NextFreeMask << 0, - WarpMask = Parent::NextFreeMask << 1, - LightMask = Parent::NextFreeMask << 2, - SleepMask = Parent::NextFreeMask << 3, - ForceSleepMask = Parent::NextFreeMask << 4, - ImpulseMask = Parent::NextFreeMask << 5, - UpdateMask = Parent::NextFreeMask << 6, - MountedMask = Parent::NextFreeMask << 7, - NextFreeMask = Parent::NextFreeMask << 8 - }; - -public: - - PxMultiActor(); - - DECLARE_CONOBJECT( PxMultiActor ); - static void initPersistFields(); - - // SimObject - bool onAdd(); - void onRemove(); - void inspectPostApply(); - void onPhysicsReset( PhysicsResetEvent reset ); - void onStaticModified( const char *slotName, const char *newValue ); - void onDeleteNotify( SimObject *obj ); - - // NetObject - U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream ); - void unpackUpdate( NetConnection *conn, BitStream *stream ); - - // SceneObject - void prepRenderImage( SceneRenderState *state ); - void setScale( const VectorF &scale ); - void setTransform( const MatrixF &mat ); - virtual void mountObject( SceneObject *obj, U32 node ); - virtual void unmountObject( SceneObject *obj ); - virtual void getMountTransform( U32 mountPoint, MatrixF *mat ); - virtual void getRenderMountTransform( U32 index, MatrixF *mat ); - - // GameBase - virtual bool onNewDataBlock( GameBaseData *dptr, bool reload ); - virtual void processTick( const Move *move ); - virtual void interpolateTick( F32 delta ); - virtual void applyImpulse( const Point3F &pos, const VectorF &vec ); - virtual void applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude ); - - /// PxMultiActor - /// @{ - - /// Set visibility of all broken/unbroken meshes to match this state. - void setAllBroken( bool isBroken ); - - /// Sets up actors and meshes associated with the passed joint to reflect - /// the desired state. - void setBroken( const NxMat34 &parentPose, - const NxVec3 &parentVel, - PxUserData *userData, - bool isBroken ); - - /// - void setMeshHidden( String namePrefix, bool hidden ); - - void setAllHidden( bool hide ); - - void listMeshes( const String &state ) const; - - void _onJointBreak( NxReal breakForce, NxJoint &brokenJoint ); - - void _onContact( PhysicsUserData *us, - PhysicsUserData *them, - const Point3F &hitPoint, - const Point3F &hitForce ); - - void applyWarp( const MatrixF& mat, bool interpRender, bool sweep ); - - void getDynamicXfms( PxMultiActor *srcObj, F32 dt ); - - /// @} - -protected: - - /// This creates the physics objects. - bool _createActors( const MatrixF &xfm ); - - /// Creates a PxUserData for a joint and parses userProperties into it. - PxUserData* _createJointUserData( NxJoint *joint, String &userProperties ); - - /// Creates a PxUserData and parses userProperties into it. - PxUserData* _createActorUserData( NxActor *actor, String &userProperties ); - - /// Called to cleanup the physics objects. - void _destroyActors(); - - NxActor* _findActor( const String &actorName ) const; - - /// Get the corresponding meshName for a given actor. - String _getMeshName( const NxActor *actor ) const; - - /// - void _updateBounds(); - - void _updateContainerForces(); - - void _debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat ); - - void onFileNotify(); - - void _applyActorRadialForce( NxActor *inActor, const NxVec3 &origin, F32 radius, F32 magnitude ); - - void _updateDeltas( bool clearDelta ); - - bool _getNodeTransform( U32 nodeIdx, MatrixF *outXfm ); - -protected: - - PxMultiActorData *mDataBlock; - - PxWorld *mWorld; - - Vector mActors; - Vector mMappedActors; - Vector mMappedToActorIndex; - Vector mMappedActorDL; - Vector mJoints; - Vector mShapes; - - /// This is the root actor whose transform is the - /// transform of this SceneObject. - NxActor *mRootActor; - - TSShapeInstance *mShapeInstance; - Resource mDebrisShape; - - struct Delta - { - Point3F pos; - Point3F lastPos; - QuatF rot; - QuatF lastRot; - }; - - Delta mDelta; - - Vector mActorDeltas; - - /// The transform of this actor when it was first - /// created. It is used to reset the physics state - /// when the editor is enabled. - MatrixF mResetXfm; - - - /// The userdata object assigned to all actors - /// and joints of this multi-actor. - //PxUserData mUserData; - - /// - //Vector mRelXfms; - - /// This is the scale the actors were built at and - /// is used to decide if we need to recreate them. - VectorF mActorScale; - //F32 mBuildAngDrag; - //F32 mBuildLinDrag; - - VectorF mStartImpulse; - - bool mDebugRender; - - /// A helper set to true if is a client object and - /// is a singlePlayerOnly object. - bool mIsDummy; - - /// Helper for - bool mBroken; -}; - -#endif // _PXMULTIACTOR_H - diff --git a/Engine/source/T3D/physics/physx/pxPlayer.cpp b/Engine/source/T3D/physics/physx/pxPlayer.cpp deleted file mode 100644 index cf4ca9038..000000000 --- a/Engine/source/T3D/physics/physx/pxPlayer.cpp +++ /dev/null @@ -1,428 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxPlayer.h" - -#include "T3D/physics/physicsPlugin.h" -#include "T3D/physics/physX/pxWorld.h" -#include "T3D/physics/physX/pxCasts.h" -#include "collision/collision.h" -//#include "gfx/gfxDrawUtil.h" -//#include "sim/netConnection.h" - - -PxPlayer::PxPlayer() - : PhysicsPlayer(), - mController( NULL ), - mWorld( NULL ), - mObject( NULL ), - mSkinWidth( 0.1f ), - mOriginOffset( 0.0f ) -{ - PHYSICSMGR->getPhysicsResetSignal().notify( this, &PxPlayer::_onPhysicsReset ); -} - -PxPlayer::~PxPlayer() -{ - _releaseController(); - PHYSICSMGR->getPhysicsResetSignal().remove( this, &PxPlayer::_onPhysicsReset ); -} - -void PxPlayer::_releaseController() -{ - if ( mController ) - { - mController->getActor()->userData = NULL; - mWorld->getStaticChangedSignal().remove( this, &PxPlayer::_onStaticChanged ); - mWorld->releaseController( *mController ); - mController = NULL; - } -} - -void PxPlayer::init( const char *type, - const Point3F &size, - F32 runSurfaceCos, - F32 stepHeight, - SceneObject *obj, - PhysicsWorld *world ) -{ - AssertFatal( obj, "PxPlayer::init - Got a null scene object!" ); - AssertFatal( world, "PxPlayer::init - Got a null world!" ); - AssertFatal( dynamic_cast( world ), "PxPlayer::init - The world is the wrong type!" ); - - // Cleanup any previous controller. - _releaseController(); - - mObject = obj; - mWorld = (PxWorld*)world; - mOriginOffset = size.z * 0.5f; - - //if ( dStricmp( type, "Capsule" ) == 0 ) - { - NxCapsuleControllerDesc desc; - desc.skinWidth = 0.05f; // Expose? - desc.radius = getMax( size.x, size.y ) * 0.5f; - desc.radius -= desc.skinWidth; - desc.height = size.z - ( desc.radius * 2.0f ); - desc.height -= desc.skinWidth * 2.0f; - - desc.climbingMode = CLIMB_CONSTRAINED; - desc.position.set( 0, 0, 0 ); - desc.upDirection = NX_Z; - desc.callback = this; // TODO: Fix this as well! - desc.slopeLimit = runSurfaceCos; - desc.stepOffset = stepHeight; - mController = mWorld->createController( desc ); - } - //else - { - //mColShape = new btBoxShape( btVector3( 0.5f, 0.5f, 1.0f ) ); - //mOriginOffset = 1.0f; - } - - mWorld->getStaticChangedSignal().notify( this, &PxPlayer::_onStaticChanged ); - - // Put the kinematic actor on group 29. - NxActor *kineActor = mController->getActor(); - kineActor->setGroup( 29 ); - NxShape *const *shapes = kineActor->getShapes(); - for ( U32 i=0; i < kineActor->getNbShapes(); i++ ) - shapes[i]->setGroup( 29 ); - - mUserData.setObject( obj ); - kineActor->userData = &mUserData; -} - -void PxPlayer::_onStaticChanged() -{ - mController->reportSceneChanged(); -} - -void PxPlayer::_onPhysicsReset( PhysicsResetEvent reset ) -{ - // The PhysX controller will crash out if it doesn't clear its - // list of static elements when they are deleted. By calling this - // on physics events we clear the cache and we don't get crashes. - // - // This all depends on not doing moves and sweeps when the - // simulation is paused... we need to stop operating. - - if ( mController ) - mController->reportSceneChanged(); -} - -Point3F PxPlayer::move( const VectorF &disp, CollisionList &outCol ) -{ - AssertFatal( mController, "PxPlayer::move - The controller is null!" ); - - // Return the last position if the simulation is stopped. - // - // See PxPlayer::_onPhysicsReset - if ( !mWorld->isEnabled() ) - { - Point3F newPos = pxCast( mController->getDebugPosition() ); - newPos.z -= mOriginOffset; - //outCol->point = newPos; - //outCol->normal.set( 0, 0, 1 ); - return newPos; - } - - mWorld->releaseWriteLock(); - - mCollisionList = &outCol; - - // PhysX 2.8.4 checks up an up displacement and if found will assume - // the player is flying and remove the step offset. If we have a small - // z displacement here, zero it out. - NxVec3 dispNx( disp.x, disp.y, disp.z ); - if (mIsZero(disp.z)) - dispNx.z = 0.0f; - - NxU32 activeGroups = 0xFFFFFFFF; - activeGroups &= ~( 1<<31 ); // Skip activeGroup for triggers ( 31 ) - activeGroups &= ~( 1<<30 ); // Skip activeGroup for debris / non interactive dynamics ( 30 ) - - NxU32 collisionFlags = NXCC_COLLISION_SIDES | NXCC_COLLISION_DOWN | NXCC_COLLISION_UP; - - mController->move( dispNx, activeGroups, 0.0001f, collisionFlags ); - - Point3F newPos = pxCast( mController->getDebugPosition() ); - newPos.z -= mOriginOffset; - - mCollisionList = NULL; - - return newPos; -} - -NxControllerAction PxPlayer::onShapeHit( const NxControllerShapeHit& hit ) -{ - if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions) - return NX_ACTION_NONE; - - NxActor *actor = &hit.shape->getActor(); - PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); - - if ( actor->readActorFlag( NX_AF_DISABLE_RESPONSE ) ) - return NX_ACTION_NONE; - - // Fill out the Collision - // structure for use later. - Collision &col = mCollisionList->increment(); - dMemset( &col, 0, sizeof( col ) ); - - col.normal = pxCast( hit.worldNormal ); - col.point.set( hit.worldPos.x, hit.worldPos.y, hit.worldPos.z ); - col.distance = hit.length; - if ( userData ) - col.object = userData->getObject(); - - // If the collision direction is sideways then modify the collision normal - // to remove any z component. This takes care of any sideways collisions - // with the round bottom of the capsule when it comes to the Player class - // velocity calculations. We want all sideways collisions to be treated - // as if they hit the side of a cylinder. - if (mIsZero(hit.dir.z)) - { - if (col.normal.z > 0.0f) - { - // This will only remove the z component of the collision normal - // for the bottom of the character controller, which would hit during - // a step. We'll leave the top hemisphere of the character's capsule - // alone as bumping one's head is an entirely different story. This - // helps with low doorways. - col.normal.z = 0.0f; - col.normal.normalizeSafe(); - } - } - else - { - // PhysX doesn't perform callbacks in its upwards collision check so if - // this isn't a sideways collision then it must be a downwards one. In this - // case we want to have the collision normal only point in the opposite direction. - // i.e. up If we include the sideways part of the normal then the Player class - // velocity calculations using this normal will affect the player's forwards - // momentum. This is especially noticable on stairs as the rounded bottom of - // the capsule slides up the corner of a stair. - col.normal.set(0.0f, 0.0f, 1.0f); - } - - /* - if ( userData && - userData->mCanPush && - actor->isDynamic() && - !actor->readBodyFlag( NX_BF_KINEMATIC ) && - !mDummyMove ) - { - NxActor *ctrlActor = mController->getActor(); - - // So the object is neither - // a static or a kinematic, - // meaning we need to figure out - // if we have enough force to push it. - - // Get the hit object's force - // and scale it by the amount - // that it's acceleration is going - // against our acceleration. - const Point3F &hitObjLinVel = pxCast( actor->getLinearVelocity() ); - - F32 hitObjMass = actor->getMass(); - - VectorF hitObjDeltaVel = hitObjLinVel * TickSec; - VectorF hitObjAccel = hitObjDeltaVel / TickSec; - - VectorF controllerLinVel = pxCast( controllerActor->getLinearVelocity() ); - VectorF controllerDeltaVel = controllerLinVel * TickSec; - VectorF controllerAccel = controllerDeltaVel / TickSec; - - Point3F hitObjForce = (hitObjMass * hitObjAccel); - Point3F playerForce = (controllerActor->getMass() * controllerAccel); - - VectorF normalizedObjVel( hitObjLinVel ); - normalizedObjVel.normalizeSafe(); - - VectorF normalizedPlayerVel( pxCast( controllerActor->getLinearVelocity() ) ); - normalizedPlayerVel.normalizeSafe(); - - F32 forceDot = mDot( normalizedObjVel, normalizedPlayerVel ); - - hitObjForce *= forceDot; - - playerForce = playerForce - hitObjForce; - - if ( playerForce.x > 0.0f || playerForce.y > 0.0f || playerForce.z > 0.0f ) - actor->addForceAtPos( NxVec3( playerForce.x, playerForce.y, playerForce.z ), actor->getCMassGlobalPosition() ); - - //Con::printf( "onShapeHit: %f %f %f", playerForce.x, playerForce.y, playerForce.z ); - } - */ - - return NX_ACTION_PUSH; -} - -NxControllerAction PxPlayer::onControllerHit( const NxControllersHit& hit ) -{ - if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions) - return NX_ACTION_NONE; - - NxActor *actor = hit.other->getActor(); - PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); - - if ( actor->readActorFlag( NX_AF_DISABLE_RESPONSE ) ) - return NX_ACTION_NONE; - - // For controller-to-controller hit we don't have an actual hit point, so all - // we can do is set the hit object. - Collision &col = mCollisionList->increment(); - dMemset( &col, 0, sizeof( col ) ); - if ( userData ) - col.object = userData->getObject(); - - return NX_ACTION_NONE; -} - -void PxPlayer::findContact( SceneObject **contactObject, - VectorF *contactNormal, - Vector *outOverlapObjects ) const -{ - AssertFatal( mController, "PxPlayer::findContact - The controller is null!" ); - - // See PxPlayer::_onPhysicsReset - if ( !mWorld->isEnabled() ) - return; - - // Calculate the sweep motion... - F32 halfCapSize = mOriginOffset; - F32 halfSmallCapSize = halfCapSize * 0.8f; - F32 diff = halfCapSize - halfSmallCapSize; - - const F32 mSkinWidth = 0.1f; - - F32 offsetDist = diff + mSkinWidth + 0.01f; - NxVec3 motion(0,0,-offsetDist); - - /* - // Construct the capsule... - F32 radius = mCapsuleController->getRadius(); - F32 halfHeight = mCapsuleController->getHeight() * 0.5f; - - NxCapsule capsule; - capsule.p0 = capsule.p1 = pxCast( mCapsuleController->getDebugPosition() ); - capsule.p0.z -= halfHeight; - capsule.p1.z += halfHeight; - capsule.radius = radius; - */ - - NxSweepQueryHit sweepHit; - NxU32 hitCount = mController->getActor()->linearSweep( motion, NX_SF_STATICS | NX_SF_DYNAMICS, NULL, 1, &sweepHit, NULL ); - - if ( hitCount > 0 ) - { - PhysicsUserData *data = PhysicsUserData::cast( sweepHit.hitShape->getActor().userData ); - if ( data ) - { - *contactObject = data->getObject(); - *contactNormal = pxCast( sweepHit.normal ); - } - } - - // Check for overlapped objects ( triggers ) - - if ( !outOverlapObjects ) - return; - - NxCapsuleShape *shape = reinterpret_cast( mController->getActor()->getShapes()[0] ); - NxCapsule worldCapsule; - shape->getWorldCapsule( worldCapsule ); - - // Test only against activeGroup with triggers ( 31 ). - NxU32 activeGroups = 1 << 31; - - NxShape *shapes[10]; - - hitCount = mWorld->getScene()->overlapCapsuleShapes( worldCapsule, NX_ALL_SHAPES, 10, shapes, NULL, activeGroups ); - - for ( S32 i = 0; i < hitCount; i++ ) - { - PhysicsUserData *data = PhysicsUserData::cast( shapes[i]->getActor().userData ); - if ( data ) - outOverlapObjects->push_back( data->getObject() ); - } -} - -void PxPlayer::enableCollision() -{ - AssertFatal( mController, "PxPlayer::enableCollision - The controller is null!" ); - - mWorld->releaseWriteLock(); - mController->setCollision( true ); -} - -void PxPlayer::disableCollision() -{ - AssertFatal( mController, "PxPlayer::disableCollision - The controller is null!" ); - - mWorld->releaseWriteLock(); - mController->setCollision( false ); -} - -PhysicsWorld* PxPlayer::getWorld() -{ - return mWorld; -} - -void PxPlayer::setTransform( const MatrixF &transform ) -{ - AssertFatal( mController, "PxPlayer::setTransform - The controller is null!" ); - - mWorld->releaseWriteLock(); - - Point3F newPos = transform.getPosition(); - newPos.z += mOriginOffset; - - const Point3F &curPos = pxCast(mController->getDebugPosition()); - - if ( !(newPos - curPos ).isZero() ) - mController->setPosition( pxCast(newPos) ); -} - -MatrixF& PxPlayer::getTransform( MatrixF *outMatrix ) -{ - AssertFatal( mController, "PxPlayer::getTransform - The controller is null!" ); - - Point3F newPos = pxCast( mController->getDebugPosition() ); - newPos.z -= mOriginOffset; - outMatrix->setPosition( newPos ); - - return *outMatrix; -} - -void PxPlayer::setScale( const Point3F &scale ) -{ -} - -Box3F PxPlayer::getWorldBounds() -{ - Con::warnf( "PxPlayer::getWorldBounds - not implemented" ); - return Box3F::Invalid; -} \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxPlayer.h b/Engine/source/T3D/physics/physx/pxPlayer.h deleted file mode 100644 index 419ddcc2b..000000000 --- a/Engine/source/T3D/physics/physx/pxPlayer.h +++ /dev/null @@ -1,106 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PXPLAYER_H -#define _PXPLAYER_H - -#ifndef _PHYSX_H_ -#include "T3D/physics/physX/px.h" -#endif -#ifndef _T3D_PHYSICS_PHYSICSPLAYER_H_ -#include "T3D/physics/physicsPlayer.h" -#endif -#ifndef _T3D_PHYSICSCOMMON_H_ -#include "T3D/physics/physicsCommon.h" -#endif - - -class PxWorld; -class NxController; - - -class PxPlayer : public PhysicsPlayer, public NxUserControllerHitReport -{ -protected: - - NxController *mController; - - F32 mSkinWidth; - - PxWorld *mWorld; - - SceneObject *mObject; - - /// Used to get collision info out of the - /// NxUserControllerHitReport callbacks. - CollisionList *mCollisionList; - - /// - F32 mOriginOffset; - - /// - F32 mStepHeight; - - /// - void _releaseController(); - - // NxUserControllerHitReport - virtual NxControllerAction onShapeHit( const NxControllerShapeHit& hit ); - virtual NxControllerAction onControllerHit( const NxControllersHit& hit ); - - void _findContact( SceneObject **contactObject, VectorF *contactNormal ) const; - - void _onPhysicsReset( PhysicsResetEvent reset ); - - void _onStaticChanged(); - -public: - - PxPlayer(); - virtual ~PxPlayer(); - - // PhysicsObject - virtual PhysicsWorld* getWorld(); - virtual void setTransform( const MatrixF &transform ); - virtual MatrixF& getTransform( MatrixF *outMatrix ); - virtual void setScale( const Point3F &scale ); - virtual Box3F getWorldBounds(); - virtual void setSimulationEnabled( bool enabled ) {} - virtual bool isSimulationEnabled() { return true; } - - // PhysicsPlayer - virtual void init( const char *type, - const Point3F &size, - F32 runSurfaceCos, - F32 stepHeight, - SceneObject *obj, - PhysicsWorld *world ); - virtual Point3F move( const VectorF &displacement, CollisionList &outCol ); - virtual void findContact( SceneObject **contactObject, VectorF *contactNormal, Vector *outOverlapObjects ) const; - virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const { return true; } - virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {} - virtual void enableCollision(); - virtual void disableCollision(); -}; - - -#endif // _PXPLAYER_H \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxPlugin.cpp b/Engine/source/T3D/physics/physx/pxPlugin.cpp deleted file mode 100644 index bb3352983..000000000 --- a/Engine/source/T3D/physics/physx/pxPlugin.cpp +++ /dev/null @@ -1,297 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "console/consoleTypes.h" -#include "T3D/physics/physX/pxPlugin.h" - -#include "T3D/physics/physicsShape.h" -#include "T3D/physics/physX/pxWorld.h" -#include "T3D/physics/physX/pxBody.h" -#include "T3D/physics/physX/pxPlayer.h" -#include "T3D/physics/physX/pxCollision.h" -#include "T3D/gameBase/gameProcess.h" -#include "core/util/tNamedFactory.h" - - -extern bool gPhysXLogWarnings; - -AFTER_MODULE_INIT( Sim ) -{ - NamedFactory::add( "PhysX", &PxPlugin::create ); - - #if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) - NamedFactory::add( "default", &PxPlugin::create ); - #endif - - Con::addVariable( "$PhysXLogWarnings", TypeBool, &gPhysXLogWarnings, - "@brief Output PhysX warnings to the console.\n\n" - "@ingroup Physics\n"); -} - - -PhysicsPlugin* PxPlugin::create() -{ - // Only create the plugin if it hasn't been set up AND - // the PhysX world is successfully initialized. - bool success = PxWorld::restartSDK( false ); - if ( success ) - return new PxPlugin(); - - return NULL; -} - -PxPlugin::PxPlugin() -{ -} - -PxPlugin::~PxPlugin() -{ -} - -void PxPlugin::destroyPlugin() -{ - // Cleanup any worlds that are still kicking. - Map::Iterator iter = mPhysicsWorldLookup.begin(); - for ( ; iter != mPhysicsWorldLookup.end(); iter++ ) - { - iter->value->destroyWorld(); - delete iter->value; - } - mPhysicsWorldLookup.clear(); - - PxWorld::restartSDK( true ); - - delete this; -} - -void PxPlugin::reset() -{ - // First delete all the cleanup objects. - if ( getPhysicsCleanup() ) - getPhysicsCleanup()->deleteAllObjects(); - - getPhysicsResetSignal().trigger( PhysicsResetEvent_Restore ); - - // Now let each world reset itself. - Map::Iterator iter = mPhysicsWorldLookup.begin(); - for ( ; iter != mPhysicsWorldLookup.end(); iter++ ) - iter->value->reset(); -} - -PhysicsCollision* PxPlugin::createCollision() -{ - return new PxCollision(); -} - -PhysicsBody* PxPlugin::createBody() -{ - return new PxBody(); -} - -PhysicsPlayer* PxPlugin::createPlayer() -{ - return new PxPlayer(); -} - -bool PxPlugin::isSimulationEnabled() const -{ - bool ret = false; - PxWorld *world = static_cast( getWorld( smClientWorldName ) ); - if ( world ) - { - ret = world->getEnabled(); - return ret; - } - - world = static_cast( getWorld( smServerWorldName ) ); - if ( world ) - { - ret = world->getEnabled(); - return ret; - } - - return ret; -} - -void PxPlugin::enableSimulation( const String &worldName, bool enable ) -{ - PxWorld *world = static_cast( getWorld( worldName ) ); - if ( world ) - world->setEnabled( enable ); -} - -void PxPlugin::setTimeScale( const F32 timeScale ) -{ - // Grab both the client and - // server worlds and set their time - // scales to the passed value. - PxWorld *world = static_cast( getWorld( smClientWorldName ) ); - if ( world ) - world->setEditorTimeScale( timeScale ); - - world = static_cast( getWorld( smServerWorldName ) ); - if ( world ) - world->setEditorTimeScale( timeScale ); -} - -const F32 PxPlugin::getTimeScale() const -{ - // Grab both the client and - // server worlds and call - // setEnabled( true ) on them. - PxWorld *world = static_cast( getWorld( smClientWorldName ) ); - if ( !world ) - { - world = static_cast( getWorld( smServerWorldName ) ); - if ( !world ) - return 0.0f; - } - - return world->getEditorTimeScale(); -} - -bool PxPlugin::createWorld( const String &worldName ) -{ - Map::Iterator iter = mPhysicsWorldLookup.find( worldName ); - PhysicsWorld *world = NULL; - - iter != mPhysicsWorldLookup.end() ? world = (*iter).value : world = NULL; - - if ( world ) - { - Con::errorf( "PxPlugin::createWorld - %s world already exists!", worldName.c_str() ); - return false; - } - - world = new PxWorld(); - - if ( worldName.equal( smClientWorldName, String::NoCase ) ) - world->initWorld( false, ClientProcessList::get() ); - else - world->initWorld( true, ServerProcessList::get() ); - - mPhysicsWorldLookup.insert( worldName, world ); - - return world != NULL; -} - -void PxPlugin::destroyWorld( const String &worldName ) -{ - Map::Iterator iter = mPhysicsWorldLookup.find( worldName ); - if ( iter == mPhysicsWorldLookup.end() ) - return; - - PhysicsWorld *world = (*iter).value; - world->destroyWorld(); - delete world; - - mPhysicsWorldLookup.erase( iter ); -} - -PhysicsWorld* PxPlugin::getWorld( const String &worldName ) const -{ - if ( mPhysicsWorldLookup.isEmpty() ) - return NULL; - - Map::ConstIterator iter = mPhysicsWorldLookup.find( worldName ); - - return iter != mPhysicsWorldLookup.end() ? (*iter).value : NULL; -} - -PhysicsWorld* PxPlugin::getWorld() const -{ - if ( mPhysicsWorldLookup.size() == 0 ) - return NULL; - - Map::ConstIterator iter = mPhysicsWorldLookup.begin(); - return iter->value; -} - -U32 PxPlugin::getWorldCount() const -{ - return mPhysicsWorldLookup.size(); -} - -void PxPlugin::_onDebugDrawEnabled( bool enabled ) -{ - if ( !enabled ) - gPhysicsSDK->setParameter( NX_VISUALIZATION_SCALE, 0.0f ); -} - -ConsoleFunction( physXRemoteDebuggerConnect, bool, 1, 3, "" ) -{ - if ( !gPhysicsSDK ) - { - Con::errorf( "PhysX SDK not initialized!" ); - return false; - } - - NxRemoteDebugger *debugger = gPhysicsSDK->getFoundationSDK().getRemoteDebugger(); - - if ( debugger->isConnected() ) - { - Con::errorf( "RemoteDebugger already connected... call disconnect first!" ); - return false; - } - - const UTF8 *host = "localhost"; - U32 port = 5425; - - if ( argc >= 2 ) - host = argv[1]; - if ( argc >= 3 ) - port = dAtoi( argv[2] ); - - // Before we connect we need to have write access - // to both the client and server worlds. - PxWorld::releaseWriteLocks(); - - // Connect! - debugger->connect( host, port ); - if ( !debugger->isConnected() ) - { - Con::errorf( "RemoteDebugger failed to connect!" ); - return false; - } - - Con::printf( "RemoteDebugger connected to %s at port %u!", host, port ); - return true; -} - -ConsoleFunction( physXRemoteDebuggerDisconnect, void, 1, 1, "" ) -{ - if ( !gPhysicsSDK ) - { - Con::errorf( "PhysX SDK not initialized!" ); - return; - } - - NxRemoteDebugger *debugger = gPhysicsSDK->getFoundationSDK().getRemoteDebugger(); - - if ( debugger->isConnected() ) - { - debugger->flush(); - debugger->disconnect(); - Con::printf( "RemoteDebugger disconnected!" ); - } -} diff --git a/Engine/source/T3D/physics/physx/pxPlugin.h b/Engine/source/T3D/physics/physx/pxPlugin.h deleted file mode 100644 index c32c1162c..000000000 --- a/Engine/source/T3D/physics/physx/pxPlugin.h +++ /dev/null @@ -1,59 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _T3D_PHYSICS_PXPLUGIN_H_ -#define _T3D_PHYSICS_PXPLUGIN_H_ - -#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_ -#include "T3D/physics/physicsPlugin.h" -#endif - - -class PxPlugin : public PhysicsPlugin -{ -public: - - PxPlugin(); - ~PxPlugin(); - - /// Create function for factory. - static PhysicsPlugin* create(); - - // PhysicsPlugin - virtual void destroyPlugin(); - virtual void reset(); - virtual PhysicsCollision* createCollision(); - virtual PhysicsBody* createBody(); - virtual PhysicsPlayer* createPlayer(); - virtual bool isSimulationEnabled() const; - virtual void enableSimulation( const String &worldName, bool enable ); - virtual void setTimeScale( const F32 timeScale ); - virtual const F32 getTimeScale() const; - virtual bool createWorld( const String &worldName ); - virtual void destroyWorld( const String &worldName ); - virtual PhysicsWorld* getWorld( const String &worldName ) const; - virtual PhysicsWorld* getWorld() const; - virtual U32 getWorldCount() const; - virtual void _onDebugDrawEnabled( bool enabled ); -}; - -#endif // _T3D_PHYSICS_PXPLUGIN_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxStream.cpp b/Engine/source/T3D/physics/physx/pxStream.cpp deleted file mode 100644 index 6c7565ee6..000000000 --- a/Engine/source/T3D/physics/physx/pxStream.cpp +++ /dev/null @@ -1,174 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxStream.h" - -#include "console/console.h" -#include "console/consoleTypes.h" -#include "core/strings/stringFunctions.h" - - -PxMemStream::PxMemStream() - : mMemStream( 1024 ) -{ -} - -PxMemStream::~PxMemStream() -{ -} - -void PxMemStream::resetPosition() -{ - mMemStream.setPosition( 0 ); -} - -NxU8 PxMemStream::readByte() const -{ - NxU8 out; - mMemStream.read( &out ); - return out; -} - -NxU16 PxMemStream::readWord() const -{ - NxU16 out; - mMemStream.read( &out ); - return out; -} - -NxU32 PxMemStream::readDword() const -{ - NxU32 out; - mMemStream.read( &out ); - return out; -} - -float PxMemStream::readFloat() const -{ - float out; - mMemStream.read( &out ); - return out; -} - -double PxMemStream::readDouble() const -{ - double out; - mMemStream.read( &out ); - return out; -} - -void PxMemStream::readBuffer( void *buffer, NxU32 size ) const -{ - mMemStream.read( size, buffer ); -} - -NxStream& PxMemStream::storeByte( NxU8 b ) -{ - mMemStream.write( b ); - return *this; -} - -NxStream& PxMemStream::storeWord( NxU16 w ) -{ - mMemStream.write( w ); - return *this; -} - -NxStream& PxMemStream::storeDword( NxU32 d ) -{ - mMemStream.write( d ); - return *this; -} - -NxStream& PxMemStream::storeFloat( NxReal f ) -{ - mMemStream.write( f ); - return *this; -} - -NxStream& PxMemStream::storeDouble( NxF64 f ) -{ - mMemStream.write( f ); - return *this; -} - -NxStream& PxMemStream::storeBuffer( const void *buffer, NxU32 size ) -{ - mMemStream.write( size, buffer ); - return *this; -} - - -bool gPhysXLogWarnings = false; - -PxConsoleStream::PxConsoleStream() -{ -} - -PxConsoleStream::~PxConsoleStream() -{ -} - -void PxConsoleStream::reportError( NxErrorCode code, const char *message, const char* file, int line ) -{ - #ifdef TORQUE_DEBUG - - // If we're in debug mode and the error code is serious then - // pop up a message box to make sure we see it. - if ( code < NXE_DB_INFO ) - { - UTF8 info[1024]; - dSprintf( info, 1024, "File: %s\nLine: %d\n%s", file, line, message ); - Platform::AlertOK( "PhysX Error", info ); - } - - #endif - - // In all other cases we just dump the message to the console. - if ( code == NXE_DB_WARNING ) - { - if ( gPhysXLogWarnings ) - Con::printf( "PhysX Warning:\n %s(%d) : %s\n", file, line, message ); - } - else - Con::printf( "PhysX Error:\n %s(%d) : %s\n", file, line, message ); -} - -NxAssertResponse PxConsoleStream::reportAssertViolation (const char *message, const char *file,int line) -{ - // Assert if we're in debug mode... - bool triggerBreak = false; - #ifdef TORQUE_DEBUG - triggerBreak = PlatformAssert::processAssert( PlatformAssert::Fatal, file, line, message ); - #endif - - // In all other cases we just dump the message to the console. - Con::errorf( "PhysX Assert:\n %s(%d) : %s\n", file, line, message ); - - return triggerBreak ? NX_AR_BREAKPOINT : NX_AR_CONTINUE; -} - -void PxConsoleStream::print( const char *message ) -{ - Con::printf( "PhysX Says: %s\n", message ); -} diff --git a/Engine/source/T3D/physics/physx/pxStream.h b/Engine/source/T3D/physics/physx/pxStream.h deleted file mode 100644 index 8dc875fa3..000000000 --- a/Engine/source/T3D/physics/physx/pxStream.h +++ /dev/null @@ -1,78 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _T3D_PHYSICS_PXSTREAM_H_ -#define _T3D_PHYSICS_PXSTREAM_H_ - -#ifndef _PHYSX_H_ -#include "T3D/physics/physX/px.h" -#endif -#ifndef _MEMSTREAM_H_ -#include "core/stream/memStream.h" -#endif - - -class PxMemStream : public NxStream -{ -public: - - PxMemStream(); - virtual ~PxMemStream(); - - void resetPosition(); - - // NxStream - NxU8 readByte() const; - NxU16 readWord() const; - NxU32 readDword() const; - float readFloat() const; - double readDouble() const; - void readBuffer( void *buffer, NxU32 size ) const; - NxStream& storeByte( NxU8 b ); - NxStream& storeWord( NxU16 w ); - NxStream& storeDword( NxU32 d ); - NxStream& storeFloat( NxReal f ); - NxStream& storeDouble( NxF64 f ); - NxStream& storeBuffer( const void* buffer, NxU32 size ); - -protected: - - mutable MemStream mMemStream; -}; - - -class PxConsoleStream : public NxUserOutputStream -{ -protected: - - // NxUserOutputStream - void reportError( NxErrorCode code, const char *message, const char* file, int line ); - NxAssertResponse reportAssertViolation( const char *message, const char *file, int line ); - void print( const char *message ); - -public: - - PxConsoleStream(); - ~PxConsoleStream(); -}; - -#endif // _T3D_PHYSICS_PXSTREAM_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxUtils.cpp b/Engine/source/T3D/physics/physx/pxUtils.cpp deleted file mode 100644 index 05671806f..000000000 --- a/Engine/source/T3D/physics/physx/pxUtils.cpp +++ /dev/null @@ -1,109 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physx/pxUtils.h" - -#include "gfx/gfxTransformSaver.h" -#include "gfx/gfxDrawUtil.h" -#include "math/mMatrix.h" -#include "math/mPoint3.h" -#include "T3D/physics/physX/px.h" -#include "T3D/physics/physX/pxCasts.h" - -namespace PxUtils { - -void drawActor( NxActor *inActor ) -{ - GFXDrawUtil *drawer = GFX->getDrawUtil(); - //drawer->setZRead( false ); - - // Determine alpha we render shapes with. - const U8 enabledAlpha = 255; - const U8 disabledAlpha = 100; - U8 renderAlpha = inActor->readActorFlag( NX_AF_DISABLE_COLLISION ) ? disabledAlpha : enabledAlpha; - - // Determine color we render actors and shapes with. - ColorI actorColor( 0, 0, 255, 200 ); - ColorI shapeColor = ( inActor->isSleeping() ? ColorI( 0, 0, 255, renderAlpha ) : ColorI( 255, 0, 255, renderAlpha ) ); - - MatrixF actorMat(true); - inActor->getGlobalPose().getRowMajor44( actorMat ); - - GFXStateBlockDesc desc; - desc.setBlend( true ); - desc.setZReadWrite( true, false ); - desc.setCullMode( GFXCullNone ); - - // Draw an xfm gizmo for the actor's globalPose... - //drawer->drawTransform( desc, actorMat, Point3F::One, actorColor ); - - // Loop through and render all the actor's shapes.... - - NxShape *const*pShapeArray = inActor->getShapes(); - U32 numShapes = inActor->getNbShapes(); - - for ( U32 i = 0; i < numShapes; i++ ) - { - const NxShape *shape = pShapeArray[i]; - - Point3F shapePos = pxCast( shape->getGlobalPosition() ); - MatrixF shapeMat(true); - shape->getGlobalPose().getRowMajor44(shapeMat); - shapeMat.setPosition( Point3F::Zero ); - - switch ( shape->getType() ) - { - case NX_SHAPE_SPHERE: - { - NxSphereShape *sphere = (NxSphereShape*)shape; - drawer->drawSphere( desc, sphere->getRadius(), shapePos, shapeColor ); - - break; - } - case NX_SHAPE_BOX: - { - NxBoxShape *box = (NxBoxShape*)shape; - Point3F size = pxCast( box->getDimensions() ); - drawer->drawCube( desc, size*2, shapePos, shapeColor, &shapeMat ); - break; - } - case NX_SHAPE_CAPSULE: - { - shapeMat.mul( MatrixF( EulerF( mDegToRad(90.0f), mDegToRad(90.0f), 0 ) ) ); - - NxCapsuleShape *capsule = (NxCapsuleShape*)shape; - drawer->drawCapsule( desc, shapePos, capsule->getRadius(), capsule->getHeight(), shapeColor, &shapeMat ); - - break; - } - default: - { - break; - } - } - } - - //drawer->clearZDefined(); -} - -} // namespace PxUtils \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxUtils.h b/Engine/source/T3D/physics/physx/pxUtils.h deleted file mode 100644 index 1c1d9873b..000000000 --- a/Engine/source/T3D/physics/physx/pxUtils.h +++ /dev/null @@ -1,38 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PXUTILS_H_ -#define _PXUTILS_H_ - - -class NxActor; - - -namespace PxUtils { - - /// Debug render an actor, loops through all shapes - /// and translates primitive types into drawUtil calls. - void drawActor( NxActor *inActor ); - -} // namespace PxUtils - -#endif // _PXUTILS_H_ \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx/pxWorld.cpp b/Engine/source/T3D/physics/physx/pxWorld.cpp deleted file mode 100644 index 0ec3d7fea..000000000 --- a/Engine/source/T3D/physics/physx/pxWorld.cpp +++ /dev/null @@ -1,876 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#include "platform/platform.h" -#include "T3D/physics/physX/pxWorld.h" - -#include "T3D/physics/physX/px.h" -#include "T3D/physics/physX/pxPlugin.h" -#include "T3D/physics/physX/pxMaterial.h" -#include "T3D/physics/physX/pxContactReporter.h" -#include "T3D/physics/physX/pxStream.h" -#include "T3D/physics/physX/pxCasts.h" -#include "T3D/physics/physicsUserData.h" - -#include "core/stream/bitStream.h" -#include "platform/profiler.h" -#include "sim/netConnection.h" -#include "console/console.h" -#include "console/consoleTypes.h" -#include "core/util/safeDelete.h" -#include "T3D/tsstatic.h" -#include "T3D/gameBase/gameProcess.h" -#include "gfx/sim/debugDraw.h" -#include "gfx/primBuilder.h" - -#include - - -static const F32 PhysicsStepTime = (F32)TickMs / 1000.0f; -static const U32 PhysicsMaxIterations = 8; -static const F32 PhysicsMaxTimeStep = PhysicsStepTime / 2.0f; - -NxPhysicsSDK *gPhysicsSDK = NULL; -NxCookingInterface *PxWorld::smCooking = NULL; -PxConsoleStream *PxWorld::smConsoleStream = NULL; - - -PxWorld::PxWorld() : - mScene( NULL ), - mConactReporter( NULL ), - mProcessList( NULL ), - mIsSimulating( false ), - mErrorReport( false ), - mTickCount( 0 ), - mIsEnabled( false ), - mEditorTimeScale( 1.0f ) -{ - if ( !CCTAllocator::mAllocator ) - CCTAllocator::mAllocator = new NxUserAllocatorDefault(); - mControllerManager = new CharacterControllerManager( CCTAllocator::mAllocator ); -} - -PxWorld::~PxWorld() -{ - delete mControllerManager; -} - -NxCookingInterface* PxWorld::getCooking() -{ - if ( !smCooking ) - smCooking = NxGetCookingLib( NX_PHYSICS_SDK_VERSION ); - - return smCooking; -} - -bool PxWorld::_init( bool isServer, ProcessList *processList ) -{ - if ( !gPhysicsSDK ) - { - Con::errorf( "PhysXWorld::init - PhysXSDK not initialized!" ); - return false; - } - - // Create the scene description. - NxSceneDesc sceneDesc; - sceneDesc.userData = this; - - // Set up default gravity. - sceneDesc.gravity.set( mGravity.x, mGravity.y, mGravity.z ); - - // The master scene is always on the CPU and is used - // mostly for static shapes. - sceneDesc.simType = NX_SIMULATION_SW; // [9/28/2009 Pat] Why is this software? Should be software server, hardware client? - - // Threading... seems to improve performance. - // - // TODO: I was getting random crashes in debug when doing - // edit and continue... lets see if i still get them with - // the threading disabled. - // - sceneDesc.flags |= NX_SF_ENABLE_MULTITHREAD | NX_SF_DISABLE_SCENE_MUTEX; - sceneDesc.threadMask = 0xfffffffe; - sceneDesc.internalThreadCount = PHYSICSMGR->getThreadCount(); - - // Create the scene. - mScene = gPhysicsSDK->createScene(sceneDesc); - if ( !mScene ) - { - Con::errorf( "PhysXWorld - %s world createScene returned a null scene!", isServer ? "Server" : "Client" ); - return false; - } - - /* - // Make note of what we've created. - String simType = sceneDesc.simType == NX_SIMULATION_SW ? "software" : "hardware"; - String clientOrServer = this == isServer ? "server" : "client"; - Con::printf( "PhysXWorld::init() - Created %s %s simulation!", - clientOrServer.c_str(), - simType.c_str() ); - */ - - mScene->setTiming( PhysicsMaxTimeStep, PhysicsMaxIterations, NX_TIMESTEP_FIXED ); - - // TODO: Add dummy actor with scene name! - - // Set the global contact reporter. - - mConactReporter = new PxContactReporter(); - mScene->setUserContactReport( mConactReporter ); - - // Set the global PxUserNotify - - mUserNotify = new PxUserNotify(); - mScene->setUserNotify( mUserNotify ); - - // Now create the dynamic rigid body compartment which - // can reside on the hardware when hardware is present. - /* - NxCompartmentDesc compartmentDesc; - compartmentDesc.type = NX_SCT_RIGIDBODY; - compartmentDesc.deviceCode = NX_DC_PPU_AUTO_ASSIGN; - mRigidCompartment = mScene->createCompartment( compartmentDesc ); - if ( !mRigidCompartment ) - { - Con::errorf( "PhysXWorld - Creation of rigid body compartment failed!" ); - return false; - } - */ - - // Hook up the tick processing signals for advancing physics. - // - // First an overview of how physics and the game ticks - // interact with each other. - // - // In Torque you normally tick the server and then the client - // approximately every 32ms. So before the game tick we call - // getPhysicsResults() to get the new physics state and call - // tickPhysics() when the game tick is done to start processing - // the next physics state. This means PhysX is happily doing - // physics in a separate thread while we're doing rendering, - // sound, input, networking, etc. - // - // Because your frame rate is rarely perfectly even you can - // get cases where you may tick the server or the client - // several times in a row. This happens most often in debug - // mode, but can also happen in release. - // - // The simple implementation is to do a getPhysicsResults() and - // tickPhysics() for each tick. But this very bad! It forces - // immediate results from PhysX which blocks the primary thread - // and further slows down processing. It leads to slower and - // slower frame rates as the simulation is never able to catch - // up to the current tick. - // - // The trick is processing physics once for backlogged ticks - // with the total of the elapsed tick time. This is a huge - // performance gain and keeps you from blocking on PhysX. - // - // This does have a side effect that when it occurs you'll get - // ticks where the physics state hasn't advanced, but this beats - // single digit frame rates. - // - AssertFatal( processList, "PxWorld::init() - We need a process list to create the world!" ); - mProcessList = processList; - mProcessList->preTickSignal().notify( this, &PxWorld::getPhysicsResults ); - mProcessList->postTickSignal().notify( this, &PxWorld::tickPhysics, 1000.0f ); - - // Setup the default material. - NxMaterial *dmat = mScene->getMaterialFromIndex( 0 ); - dmat->setRestitution( 0.2f ); - dmat->setStaticFriction( 0.6f ); - dmat->setDynamicFriction( 0.4f ); - - // Setup dominance groups. - - // Group 31 is for debris and other objects which can be pushed but cannot push back. - // Group 0 is for everything else. - - NxConstraintDominance debrisDominance( 0.0f, 1.0f ); - mScene->setDominanceGroupPair( 0, 31, debrisDominance ); - - return true; -} - -void PxWorld::_destroy() -{ - // Make sure the simulation is stopped! - getPhysicsResults(); - _releaseQueues(); - - #ifdef TORQUE_DEBUG - - U32 actorCount = mScene->getNbActors(); - U32 jointCount = mScene->getNbJoints(); - - if ( actorCount != 0 || jointCount != 0 ) - { - // Dump the names of any actors or joints that - // were not released before the destruction of - // this scene. - - for ( U32 i=0; i < actorCount; i++ ) - { - const NxActor *actor = mScene->getActors()[i]; - Con::errorf( "Orphan NxActor - '%s'!", actor->getName() ); - } - - mScene->resetJointIterator(); - for ( ;; ) - { - const NxJoint *joint = mScene->getNextJoint(); - if ( !joint ) - break; - - Con::errorf( "Orphan NxJoint - '%s'!", joint->getName() ); - } - - AssertFatal( false, "PhysXWorld::_destroy() - Some actors and/or joints were not released!" ); - } - - #endif // TORQUE_DEBUG - - //NxCloseCooking(); - - // Release the tick processing signals. - if ( mProcessList ) - { - mProcessList->preTickSignal().remove( this, &PxWorld::getPhysicsResults ); - mProcessList->postTickSignal().remove( this, &PxWorld::tickPhysics ); - mProcessList = NULL; - } - - // Destroy the scene. - if ( mScene ) - { - // Delete the contact reporter. - mScene->setUserContactReport( NULL ); - SAFE_DELETE( mConactReporter ); - - // First shut down threads... this makes it - // safe to release the scene. - mScene->shutdownWorkerThreads(); - - // Release the scene. - gPhysicsSDK->releaseScene( *mScene ); - mScene = NULL; - } - - // Try to restart the sdk if we can. - //restartSDK(); -} - -bool PxWorld::restartSDK( bool destroyOnly, PxWorld *clientWorld, PxWorld *serverWorld ) -{ - // If either the client or the server still exist - // then we cannot reset the SDK. - if ( clientWorld || serverWorld ) - return false; - - // Destroy the existing SDK. - if ( gPhysicsSDK ) - { - NXU::releasePersistentMemory(); - gPhysicsSDK->release(); - gPhysicsSDK = NULL; - smCooking = NULL; - SAFE_DELETE( smConsoleStream ); - } - - // If we're not supposed to restart... return. - if ( destroyOnly ) - return true; - - smConsoleStream = new PxConsoleStream(); - - NxPhysicsSDKDesc sdkDesc; - sdkDesc.flags |= NX_SDKF_NO_HARDWARE; // [9/28/2009 Pat] Why is this disabled? - - NxSDKCreateError error; - gPhysicsSDK = NxCreatePhysicsSDK( NX_PHYSICS_SDK_VERSION, - NULL, - smConsoleStream, - sdkDesc, - &error ); - if ( !gPhysicsSDK ) - { - Con::errorf( "PhysX failed to initialize! Error code: %d", error ); - Platform::messageBox( Con::getVariable( "$appName" ), - avar("PhysX could not be started!\r\n" - "Please be sure you have the latest version of PhysX installed.\r\n" - "Error Code: %d", error), - MBOk, MIStop ); - Platform::forceShutdown( -1 ); - - // We shouldn't get here, but this shuts up - // source diagnostic tools. - return false; - } - - // Set the default skin width for all actors. - gPhysicsSDK->setParameter( NX_SKIN_WIDTH, 0.01f ); - - return true; -} - -void PxWorld::tickPhysics( U32 elapsedMs ) -{ - if ( !mScene || !mIsEnabled ) - return; - - // Did we forget to call getPhysicsResults somewhere? - AssertFatal( !mIsSimulating, "PhysXWorld::tickPhysics() - Already simulating!" ); - - // The elapsed time should be non-zero and - // a multiple of TickMs! - AssertFatal( elapsedMs != 0 && - ( elapsedMs % TickMs ) == 0 , "PhysXWorld::tickPhysics() - Got bad elapsed time!" ); - - PROFILE_SCOPE(PxWorld_TickPhysics); - - // Convert it to seconds. - const F32 elapsedSec = (F32)elapsedMs * 0.001f; - - // For some reason this gets reset all the time - // and it must be called before the simulate. - mScene->setFilterOps( NX_FILTEROP_OR, - NX_FILTEROP_OR, - NX_FILTEROP_AND ); - mScene->setFilterBool( false ); - NxGroupsMask zeroMask; - zeroMask.bits0=zeroMask.bits1=zeroMask.bits2=zeroMask.bits3=0; - mScene->setFilterConstant0( zeroMask ); - mScene->setFilterConstant1( zeroMask ); - - mScene->simulate( elapsedSec * mEditorTimeScale ); - mScene->flushStream(); - mIsSimulating = true; - - //Con::printf( "%s PhysXWorld::tickPhysics!", this == smClientWorld ? "Client" : "Server" ); -} - -void PxWorld::releaseWriteLocks() -{ - PxWorld *world = dynamic_cast( PHYSICSMGR->getWorld( "server" ) ); - - if ( world ) - world->releaseWriteLock(); - - world = dynamic_cast( PHYSICSMGR->getWorld( "client" ) ); - - if ( world ) - world->releaseWriteLock(); -} - -void PxWorld::releaseWriteLock() -{ - if ( !mScene || !mIsSimulating ) - return; - - PROFILE_SCOPE(PxWorld_ReleaseWriteLock); - - // We use checkResults here to release the write lock - // but we do not change the simulation flag or increment - // the tick count... we may have gotten results, but the - // simulation hasn't really ticked! - mScene->checkResults( NX_RIGID_BODY_FINISHED, true ); - AssertFatal( mScene->isWritable(), "PhysXWorld::releaseWriteLock() - We should have been writable now!" ); -} - -void PxWorld::getPhysicsResults() -{ - if ( !mScene || !mIsSimulating ) - return; - - PROFILE_SCOPE(PxWorld_GetPhysicsResults); - - // Get results from scene. - mScene->fetchResults( NX_RIGID_BODY_FINISHED, true ); - mIsSimulating = false; - mTickCount++; - - // Release any joints/actors that were waiting - // for the scene to become writable. - _releaseQueues(); - - //Con::printf( "%s PhysXWorld::getPhysicsResults!", this == smClientWorld ? "Client" : "Server" ); -} - -NxMaterial* PxWorld::createMaterial( NxMaterialDesc &material ) -{ - if ( !mScene ) - return NULL; - - // We need the writelock to create a material! - releaseWriteLock(); - - NxMaterial *mat = mScene->createMaterial( material ); - if ( !mat ) - return NULL; - - return mat; -} - -NxController* PxWorld::createController( NxControllerDesc &desc ) -{ - if ( !mScene ) - return NULL; - - // We need the writelock! - releaseWriteLock(); - - return mControllerManager->createController( mScene, desc ); -} - -void PxWorld::releaseActor( NxActor &actor ) -{ - AssertFatal( &actor.getScene() == mScene, "PhysXWorld::releaseActor() - Bad scene!" ); - - // Clear the userdata. - actor.userData = NULL; - - // actors are one of the few objects that are stable removing this way in physx 2.8 - if (mScene->isWritable() ) - { - mScene->releaseActor( actor ); - } - else - { - mReleaseActorQueue.push_back( &actor ); - } -} - -void PxWorld::releaseMaterial( NxMaterial &mat ) -{ - AssertFatal( &mat.getScene() == mScene, "PhysXWorld::releaseMaterial() - Bad scene!" ); - - // If the scene is not simulating then we have the - // write lock and can safely delete it now. - if ( !mIsSimulating ) - mScene->releaseMaterial( mat ); - else - mReleaseMaterialQueue.push_back( &mat ); -} - -void PxWorld::releaseHeightField( NxHeightField &heightfield ) -{ - // Always delay releasing a heightfield, for whatever reason, - // it causes lots of deadlock asserts if we do it here, even if - // the scene "says" its writable. - // - // Actually this is probably because a heightfield is owned by the "sdk" and - // not an individual scene so if either the client "or" server scene are - // simulating it asserts, thats just my theory. - - mReleaseHeightFieldQueue.push_back( &heightfield ); -} - -void PxWorld::releaseJoint( NxJoint &joint ) -{ - AssertFatal( &joint.getScene() == mScene, "PhysXWorld::releaseJoint() - Bad scene!" ); - - AssertFatal( !mReleaseJointQueue.contains( &joint ), - "PhysXWorld::releaseJoint() - Joint already exists in the release queue!" ); - - // Clear the userdata. - joint.userData = NULL; - - // If the scene is not simulating then we have the - // write lock and can safely delete it now. - if ( !mIsSimulating ) - mScene->releaseJoint( joint ); - else - mReleaseJointQueue.push_back( &joint ); -} - -void PxWorld::releaseCloth( NxCloth &cloth ) -{ - AssertFatal( &cloth.getScene() == mScene, "PhysXWorld::releaseCloth() - Bad scene!" ); - - // Clear the userdata. - cloth.userData = NULL; - - // If the scene is not simulating then we have the - // write lock and can safely delete it now. - if ( !mIsSimulating ) - mScene->releaseCloth( cloth ); - else - mReleaseClothQueue.push_back( &cloth ); -} - -void PxWorld::releaseFluid( NxFluid &fluid ) -{ - AssertFatal( &fluid.getScene() == mScene, "PhysXWorld::releaseFluid() - Bad scene!" ); - - // Clear the userdata. - fluid.userData = NULL; - - // If the scene is not simulating then we have the - // write lock and can safely delete it now. - if ( !mIsSimulating ) - mScene->releaseFluid( fluid ); - else - mReleaseFluidQueue.push_back( &fluid ); -} - -void PxWorld::releaseClothMesh( NxClothMesh &clothMesh ) -{ - // We need the writelock to release. - releaseWriteLock(); - - gPhysicsSDK->releaseClothMesh( clothMesh ); -} - -void PxWorld::releaseController( NxController &controller ) -{ - // TODO: This isn't safe to do with actors and - // joints, so we probably need a queue like we - // do for them. - - // We need the writelock to release. - releaseWriteLock(); - - mControllerManager->releaseController( controller ); -} - -void PxWorld::_releaseQueues() -{ - AssertFatal( mScene, "PhysXWorld::_releaseQueues() - The scene is null!" ); - - // We release joints still pending in the queue - // first as they depend on the actors. - for ( S32 i = 0; i < mReleaseJointQueue.size(); i++ ) - { - NxJoint *currJoint = mReleaseJointQueue[i]; - mScene->releaseJoint( *currJoint ); - } - - // All the joints should be released, clear the queue. - mReleaseJointQueue.clear(); - - // Now release any actors still pending in the queue. - bool staticChanged = false; - for ( S32 i = 0; i < mReleaseActorQueue.size(); i++ ) - { - NxActor *currActor = mReleaseActorQueue[i]; - staticChanged |= !currActor->isDynamic(); - mScene->releaseActor( *currActor ); - } - - // All the actors should be released, clear the queue. - mReleaseActorQueue.clear(); - - // Now release any materials still pending in the queue. - for ( S32 i = 0; i < mReleaseMaterialQueue.size(); i++ ) - { - NxMaterial *currMat = mReleaseMaterialQueue[i]; - mScene->releaseMaterial( *currMat ); - } - - // All the materials should be released, clear the queue. - mReleaseMaterialQueue.clear(); - - // Now release any cloth still pending in the queue. - for ( S32 i = 0; i < mReleaseClothQueue.size(); i++ ) - { - NxCloth *currCloth = mReleaseClothQueue[i]; - mScene->releaseCloth( *currCloth ); - } - - // All the actors should be released, clear the queue. - mReleaseClothQueue.clear(); - - // Release heightfields that don't still have references. - for ( S32 i = 0; i < mReleaseHeightFieldQueue.size(); i++ ) - { - NxHeightField *currHeightfield = mReleaseHeightFieldQueue[i]; - - if ( currHeightfield->getReferenceCount() == 0 ) - { - gPhysicsSDK->releaseHeightField( *currHeightfield ); - mReleaseHeightFieldQueue.erase_fast( i ); - i--; - } - } - - // Clear fluid queue - for ( S32 i = 0; i < mReleaseFluidQueue.size(); i++ ) - { - NxFluid *currFluid = mReleaseFluidQueue[i]; - mScene->releaseFluid( *currFluid ); - } - mReleaseFluidQueue.clear(); - - if ( staticChanged ) - mStaticChangedSignal.trigger(); -} - -void PxWorld::setEnabled( bool enabled ) -{ - mIsEnabled = enabled; - - if ( !mIsEnabled ) - getPhysicsResults(); -} - -bool PxWorld::initWorld( bool isServer, ProcessList *processList ) -{ - /* This stuff is handled outside. - PxWorld* world = PxWorld::getWorld( isServer ); - if ( world ) - { - Con::errorf( "PhysXWorld::initWorld - %s world already exists!", isServer ? "Server" : "Client" ); - return false; - } - */ - - if ( !_init( isServer, processList ) ) - return false; - - return true; -} - -void PxWorld::destroyWorld() -{ - //PxWorld* world = PxWorld::getWorld( serverWorld ); - /* - if ( !world ) - { - Con::errorf( "PhysXWorld::destroyWorld - %s world already destroyed!", serverWorld ? "Server" : "Client" ); - return; - } - */ - //world->_destroy(); - //delete world; - - _destroy(); -} - -bool PxWorld::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse ) -{ - NxRay worldRay; - worldRay.orig = pxCast( startPnt ); - worldRay.dir = pxCast( endPnt - startPnt ); - NxF32 maxDist = worldRay.dir.magnitude(); - worldRay.dir.normalize(); - - U32 groups = 0xffffffff; - groups &= ~( 1<<31 ); // No trigger shapes! - - NxRaycastHit hitInfo; - NxShape *hitShape = mScene->raycastClosestShape( worldRay, NX_ALL_SHAPES, hitInfo, groups, maxDist ); - - if ( !hitShape ) - return false; - - //if ( hitShape->userData != NULL ) - // return false; - - NxActor &actor = hitShape->getActor(); - PhysicsUserData *userData = PhysicsUserData::cast( actor.userData ); - - if ( ri ) - { - ri->object = ( userData != NULL ) ? userData->getObject() : NULL; - - // If we were passed a RayInfo, we can only return true signifying a collision - // if we hit an object that actually has a torque object associated with it. - // - // In some ways this could be considered an error, either a physx object - // has raycast-collision enabled that shouldn't or someone did not set - // an object in this actor's userData. - // - if ( ri->object == NULL ) - return false; - - ri->distance = hitInfo.distance; - ri->normal = pxCast( hitInfo.worldNormal ); - ri->point = pxCast( hitInfo.worldImpact ); - ri->t = maxDist / hitInfo.distance; - } - - if ( impulse.isZero() || - !actor.isDynamic() || - actor.readBodyFlag( NX_BF_KINEMATIC ) ) - return true; - - NxVec3 force = pxCast( impulse );//worldRay.dir * forceAmt; - actor.addForceAtPos( force, hitInfo.worldImpact, NX_IMPULSE ); - - return true; -} - -PhysicsBody* PxWorld::castRay( const Point3F &start, const Point3F &end, U32 bodyTypes ) -{ - NxRay worldRay; - worldRay.orig = pxCast( start ); - worldRay.dir = pxCast( end - start ); - F32 maxDist = worldRay.dir.normalize(); - - U32 groups = 0xFFFFFFFF; - if ( !( bodyTypes & BT_Player ) ) - groups &= ~( 1<<29 ); - - // TODO: For now always skip triggers and debris, - // but we should consider how game specifc this API - // should be in the future. - groups &= ~( 1<<31 ); // triggers - groups &= ~( 1<<30 ); // debris - - U32 shapesType = 0; - if ( bodyTypes & BT_Static ) - shapesType |= NX_STATIC_SHAPES; - if ( bodyTypes & BT_Dynamic ) - shapesType |= NX_DYNAMIC_SHAPES; - - NxRaycastHit hitInfo; - NxShape *hitShape = mScene->raycastClosestShape( worldRay, (NxShapesType)shapesType, hitInfo, groups, maxDist ); - if ( !hitShape ) - return NULL; - - NxActor &actor = hitShape->getActor(); - PhysicsUserData *userData = PhysicsUserData::cast( actor.userData ); - if ( !userData ) - return NULL; - - return userData->getBody(); -} - -void PxWorld::explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ) -{ - // Find Actors at the position within the radius - // and apply force to them. - - NxVec3 nxPos = pxCast( pos ); - NxShape **shapes = (NxShape**)NxAlloca(10*sizeof(NxShape*)); - NxSphere worldSphere( nxPos, radius ); - - NxU32 numHits = mScene->overlapSphereShapes( worldSphere, NX_ALL_SHAPES, 10, shapes, NULL ); - - for ( NxU32 i = 0; i < numHits; i++ ) - { - NxActor &actor = shapes[i]->getActor(); - - bool dynamic = actor.isDynamic(); - - if ( !dynamic ) - continue; - - bool kinematic = actor.readBodyFlag( NX_BF_KINEMATIC ); - - if ( kinematic ) - continue; - - NxVec3 force = actor.getGlobalPosition() - nxPos; - force.normalize(); - force *= forceMagnitude; - - actor.addForceAtPos( force, nxPos, NX_IMPULSE, true ); - } -} - -static ColorI getDebugColor( NxU32 packed ) -{ - ColorI col; - col.blue = (packed)&0xff; - col.green = (packed>>8)&0xff; - col.red = (packed>>16)&0xff; - col.alpha = 255; - - return col; -} - -void PxWorld::onDebugDraw( const SceneRenderState *state ) -{ - if ( !mScene ) - return; - - // We need the write lock to be able to request - // the NxDebugRenderable object. - releaseWriteLock(); - - // TODO: We need to expose the different types of visualization - // options to script and add a GUI for toggling them! - - gPhysicsSDK->setParameter( NX_VISUALIZATION_SCALE, 1.0f ); - //gPhysicsSDK->setParameter( NX_VISUALIZE_BODY_MASS_AXES, 0.0f ); - gPhysicsSDK->setParameter( NX_VISUALIZE_BODY_AXES, 1.0f ); - gPhysicsSDK->setParameter( NX_VISUALIZE_COLLISION_SHAPES, 1.0f ); - - const NxDebugRenderable *data = mScene->getDebugRenderable(); - if ( !data ) - return; - - // Render points - { - NxU32 numPoints = data->getNbPoints(); - const NxDebugPoint *points = data->getPoints(); - - PrimBuild::begin( GFXPointList, numPoints ); - - while ( numPoints-- ) - { - PrimBuild::color( getDebugColor(points->color) ); - PrimBuild::vertex3fv( &points->p.x ); - points++; - } - - PrimBuild::end(); - } - - // Render lines - { - NxU32 numLines = data->getNbLines(); - const NxDebugLine *lines = data->getLines(); - - PrimBuild::begin( GFXLineList, numLines * 2 ); - - while ( numLines-- ) - { - PrimBuild::color( getDebugColor( lines->color ) ); - PrimBuild::vertex3fv( &lines->p0.x ); - PrimBuild::vertex3fv( &lines->p1.x ); - lines++; - } - - PrimBuild::end(); - } - - // Render triangles - { - NxU32 numTris = data->getNbTriangles(); - const NxDebugTriangle *triangles = data->getTriangles(); - - PrimBuild::begin( GFXTriangleList, numTris * 3 ); - - while ( numTris-- ) - { - PrimBuild::color( getDebugColor( triangles->color ) ); - PrimBuild::vertex3fv( &triangles->p0.x ); - PrimBuild::vertex3fv( &triangles->p1.x ); - PrimBuild::vertex3fv( &triangles->p2.x ); - triangles++; - } - - PrimBuild::end(); - } -} diff --git a/Engine/source/T3D/physics/physx/pxWorld.h b/Engine/source/T3D/physics/physx/pxWorld.h deleted file mode 100644 index d9d570336..000000000 --- a/Engine/source/T3D/physics/physx/pxWorld.h +++ /dev/null @@ -1,193 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (c) 2012 GarageGames, LLC -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -//----------------------------------------------------------------------------- - -#ifndef _PHYSX_WORLD_H_ -#define _PHYSX_WORLD_H_ - -#ifndef _T3D_PHYSICS_PHYSICSWORLD_H_ -#include "T3D/physics/physicsWorld.h" -#endif -#ifndef _MMATH_H_ -#include "math/mMath.h" -#endif -#ifndef _PHYSX_H_ -#include "T3D/physics/physX/px.h" -#endif -#ifndef _TVECTOR_H_ -#include "core/util/tVector.h" -#endif - -class PxContactReporter; -class PxUserNotify; -class NxController; -class NxControllerDesc; -class ShapeBase; -class TSStatic; -class SceneObject; -class ProcessList; -class GameBase; -class CharacterControllerManager; -class PxConsoleStream; - - -class PxWorld : public PhysicsWorld -{ -protected: - - F32 mEditorTimeScale; - - Vector mReleaseClothQueue; - Vector mReleaseJointQueue; - Vector mReleaseActorQueue; - Vector mReleaseMaterialQueue; - Vector mReleaseHeightFieldQueue; - Vector mReleaseFluidQueue; - //Vector> mReleaseColQueue; - - Vector mCatchupQueue; - - PxContactReporter *mConactReporter; - - PxUserNotify *mUserNotify; - - NxScene *mScene; - - CharacterControllerManager *mControllerManager; - - bool mErrorReport; - - bool mIsEnabled; - - bool mIsSimulating; - - U32 mTickCount; - - ProcessList *mProcessList; - - bool _init( bool isServer, ProcessList *processList ); - - void _destroy(); - - void _releaseQueues(); - - void _updateScheduledStatics(); - - /// The mesh cooking interface which is loaded on first use. - /// @see getCooking - static NxCookingInterface *smCooking; - - /// The console stream for PhysX error reporting. - static PxConsoleStream *smConsoleStream; - -public: - - // PhysicWorld - virtual bool initWorld( bool isServer, ProcessList *processList ); - virtual void destroyWorld(); - virtual bool castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse ); - virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All ); - virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ); - virtual void onDebugDraw( const SceneRenderState *state ); - virtual void reset() {} - virtual bool isEnabled() const { return mIsEnabled; } - - /// @name Static Methods - /// @{ - - static bool restartSDK( bool destroyOnly = false, PxWorld *clientWorld = NULL, PxWorld *serverWorld = NULL ); - - static void releaseWriteLocks(); - - /// @} - - PxWorld(); - virtual ~PxWorld(); - -public: - - NxScene* getScene() { return mScene; } - - /// Returns the cooking interface. Will only return NULL - /// in the case of a missing or bad PhysX install. - static NxCookingInterface* getCooking(); - - U32 getTick() { return mTickCount; } - - void tickPhysics( U32 elapsedMs ); - - void getPhysicsResults(); - - //void enableCatchupMode( GameBase *obj ); - - bool isWritable() const { return !mIsSimulating; /* mScene->isWritable(); */ } - - void releaseWriteLock(); - - void setEnabled( bool enabled ); - bool getEnabled() const { return mIsEnabled; } - - NxMaterial* createMaterial( NxMaterialDesc &material ); - - /// - /// @see releaseController - NxController* createController( NxControllerDesc &desc ); - - //U16 setMaterial(NxMaterialDesc &material, U16 id); - - // NOTE: This is all a mess, but its a side effect of how - // PhysX works. Many objects cannot be deleted without write - // access to the scene. Worse some objects cannot be deleted - // until their owner objects are deleted first. - // - // For these reasons we have these methods to register objects to be - // released after the Scene has been ticked. - // - // Since there is no common base to PhysX objects we're stuck with - // this list of release methods. - // - - void releaseActor( NxActor &actor ); - - void releaseMaterial( NxMaterial &mat ); - - void releaseJoint( NxJoint &joint ); - - void releaseCloth( NxCloth &cloth ); - - void releaseClothMesh( NxClothMesh &clothMesh ); - - void releaseController( NxController &controller ); - - void releaseHeightField( NxHeightField &heightfield ); - - void releaseFluid( NxFluid &fluid ); - - //void releaseCol( PxCollision *col ); - - /// Returns the contact reporter for this scene. - PxContactReporter* getContactReporter() { return mConactReporter; } - - void setEditorTimeScale( F32 timeScale ) { mEditorTimeScale = timeScale; } - const F32 getEditorTimeScale() const { return mEditorTimeScale; } -}; - -#endif // _PHYSX_WORLD_H_