From d4b189e175d1148d9669f811571adb063ef013a5 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Fri, 28 Feb 2014 12:11:26 +1000 Subject: [PATCH 1/8] PhysX3 basic plugin. --- Engine/source/T3D/physics/physx3/px3.h | 53 ++ Engine/source/T3D/physics/physx3/px3Body.cpp | 421 +++++++++++++ Engine/source/T3D/physics/physx3/px3Body.h | 121 ++++ Engine/source/T3D/physics/physx3/px3Cast.h | 137 +++++ .../T3D/physics/physx3/px3Collision.cpp | 212 +++++++ .../source/T3D/physics/physx3/px3Collision.h | 87 +++ .../source/T3D/physics/physx3/px3Player.cpp | 328 ++++++++++ Engine/source/T3D/physics/physx3/px3Player.h | 104 ++++ .../source/T3D/physics/physx3/px3Plugin.cpp | 227 +++++++ Engine/source/T3D/physics/physx3/px3Plugin.h | 58 ++ .../source/T3D/physics/physx3/px3Stream.cpp | 92 +++ Engine/source/T3D/physics/physx3/px3Stream.h | 77 +++ Engine/source/T3D/physics/physx3/px3Utils.cpp | 32 + Engine/source/T3D/physics/physx3/px3Utils.h | 35 ++ Engine/source/T3D/physics/physx3/px3World.cpp | 567 ++++++++++++++++++ Engine/source/T3D/physics/physx3/px3World.h | 110 ++++ Tools/projectGenerator/modules/physX3.inc | 106 ++++ 17 files changed, 2767 insertions(+) create mode 100644 Engine/source/T3D/physics/physx3/px3.h create mode 100644 Engine/source/T3D/physics/physx3/px3Body.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3Body.h create mode 100644 Engine/source/T3D/physics/physx3/px3Cast.h create mode 100644 Engine/source/T3D/physics/physx3/px3Collision.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3Collision.h create mode 100644 Engine/source/T3D/physics/physx3/px3Player.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3Player.h create mode 100644 Engine/source/T3D/physics/physx3/px3Plugin.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3Plugin.h create mode 100644 Engine/source/T3D/physics/physx3/px3Stream.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3Stream.h create mode 100644 Engine/source/T3D/physics/physx3/px3Utils.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3Utils.h create mode 100644 Engine/source/T3D/physics/physx3/px3World.cpp create mode 100644 Engine/source/T3D/physics/physx3/px3World.h create mode 100644 Tools/projectGenerator/modules/physX3.inc diff --git a/Engine/source/T3D/physics/physx3/px3.h b/Engine/source/T3D/physics/physx3/px3.h new file mode 100644 index 000000000..e7c8b6555 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3.h @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------------- +// 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 _PHYSX3_H_ +#define _PHYSX3_H_ + +//------------------------------------------------------------------------- +//defines to keep PhysX happy and compiling +#if defined(TORQUE_OS_MAC) && !defined(__APPLE__) + #define __APPLE__ +#elif defined(TORQUE_OS_LINUX) && !defined(LINUX) + #define LINUX +#elif defined(TORQUE_OS_WIN32) && !defined(WIN32) + #define WIN32 +#endif + +//------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern physx::PxPhysics* gPhysics3SDK; + +#endif \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3Body.cpp b/Engine/source/T3D/physics/physx3/px3Body.cpp new file mode 100644 index 000000000..e4f437225 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Body.cpp @@ -0,0 +1,421 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3Body.h" + +#include "T3D/physics/physx3/px3.h" +#include "T3D/physics/physx3/px3Cast.h" +#include "T3D/physics/physx3/px3World.h" +#include "T3D/physics/physx3/px3Collision.h" + +#include "console/console.h" +#include "console/consoleTypes.h" + + +Px3Body::Px3Body() : + mActor( NULL ), + mMaterial( NULL ), + mWorld( NULL ), + mBodyFlags( 0 ), + mIsEnabled( true ), + mIsStatic(false) +{ +} + +Px3Body::~Px3Body() +{ + _releaseActor(); +} + +void Px3Body::_releaseActor() +{ + if ( !mActor ) + return; + + mWorld->releaseWriteLock(); + + mActor->userData = NULL; + + mActor->release(); + mActor = NULL; + mBodyFlags = 0; + + if ( mMaterial ) + { + mMaterial->release(); + } + + mColShape = NULL; +} + +bool Px3Body::init( PhysicsCollision *shape, + F32 mass, + U32 bodyFlags, + SceneObject *obj, + PhysicsWorld *world ) +{ + AssertFatal( obj, "Px3Body::init - Got a null scene object!" ); + AssertFatal( world, "Px3Body::init - Got a null world!" ); + AssertFatal( dynamic_cast( world ), "Px3Body::init - The world is the wrong type!" ); + AssertFatal( shape, "Px3Body::init - Got a null collision shape!" ); + AssertFatal( dynamic_cast( shape ), "Px3Body::init - The collision shape is the wrong type!" ); + AssertFatal( !((Px3Collision*)shape)->getShapes().empty(), "Px3Body::init - Got empty collision shape!" ); + + // Cleanup any previous actor. + _releaseActor(); + + mWorld = (Px3World*)world; + mColShape = (Px3Collision*)shape; + mBodyFlags = bodyFlags; + + const bool isKinematic = mBodyFlags & BF_KINEMATIC; + const bool isTrigger = mBodyFlags & BF_TRIGGER; + const bool isDebris = mBodyFlags & BF_DEBRIS; + + if ( isKinematic ) + { + mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY())); + physx::PxRigidDynamic *actor = mActor->is(); + actor->setRigidDynamicFlag(physx::PxRigidDynamicFlag::eKINEMATIC, true); + actor->setMass(getMax( mass, 1.0f )); + } + else if ( mass > 0.0f ) + { + mActor = gPhysics3SDK->createRigidDynamic(physx::PxTransform(physx::PxIDENTITY())); + } + else + { + mActor = gPhysics3SDK->createRigidStatic(physx::PxTransform(physx::PxIDENTITY())); + mIsStatic = true; + } + + mMaterial = gPhysics3SDK->createMaterial(0.6f,0.4f,0.1f); + + // Add all the shapes. + const Vector &shapes = mColShape->getShapes(); + for ( U32 i=0; i < shapes.size(); i++ ) + { + Px3CollisionDesc* desc = shapes[i]; + if( mass > 0.0f ) + { + if(desc->pGeometry->getType() == physx::PxGeometryType::eTRIANGLEMESH) + { + Con::errorf("PhysX3 Dynamic Triangle Mesh is not supported."); + } + } + physx::PxShape * pShape = mActor->createShape(*desc->pGeometry,*mMaterial,desc->pose); + physx::PxFilterData colData; + if(isDebris) + colData.word0 = PX3_DEBRIS; + else if(isTrigger) + { + //We don't want trigger shapes taking part in shape pair intersection tests + pShape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, false); + colData.word0 = PX3_TRIGGER; + } + else + colData.word0 = PX3_DEFAULT; + + //set the skin width + pShape->setContactOffset(0.01f); + pShape->setFlag(physx::PxShapeFlag::eSCENE_QUERY_SHAPE,true); + pShape->setSimulationFilterData(colData); + pShape->setQueryFilterData(colData); + } + + //mass & intertia has to be set after creating the shape + if ( mass > 0.0f ) + { + physx::PxRigidDynamic *actor = mActor->is(); + physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass); + } + + // This sucks, but it has to happen if we want + // to avoid write lock errors from PhysX right now. + mWorld->releaseWriteLock(); + + mWorld->getScene()->addActor(*mActor); + mIsEnabled = true; + + if ( isDebris ) + mActor->setDominanceGroup( 31 ); + + mUserData.setObject( obj ); + mUserData.setBody( this ); + mActor->userData = &mUserData; + + return true; +} + +void Px3Body::setMaterial( F32 restitution, + F32 friction, + F32 staticFriction ) +{ + AssertFatal( mActor, "Px3Body::setMaterial - The actor is null!" ); + + if ( isDynamic() ) + { + physx::PxRigidDynamic *actor = mActor->is(); + actor->wakeUp(); + } + + mMaterial->setRestitution(restitution); + mMaterial->setStaticFriction(staticFriction); + mMaterial->setDynamicFriction(friction); + +} + +void Px3Body::setSleepThreshold( F32 linear, F32 angular ) +{ + AssertFatal( mActor, "Px3Body::setSleepThreshold - The actor is null!" ); + + if(mIsStatic) + return; + + physx::PxRigidDynamic *actor = mActor->is(); + physx::PxF32 massNormalized= (linear*linear+angular*angular)/2.0f; + actor->setSleepThreshold(massNormalized); +} + +void Px3Body::setDamping( F32 linear, F32 angular ) +{ + AssertFatal( mActor, "Px3Body::setDamping - The actor is null!" ); + if(mIsStatic) + return; + + physx::PxRigidDynamic *actor = mActor->is(); + actor->setLinearDamping( linear ); + actor->setAngularDamping( angular ); +} + +void Px3Body::getState( PhysicsState *outState ) +{ + AssertFatal( mActor, "Px3Body::getState - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::getState - This call is only for dynamics!" ); + + outState->position = px3Cast( mActor->getGlobalPose().p ); + outState->orientation = px3Cast( mActor->getGlobalPose().q ); + + physx::PxRigidDynamic *actor = mActor->is(); + outState->linVelocity = px3Cast( actor->getLinearVelocity() ); + outState->angVelocity = px3Cast( actor->getAngularVelocity() ); + outState->sleeping = actor->isSleeping(); + outState->momentum = px3Cast( (1.0f/actor->getMass()) * actor->getLinearVelocity() );//?? + +} + +F32 Px3Body::getMass() const +{ + AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" ); + if(mIsStatic) + return 0; + + const physx::PxRigidDynamic *actor = mActor->is(); + return actor->getMass(); +} + +Point3F Px3Body::getCMassPosition() const +{ + AssertFatal( mActor, "Px3Body::getCMassPosition - The actor is null!" ); + if(mIsStatic) + return px3Cast(mActor->getGlobalPose().p); + + physx::PxRigidDynamic *actor = mActor->is(); + physx::PxTransform pose = actor->getGlobalPose() * actor->getCMassLocalPose(); + return px3Cast(pose.p); +} + +void Px3Body::setLinVelocity( const Point3F &vel ) +{ + AssertFatal( mActor, "Px3Body::setLinVelocity - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::setLinVelocity - This call is only for dynamics!" ); + + physx::PxRigidDynamic *actor = mActor->is(); + actor->setLinearVelocity( px3Cast( vel ) ); +} + +void Px3Body::setAngVelocity( const Point3F &vel ) +{ + AssertFatal( mActor, "Px3Body::setAngVelocity - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::setAngVelocity - This call is only for dynamics!" ); + + physx::PxRigidDynamic *actor = mActor->is(); + actor->setAngularVelocity(px3Cast( vel ) ); +} + +Point3F Px3Body::getLinVelocity() const +{ + AssertFatal( mActor, "Px3Body::getLinVelocity - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::getLinVelocity - This call is only for dynamics!" ); + + physx::PxRigidDynamic *actor = mActor->is(); + return px3Cast( actor->getLinearVelocity() ); +} + +Point3F Px3Body::getAngVelocity() const +{ + AssertFatal( mActor, "Px3Body::getAngVelocity - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::getAngVelocity - This call is only for dynamics!" ); + + physx::PxRigidDynamic *actor = mActor->is(); + return px3Cast( actor->getAngularVelocity() ); +} + +void Px3Body::setSleeping( bool sleeping ) +{ + AssertFatal( mActor, "Px3Body::setSleeping - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::setSleeping - This call is only for dynamics!" ); + + physx::PxRigidDynamic *actor = mActor->is(); + if ( sleeping ) + actor->putToSleep(); + else + actor->wakeUp(); +} + +bool Px3Body::isDynamic() const +{ + AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" ); + return !mIsStatic && ( mBodyFlags & BF_KINEMATIC ) == 0; +} + +PhysicsWorld* Px3Body::getWorld() +{ + return mWorld; +} + +PhysicsCollision* Px3Body::getColShape() +{ + return mColShape; +} + +MatrixF& Px3Body::getTransform( MatrixF *outMatrix ) +{ + AssertFatal( mActor, "Px3Body::getTransform - The actor is null!" ); + + *outMatrix = px3Cast(mActor->getGlobalPose()); + return *outMatrix; +} + +Box3F Px3Body::getWorldBounds() +{ + AssertFatal( mActor, "Px3Body::getTransform - The actor is null!" ); + + physx::PxBounds3 bounds; + bounds.setEmpty(); + physx::PxBounds3 shapeBounds; + + + U32 shapeCount = mActor->getNbShapes(); + physx::PxShape **shapes = new physx::PxShape*[shapeCount]; + mActor->getShapes(shapes, shapeCount); + for ( U32 i = 0; i < shapeCount; i++ ) + { + // Get the shape's bounds. + shapeBounds = physx::PxShapeExt::getWorldBounds(*shapes[i],*mActor); + // Combine them into the total bounds. + bounds.include( shapeBounds ); + } + + delete [] shapes; + + return px3Cast( bounds ); +} + +void Px3Body::setSimulationEnabled( bool enabled ) +{ + if ( mIsEnabled == enabled ) + return; + + //Don't need to enable/disable eSIMULATION_SHAPE for trigger,it's disabled permanently + if(mBodyFlags & BF_TRIGGER) + return; + + // This sucks, but it has to happen if we want + // to avoid write lock errors from PhysX right now. + mWorld->releaseWriteLock(); + + U32 shapeCount = mActor->getNbShapes(); + physx::PxShape **shapes = new physx::PxShape*[shapeCount]; + mActor->getShapes(shapes, shapeCount); + for ( S32 i = 0; i < mActor->getNbShapes(); i++ ) + { + shapes[i]->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,!mIsEnabled);//????? + } + + delete [] shapes; +} + +void Px3Body::setTransform( const MatrixF &transform ) +{ + AssertFatal( mActor, "Px3Body::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(); + + + mActor->setGlobalPose(px3Cast(transform),false); + + if(mIsStatic) + return; + + physx::PxRigidDynamic *actor = mActor->is(); + bool kinematic = actor->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC; + // If its dynamic we have more to do. + if ( isDynamic() && !kinematic ) + { + actor->setLinearVelocity( physx::PxVec3(0) ); + actor->setAngularVelocity( physx::PxVec3(0) ); + actor->wakeUp(); + } +} + +void Px3Body::applyCorrection( const MatrixF &transform ) +{ + AssertFatal( mActor, "Px3Body::applyCorrection - The actor is null!" ); + AssertFatal( isDynamic(), "Px3Body::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(); + + mActor->setGlobalPose( px3Cast(transform) ); +} + +void Px3Body::applyImpulse( const Point3F &origin, const Point3F &force ) +{ + AssertFatal( mActor, "Px3Body::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(); + physx::PxRigidDynamic *actor = mActor->is(); + if ( mIsEnabled && isDynamic() ) + physx::PxRigidBodyExt::addForceAtPos(*actor,px3Cast(force), + px3Cast(origin), + physx::PxForceMode::eIMPULSE); + +} + diff --git a/Engine/source/T3D/physics/physx3/px3Body.h b/Engine/source/T3D/physics/physx3/px3Body.h new file mode 100644 index 000000000..379d5b4cd --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Body.h @@ -0,0 +1,121 @@ +//----------------------------------------------------------------------------- +// 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_PX3BODY_H_ +#define _T3D_PHYSICS_PX3BODY_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 Px3World; +class Px3Collision; +struct Px3CollisionDesc; + +namespace physx{ + class PxRigidActor; + class PxMaterial; + class PxShape; +} + + +class Px3Body : public PhysicsBody +{ +protected: + + /// The physics world we are in. + Px3World *mWorld; + + /// The physics actor. + physx::PxRigidActor *mActor; + + /// The unshared local material used on all the + /// shapes on this actor. + physx::PxMaterial *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; + bool mIsStatic; + + /// + void _releaseActor(); + + +public: + + Px3Body(); + virtual ~Px3Body(); + + // 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 diff --git a/Engine/source/T3D/physics/physx3/px3Cast.h b/Engine/source/T3D/physics/physx3/px3Cast.h new file mode 100644 index 000000000..971e830c8 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Cast.h @@ -0,0 +1,137 @@ +//----------------------------------------------------------------------------- +// 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 _PHYSX3_CASTS_H_ +#define _PHYSX3_CASTS_H_ + +#ifndef _MPOINT3_H_ +#include "math/mPoint3.h" +#endif +#ifndef _MMATRIX_H_ +#include "math/mMatrix.h" +#endif +#ifndef _MBOX_H_ +#include "math/mBox.h" +#endif +#ifndef _MQUAT_H_ +#include "math/mQuat.h" +#endif +#ifndef _MTRANSFORM_H_ +#include "math/mTransform.h" +#endif + + +template inline T px3Cast( const F &from ); + +//------------------------------------------------------------------------- + +template<> +inline Point3F px3Cast( const physx::PxVec3 &vec ) +{ + return Point3F( vec.x, vec.y, vec.z ); +} + +template<> +inline physx::PxVec3 px3Cast( const Point3F &point ) +{ + return physx::PxVec3( point.x, point.y, point.z ); +} +//------------------------------------------------------------------------- +template<> +inline QuatF px3Cast( const physx::PxQuat &quat ) +{ + /// The Torque quat has the opposite winding order. + return QuatF( -quat.x, -quat.y, -quat.z, quat.w ); +} + +template<> +inline physx::PxQuat px3Cast( const QuatF &quat ) +{ + /// The Torque quat has the opposite winding order. + physx::PxQuat result( -quat.x, -quat.y, -quat.z, quat.w ); + return result; +} +//------------------------------------------------------------------------- + +template<> +inline physx::PxExtendedVec3 px3Cast( const Point3F &point ) +{ + return physx::PxExtendedVec3( point.x, point.y, point.z ); +} + +template<> +inline Point3F px3Cast( const physx::PxExtendedVec3 &xvec ) +{ + return Point3F( xvec.x, xvec.y, xvec.z ); +} + +//------------------------------------------------------------------------- + +template<> +inline physx::PxBounds3 px3Cast( const Box3F &box ) +{ + physx::PxBounds3 bounds(px3Cast(box.minExtents), + px3Cast(box.maxExtents)); + return bounds; +} + +template<> +inline Box3F px3Cast( const physx::PxBounds3 &bounds ) +{ + return Box3F( bounds.minimum.x, + bounds.minimum.y, + bounds.minimum.z, + bounds.maximum.x, + bounds.maximum.y, + bounds.maximum.z ); +} + +//------------------------------------------------------------------------- + +template<> +inline physx::PxTransform px3Cast( const MatrixF &xfm ) +{ + physx::PxTransform out; + QuatF q; + q.set(xfm); + out.q = px3Cast(q); + out.p = px3Cast(xfm.getPosition()); + return out; +} + +template<> +inline TransformF px3Cast(const physx::PxTransform &xfm) +{ + TransformF out(px3Cast(xfm.p),AngAxisF(px3Cast(xfm.q))); + return out; +} + +template<> +inline MatrixF px3Cast( const physx::PxTransform &xfm ) +{ + MatrixF out; + TransformF t = px3Cast(xfm); + out = t.getMatrix(); + return out; +} + +#endif diff --git a/Engine/source/T3D/physics/physx3/px3Collision.cpp b/Engine/source/T3D/physics/physx3/px3Collision.cpp new file mode 100644 index 000000000..fb11a4400 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Collision.cpp @@ -0,0 +1,212 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3Collision.h" + +#include "math/mPoint3.h" +#include "math/mMatrix.h" +#include "T3D/physics/physx3/px3.h" +#include "T3D/physics/physx3/px3Cast.h" +#include "T3D/physics/physx3/px3World.h" +#include "T3D/physics/physx3/px3Stream.h" + + +Px3Collision::Px3Collision() +{ +} + +Px3Collision::~Px3Collision() +{ + + for ( U32 i=0; i < mColShapes.size(); i++ ) + { + Px3CollisionDesc *desc = mColShapes[i]; + delete desc->pGeometry; + // Delete the descriptor. + delete desc; + } + + mColShapes.clear(); +} + +void Px3Collision::addPlane( const PlaneF &plane ) +{ + physx::PxVec3 pos = px3Cast(plane.getPosition()); + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxPlaneGeometry(); + desc->pose = physx::PxTransform(pos, physx::PxQuat(physx::PxHalfPi, physx::PxVec3(0.0f, -1.0f, 0.0f))); + mColShapes.push_back(desc); +} + +void Px3Collision::addBox( const Point3F &halfWidth,const MatrixF &localXfm ) +{ + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxBoxGeometry(px3Cast(halfWidth)); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); +} + +void Px3Collision::addSphere( F32 radius, + const MatrixF &localXfm ) +{ + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxSphereGeometry(radius); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); +} + +void Px3Collision::addCapsule( F32 radius, + F32 height, + const MatrixF &localXfm ) +{ + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxCapsuleGeometry(radius,height*0.5);//uses half height + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); +} + +bool Px3Collision::addConvex( const Point3F *points, + U32 count, + const MatrixF &localXfm ) +{ + physx::PxCooking *cooking = Px3World::getCooking(); + physx::PxConvexMeshDesc convexDesc; + convexDesc.points.data = points; + convexDesc.points.stride = sizeof(Point3F); + convexDesc.points.count = count; + convexDesc.flags = physx::PxConvexFlag::eFLIPNORMALS|physx::PxConvexFlag::eCOMPUTE_CONVEX | physx::PxConvexFlag::eINFLATE_CONVEX; + + Px3MemOutStream stream; + if(!cooking->cookConvexMesh(convexDesc,stream)) + return false; + + physx::PxConvexMesh* convexMesh; + Px3MemInStream in(stream.getData(), stream.getSize()); + convexMesh = gPhysics3SDK->createConvexMesh(in); + + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxConvexMeshGeometry(convexMesh); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); + return true; +} + +bool Px3Collision::addTriangleMesh( const Point3F *vert, + U32 vertCount, + const U32 *index, + U32 triCount, + const MatrixF &localXfm ) +{ + physx::PxCooking *cooking = Px3World::getCooking(); + physx::PxTriangleMeshDesc meshDesc; + meshDesc.points.count = vertCount; + meshDesc.points.data = vert; + meshDesc.points.stride = sizeof(Point3F); + + meshDesc.triangles.count = triCount; + meshDesc.triangles.data = index; + meshDesc.triangles.stride = 3*sizeof(U32); + meshDesc.flags = physx::PxMeshFlag::eFLIPNORMALS; + + Px3MemOutStream stream; + if(!cooking->cookTriangleMesh(meshDesc,stream)) + return false; + + physx::PxTriangleMesh *mesh; + Px3MemInStream in(stream.getData(), stream.getSize()); + mesh = gPhysics3SDK->createTriangleMesh(in); + + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = new physx::PxTriangleMeshGeometry(mesh); + desc->pose = px3Cast(localXfm); + mColShapes.push_back(desc); + return true; +} + +bool Px3Collision::addHeightfield( const U16 *heights, + const bool *holes, + U32 blockSize, + F32 metersPerSample, + const MatrixF &localXfm ) +{ + const F32 heightScale = 0.03125f; + physx::PxHeightFieldSample* samples = (physx::PxHeightFieldSample*) new physx::PxHeightFieldSample[blockSize*blockSize]; + memset(samples,0,blockSize*blockSize*sizeof(physx::PxHeightFieldSample)); + + physx::PxHeightFieldDesc heightFieldDesc; + heightFieldDesc.nbColumns = blockSize; + heightFieldDesc.nbRows = blockSize; + heightFieldDesc.thickness = -10.f; + heightFieldDesc.convexEdgeThreshold = 0; + heightFieldDesc.format = physx::PxHeightFieldFormat::eS16_TM; + heightFieldDesc.samples.data = samples; + heightFieldDesc.samples.stride = sizeof(physx::PxHeightFieldSample); + + physx::PxU8 *currentByte = (physx::PxU8*)heightFieldDesc.samples.data; + for ( U32 row = 0; row < blockSize; row++ ) + { + const U32 tess = ( row + 1 ) % 2; + + for ( U32 column = 0; column < blockSize; column++ ) + { + physx::PxHeightFieldSample *currentSample = (physx::PxHeightFieldSample*)currentByte; + + U32 index = ( blockSize - row - 1 ) + ( column * blockSize ); + currentSample->height = (physx::PxI16)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; + currentSample->materialIndex1 = 1; + } + + int flag = ( column + tess ) % 2; + if(flag) + currentSample->setTessFlag(); + else + currentSample->clearTessFlag(); + + currentByte += heightFieldDesc.samples.stride; + } + } + + physx::PxHeightField * hf = gPhysics3SDK->createHeightField(heightFieldDesc); + physx::PxHeightFieldGeometry *geom = new physx::PxHeightFieldGeometry(hf,physx::PxMeshGeometryFlags(),heightScale,metersPerSample,metersPerSample); + + physx::PxTransform pose= physx::PxTransform(physx::PxQuat(Float_HalfPi, physx::PxVec3(1, 0, 0 ))); + physx::PxTransform pose1= physx::PxTransform(physx::PxQuat(Float_Pi, physx::PxVec3(0, 0, 1 ))); + physx::PxTransform pose2 = pose1 * pose; + pose2.p = physx::PxVec3(( blockSize - 1 ) * metersPerSample, 0, 0 ); + Px3CollisionDesc *desc = new Px3CollisionDesc; + desc->pGeometry = geom; + desc->pose = pose2; + + mColShapes.push_back(desc); + return true; +} diff --git a/Engine/source/T3D/physics/physx3/px3Collision.h b/Engine/source/T3D/physics/physx3/px3Collision.h new file mode 100644 index 000000000..857f4f5e3 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Collision.h @@ -0,0 +1,87 @@ +//----------------------------------------------------------------------------- +// 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_PX3COLLISION_H_ +#define _T3D_PHYSICS_PX3COLLISION_H_ + +#ifndef _T3D_PHYSICS_PHYSICSCOLLISION_H_ +#include "T3D/physics/physicsCollision.h" +#endif +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif +#ifndef _MMATRIX_H_ +#include "math/mMatrix.h" +#endif +//nasty hate doing this! +#include + +//forward declare +namespace physx{class PxGeometry;} + + +struct Px3CollisionDesc +{ + physx::PxGeometry *pGeometry; + physx::PxTransform pose; +}; + +class Px3Collision : public PhysicsCollision +{ + typedef Vector Px3CollisionList; +protected: + /// The collision representation. + Px3CollisionList mColShapes; + +public: + + Px3Collision(); + virtual ~Px3Collision(); + + /// Return the PhysX shape descriptions. + const Px3CollisionList& 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 \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3Player.cpp b/Engine/source/T3D/physics/physx3/px3Player.cpp new file mode 100644 index 000000000..1c44068e9 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Player.cpp @@ -0,0 +1,328 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3Player.h" +#include "T3D/physics/physicsPlugin.h" +#include "T3D/physics/physx3/px3World.h" +#include "T3D/physics/physx3/px3Cast.h" +#include "T3D/physics/physx3/px3Utils.h" +#include "collision/collision.h" + + +Px3Player::Px3Player() + : PhysicsPlayer(), + mController( NULL ), + mWorld( NULL ), + mObject( NULL ), + mSkinWidth( 0.05f ), + mOriginOffset( 0.0f ), + mElapsed(0) +{ + PHYSICSMGR->getPhysicsResetSignal().notify( this, &Px3Player::_onPhysicsReset ); +} + +Px3Player::~Px3Player() +{ + _releaseController(); + PHYSICSMGR->getPhysicsResetSignal().remove( this, &Px3Player::_onPhysicsReset ); +} + +void Px3Player::_releaseController() +{ + if ( mController ) + { + mController->getActor()->userData = NULL; + mWorld->getStaticChangedSignal().remove( this, &Px3Player::_onStaticChanged ); + mController->release(); + } +} + +void Px3Player::init( const char *type, + const Point3F &size, + F32 runSurfaceCos, + F32 stepHeight, + SceneObject *obj, + PhysicsWorld *world ) +{ + AssertFatal( obj, "Px3Player::init - Got a null scene object!" ); + AssertFatal( world, "Px3Player::init - Got a null world!" ); + AssertFatal( dynamic_cast( world ), "Px3Player::init - The world is the wrong type!" ); + + // Cleanup any previous controller. + _releaseController(); + + mObject = obj; + mWorld = (Px3World*)world; + mOriginOffset = size.z * 0.5f; + + physx::PxCapsuleControllerDesc desc; + desc.contactOffset = mSkinWidth; + desc.radius = getMax( size.x, size.y ) * 0.5f; + desc.radius -= mSkinWidth; + desc.height = size.z - ( desc.radius * 2.0f ); + desc.height -= mSkinWidth * 2.0f; + desc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED; + desc.position.set( 0, 0, 0 ); + desc.upDirection = physx::PxVec3(0,0,1); + desc.reportCallback = this; + desc.slopeLimit = runSurfaceCos; + desc.stepOffset = stepHeight; + desc.behaviorCallback = NULL; + desc.material = gPhysics3SDK->createMaterial(0.1f, 0.1f, 0.2f); + + mController = mWorld->createController( desc ); + + mWorld->getStaticChangedSignal().notify( this, &Px3Player::_onStaticChanged ); + physx::PxRigidDynamic *kineActor = mController->getActor(); + + //player only has one shape + physx::PxShape *shape = px3GetFirstShape(kineActor); + physx::PxFilterData colData; + colData.word0 = PX3_PLAYER; + shape->setSimulationFilterData(colData); + shape->setQueryFilterData(colData); + + //store geometry for later use in findContact calls + shape->getCapsuleGeometry(mGeometry); + + mUserData.setObject( obj ); + kineActor->userData = &mUserData; + +} + +void Px3Player::_onStaticChanged() +{ + if(mController) + mController->invalidateCache(); +} + +void Px3Player::_onPhysicsReset( PhysicsResetEvent reset ) +{ + if(mController) + mController->invalidateCache(); +} + +Point3F Px3Player::move( const VectorF &disp, CollisionList &outCol ) +{ + AssertFatal( mController, "Px3Player::move - The controller is null!" ); + + // Return the last position if the simulation is stopped. + // + // See PxPlayer::_onPhysicsReset + if ( !mWorld->isEnabled() ) + { + Point3F newPos = px3Cast( mController->getPosition() ); + newPos.z -= mOriginOffset; + return newPos; + } + + mWorld->releaseWriteLock(); + + mCollisionList = &outCol; + + physx::PxVec3 dispNx( disp.x, disp.y, disp.z ); + if (mIsZero(disp.z)) + dispNx.z = 0.0f; + + U32 groups = 0xffffffff; + groups &= ~( PX3_TRIGGER ); // No trigger shapes! + groups &= ~( PX3_DEBRIS); + physx::PxControllerFilters filter; + physx::PxFilterData data; + data.word0=groups; + filter.mFilterData = &data; + filter.mFilterFlags = physx::PxSceneQueryFilterFlags(physx::PxControllerFlag::eCOLLISION_DOWN|physx::PxControllerFlag::eCOLLISION_SIDES|physx::PxControllerFlag::eCOLLISION_UP); + + mController->move( dispNx,0.0001f,0, filter ); + + Point3F newPos = px3Cast( mController->getPosition() ); + newPos.z -= mOriginOffset; + + mCollisionList = NULL; + + return newPos; +} + +void Px3Player::onShapeHit( const physx::PxControllerShapeHit& hit ) +{ + if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions) + return; + + physx::PxRigidActor *actor = hit.actor; + PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); + + // Fill out the Collision + // structure for use later. + Collision &col = mCollisionList->increment(); + dMemset( &col, 0, sizeof( col ) ); + + col.normal = px3Cast( hit.worldNormal ); + col.point = px3Cast( hit.worldPos ); + col.distance = hit.length; + if ( userData ) + col.object = userData->getObject(); + + if (mIsZero(hit.dir.z)) + { + if (col.normal.z > 0.0f) + { + col.normal.z = 0.0f; + col.normal.normalizeSafe(); + } + } + else + { + col.normal.set(0.0f, 0.0f, 1.0f); + } + + +} + +void Px3Player::onControllerHit( const physx::PxControllersHit& hit ) +{ + if (!mCollisionList || mCollisionList->getCount() >= CollisionList::MaxCollisions) + return; + + physx::PxRigidActor *actor = hit.other->getActor(); + PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); + + // 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(); + +} + +void Px3Player::findContact( SceneObject **contactObject, + VectorF *contactNormal, + Vector *outOverlapObjects ) const +{ + // Calculate the sweep motion... + F32 halfCapSize = mOriginOffset; + F32 halfSmallCapSize = halfCapSize * 0.8f; + F32 diff = halfCapSize - halfSmallCapSize; + + F32 distance = diff + mSkinWidth + 0.01f; + physx::PxVec3 dir(0,0,-1); + + physx::PxScene *scene = mWorld->getScene(); + physx::PxHitFlags hitFlags(physx::PxHitFlag::eDEFAULT); + physx::PxQueryFilterData filterData(physx::PxQueryFlag::eDYNAMIC|physx::PxQueryFlag::eSTATIC); + filterData.data.word0 = PX3_DEFAULT; + physx::PxSweepHit sweepHit; + physx::PxRigidDynamic *actor= mController->getActor(); + physx::PxU32 shapeIndex; + + bool hit = physx::PxRigidBodyExt::linearSweepSingle(*actor,*scene,dir,distance,hitFlags,sweepHit,shapeIndex,filterData); + if ( hit ) + { + PhysicsUserData *data = PhysicsUserData::cast( sweepHit.actor->userData); + if ( data ) + { + *contactObject = data->getObject(); + *contactNormal = px3Cast( sweepHit.normal ); + } + } + + // Check for overlapped objects ( triggers ) + + if ( !outOverlapObjects ) + return; + + filterData.data.word0 = PX3_TRIGGER; + + const physx::PxU32 bufferSize = 10; + physx::PxOverlapBufferN hitBuffer; + hit = scene->overlap(mGeometry,actor->getGlobalPose(),hitBuffer,filterData); + if(hit) + { + for ( U32 i = 0; i < hitBuffer.nbTouches; i++ ) + { + PhysicsUserData *data = PhysicsUserData::cast( hitBuffer.touches[i].actor->userData ); + if ( data ) + outOverlapObjects->push_back( data->getObject() ); + } + } + +} + +void Px3Player::enableCollision() +{ + AssertFatal( mController, "Px3Player::enableCollision - The controller is null!" ); + + mWorld->releaseWriteLock(); + px3GetFirstShape(mController->getActor())->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,true); +} + +void Px3Player::disableCollision() +{ + AssertFatal( mController, "Px3Player::disableCollision - The controller is null!" ); + + mWorld->releaseWriteLock(); + px3GetFirstShape(mController->getActor())->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE,false); +} + +PhysicsWorld* Px3Player::getWorld() +{ + return mWorld; +} + +void Px3Player::setTransform( const MatrixF &transform ) +{ + AssertFatal( mController, "Px3Player::setTransform - The controller is null!" ); + + mWorld->releaseWriteLock(); + + Point3F newPos = transform.getPosition(); + newPos.z += mOriginOffset; + + const Point3F &curPos = px3Cast(mController->getPosition()); + + if ( !(newPos - curPos ).isZero() ) + mController->setPosition( px3Cast(newPos) ); +} + +MatrixF& Px3Player::getTransform( MatrixF *outMatrix ) +{ + AssertFatal( mController, "Px3Player::getTransform - The controller is null!" ); + + Point3F newPos = px3Cast( mController->getPosition() ); + newPos.z -= mOriginOffset; + outMatrix->setPosition( newPos ); + + return *outMatrix; +} + +void Px3Player::setScale( const Point3F &scale ) +{ + //Ignored +} + +Box3F Px3Player::getWorldBounds() +{ + Con::warnf( "Px3Player::getWorldBounds - not implemented" ); + return Box3F::Invalid; +} + diff --git a/Engine/source/T3D/physics/physx3/px3Player.h b/Engine/source/T3D/physics/physx3/px3Player.h new file mode 100644 index 000000000..c8dee08e6 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Player.h @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// 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 _PX3PLAYER_H +#define _PX3PLAYER_H + +#ifndef _PHYSX3_H_ +#include "T3D/physics/physx3/px3.h" +#endif +#ifndef _T3D_PHYSICS_PHYSICSPLAYER_H_ +#include "T3D/physics/physicsPlayer.h" +#endif +#ifndef _T3D_PHYSICSCOMMON_H_ +#include "T3D/physics/physicsCommon.h" +#endif + +class Px3World; + +class Px3Player : public PhysicsPlayer, public physx::PxUserControllerHitReport +{ +protected: + + physx::PxController *mController; + physx::PxCapsuleGeometry mGeometry; + F32 mSkinWidth; + + Px3World *mWorld; + + SceneObject *mObject; + + /// Used to get collision info out of the + /// PxUserControllerHitReport callbacks. + CollisionList *mCollisionList; + + /// + F32 mOriginOffset; + + /// + F32 mStepHeight; + U32 mElapsed; + /// + void _releaseController(); + + + virtual void onShapeHit( const physx::PxControllerShapeHit &hit ); + virtual void onControllerHit( const physx::PxControllersHit &hit ); + virtual void onObstacleHit(const physx::PxControllerObstacleHit &){} + + void _findContact( SceneObject **contactObject, VectorF *contactNormal ) const; + + void _onPhysicsReset( PhysicsResetEvent reset ); + + void _onStaticChanged(); + +public: + + Px3Player(); + virtual ~Px3Player(); + + // 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/physx3/px3Plugin.cpp b/Engine/source/T3D/physics/physx3/px3Plugin.cpp new file mode 100644 index 000000000..9da0ca026 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Plugin.cpp @@ -0,0 +1,227 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3World.h" +#include "T3D/physics/physx3/px3Plugin.h" +#include "T3D/physics/physx3/px3Collision.h" +#include "T3D/physics/physx3/px3Body.h" +#include "T3D/physics/physx3/px3Player.h" + +#include "T3D/physics/physicsShape.h" +#include "T3D/gameBase/gameProcess.h" +#include "core/util/tNamedFactory.h" + + +AFTER_MODULE_INIT( Sim ) +{ + NamedFactory::add( "PhysX3", &Px3Plugin::create ); + + #if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON) + NamedFactory::add( "default", &Px3Plugin::create ); + #endif +} + +PhysicsPlugin* Px3Plugin::create() +{ + // Only create the plugin if it hasn't been set up AND + // the PhysX world is successfully initialized. + bool success = Px3World::restartSDK( false ); + if ( success ) + return new Px3Plugin(); + + return NULL; +} + +Px3Plugin::Px3Plugin() +{ +} + +Px3Plugin::~Px3Plugin() +{ +} + +void Px3Plugin::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(); + + Px3World::restartSDK( true ); + + delete this; +} + +void Px3Plugin::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* Px3Plugin::createCollision() +{ + return new Px3Collision(); +} + +PhysicsBody* Px3Plugin::createBody() +{ + return new Px3Body(); +} + +PhysicsPlayer* Px3Plugin::createPlayer() +{ + return new Px3Player(); +} + +bool Px3Plugin::isSimulationEnabled() const +{ + bool ret = false; + Px3World *world = static_cast( getWorld( smClientWorldName ) ); + if ( world ) + { + ret = world->isEnabled(); + return ret; + } + + world = static_cast( getWorld( smServerWorldName ) ); + if ( world ) + { + ret = world->isEnabled(); + return ret; + } + + return ret; +} + +void Px3Plugin::enableSimulation( const String &worldName, bool enable ) +{ + Px3World *world = static_cast( getWorld( worldName ) ); + if ( world ) + world->setEnabled( enable ); +} + +void Px3Plugin::setTimeScale( const F32 timeScale ) +{ + // Grab both the client and + // server worlds and set their time + // scales to the passed value. + Px3World *world = static_cast( getWorld( smClientWorldName ) ); + if ( world ) + world->setEditorTimeScale( timeScale ); + + world = static_cast( getWorld( smServerWorldName ) ); + if ( world ) + world->setEditorTimeScale( timeScale ); +} + +const F32 Px3Plugin::getTimeScale() const +{ + // Grab both the client and + // server worlds and call + // setEnabled( true ) on them. + Px3World *world = static_cast( getWorld( smClientWorldName ) ); + if ( !world ) + { + world = static_cast( getWorld( smServerWorldName ) ); + if ( !world ) + return 0.0f; + } + + return world->getEditorTimeScale(); +} + +bool Px3Plugin::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( "Px3Plugin::createWorld - %s world already exists!", worldName.c_str() ); + return false; + } + + world = new Px3World(); + + 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 Px3Plugin::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* Px3Plugin::getWorld( const String &worldName ) const +{ + if ( mPhysicsWorldLookup.isEmpty() ) + return NULL; + + Map::ConstIterator iter = mPhysicsWorldLookup.find( worldName ); + + return iter != mPhysicsWorldLookup.end() ? (*iter).value : NULL; +} + +PhysicsWorld* Px3Plugin::getWorld() const +{ + if ( mPhysicsWorldLookup.size() == 0 ) + return NULL; + + Map::ConstIterator iter = mPhysicsWorldLookup.begin(); + return iter->value; +} + +U32 Px3Plugin::getWorldCount() const +{ + return mPhysicsWorldLookup.size(); +} + diff --git a/Engine/source/T3D/physics/physx3/px3Plugin.h b/Engine/source/T3D/physics/physx3/px3Plugin.h new file mode 100644 index 000000000..7972fe59a --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Plugin.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// 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_PX3PLUGIN_H_ +#define _T3D_PHYSICS_PX3PLUGIN_H_ + +#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_ +#include "T3D/physics/physicsPlugin.h" +#endif + +class Px3Plugin : public PhysicsPlugin +{ +public: + + Px3Plugin(); + ~Px3Plugin(); + + /// 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; + +}; + +#endif \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3Stream.cpp b/Engine/source/T3D/physics/physx3/px3Stream.cpp new file mode 100644 index 000000000..f8374cf89 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Stream.cpp @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3Stream.h" + +#include "console/console.h" +#include "console/consoleTypes.h" +#include "core/strings/stringFunctions.h" + + +Px3MemOutStream::Px3MemOutStream() : mMemStream(1024) +{ +} + +Px3MemOutStream::~Px3MemOutStream() +{ +} + +physx::PxU32 Px3MemOutStream::write(const void *src, physx::PxU32 count) +{ + physx::PxU32 out=0; + if(!mMemStream.write(count,src)) + return out; + + out = count; + return out; +} + +Px3MemInStream::Px3MemInStream(physx::PxU8* data, physx::PxU32 length):mMemStream(length,data) +{ +} + +physx::PxU32 Px3MemInStream::read(void* dest, physx::PxU32 count) +{ + physx::PxU32 read =0; + if(!mMemStream.read(count,dest)) + return read; + + read = count; + return read; +} + +void Px3MemInStream::seek(physx::PxU32 pos) +{ + mMemStream.setPosition(pos); +} + +physx::PxU32 Px3MemInStream::getLength() const +{ + return mMemStream.getStreamSize(); +} + +physx::PxU32 Px3MemInStream::tell() const +{ + return mMemStream.getPosition(); +} + +Px3ConsoleStream::Px3ConsoleStream() +{ +} + +Px3ConsoleStream::~Px3ConsoleStream() +{ +} + +void Px3ConsoleStream::reportError( physx::PxErrorCode code, const char *message, const char* file, int line ) +{ + UTF8 info[1024]; + dSprintf( info, 1024, "File: %s\nLine: %d\n%s", file, line, message ); + Platform::AlertOK( "PhysX Error", info ); + // Con::printf( "PhysX Error:\n %s(%d) : %s\n", file, line, message ); +} \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3Stream.h b/Engine/source/T3D/physics/physx3/px3Stream.h new file mode 100644 index 000000000..155165881 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Stream.h @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// 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_PX3STREAM_H_ +#define _T3D_PHYSICS_PX3STREAM_H_ + +#ifndef _PHYSX3_H_ +#include "T3D/physics/physx3/px3.h" +#endif +#ifndef _MEMSTREAM_H_ +#include "core/stream/memStream.h" +#endif + + +class Px3MemOutStream : public physx::PxOutputStream +{ +public: + + Px3MemOutStream(); + virtual ~Px3MemOutStream(); + + void resetPosition(); + + virtual physx::PxU32 write(const void *src, physx::PxU32 count); + physx::PxU32 getSize() const {return mMemStream.getStreamSize();} + physx::PxU8* getData() const {return (physx::PxU8*)mMemStream.getBuffer();} + +protected: + + mutable MemStream mMemStream; +}; + +class Px3MemInStream: public physx::PxInputData +{ + public: + Px3MemInStream(physx::PxU8* data, physx::PxU32 length); + virtual physx::PxU32 read(void* dest, physx::PxU32 count); + physx::PxU32 getLength() const; + virtual void seek(physx::PxU32 pos); + virtual physx::PxU32 tell() const; +protected: + mutable MemStream mMemStream; + + }; + +class Px3ConsoleStream : public physx::PxDefaultErrorCallback +{ +protected: + + virtual void reportError( physx::PxErrorCode code, const char *message, const char* file, int line ); + +public: + + Px3ConsoleStream(); + virtual ~Px3ConsoleStream(); +}; + +#endif \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3Utils.cpp b/Engine/source/T3D/physics/physx3/px3Utils.cpp new file mode 100644 index 000000000..ced52198c --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Utils.cpp @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3Utils.h" +#include "T3D/physics/physx3/px3.h" + +physx::PxShape* px3GetFirstShape(physx::PxRigidActor *actor) +{ + physx::PxShape *shapes[1]; + actor->getShapes(shapes, 1); + return shapes[0]; +} diff --git a/Engine/source/T3D/physics/physx3/px3Utils.h b/Engine/source/T3D/physics/physx3/px3Utils.h new file mode 100644 index 000000000..d80b5acce --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3Utils.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// 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 _PHYSX3_UTILS_H_ +#define _PHYSX3_UTILS_H_ + +namespace physx +{ + class PxRigidActor; + class PxShape; +} + +extern physx::PxShape* px3GetFirstShape(physx::PxRigidActor *actor); + + +#endif \ No newline at end of file diff --git a/Engine/source/T3D/physics/physx3/px3World.cpp b/Engine/source/T3D/physics/physx3/px3World.cpp new file mode 100644 index 000000000..67fd78cf0 --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3World.cpp @@ -0,0 +1,567 @@ +//----------------------------------------------------------------------------- +// 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/physx3/px3World.h" + +#include "T3D/physics/physx3/px3.h" +#include "T3D/physics/physx3/px3Plugin.h" +#include "T3D/physics/physx3/px3Cast.h" +#include "T3D/physics/physx3/px3Stream.h" +#include "T3D/physics/physicsUserData.h" + +#include "console/engineAPI.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 "collision/collision.h" +#include "T3D/gameBase/gameProcess.h" +#include "gfx/sim/debugDraw.h" +#include "gfx/primBuilder.h" + + +physx::PxPhysics* gPhysics3SDK = NULL; +physx::PxCooking* Px3World::smCooking = NULL; +physx::PxFoundation* Px3World::smFoundation = NULL; +physx::PxProfileZoneManager* Px3World::smProfileZoneManager = NULL; +physx::PxDefaultCpuDispatcher* Px3World::smCpuDispatcher=NULL; +Px3ConsoleStream* Px3World::smErrorCallback = NULL; +physx::PxVisualDebuggerConnection* Px3World::smPvdConnection=NULL; +physx::PxDefaultAllocator Px3World::smMemoryAlloc; +//Physics timing +F32 Px3World::smPhysicsStepTime = 1.0f/(F32)TickMs; +U32 Px3World::smPhysicsMaxIterations = 4; + +Px3World::Px3World(): mScene( NULL ), + mProcessList( NULL ), + mIsSimulating( false ), + mErrorReport( false ), + mTickCount( 0 ), + mIsEnabled( false ), + mEditorTimeScale( 1.0f ), + mAccumulator( 0 ), + mControllerManager( NULL ) +{ +} + +Px3World::~Px3World() +{ +} + +physx::PxCooking *Px3World::getCooking() +{ + return smCooking; +} + +void Px3World::setTiming(F32 stepTime,U32 maxIterations) +{ + smPhysicsStepTime = stepTime; + smPhysicsMaxIterations = maxIterations; +} + +bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *serverWorld) +{ + // If either the client or the server still exist + // then we cannot reset the SDK. + if ( clientWorld || serverWorld ) + return false; + + if(smPvdConnection) + smPvdConnection->release(); + + if(smCooking) + smCooking->release(); + + if(smCpuDispatcher) + smCpuDispatcher->release(); + + // Destroy the existing SDK. + if ( gPhysics3SDK ) + { + PxCloseExtensions(); + gPhysics3SDK->release(); + } + + if(smErrorCallback) + { + SAFE_DELETE(smErrorCallback); + } + + if(smFoundation) + { + smFoundation->release(); + SAFE_DELETE(smErrorCallback); + } + + // If we're not supposed to restart... return. + if ( destroyOnly ) + return true; + + bool memTrack = false; + #ifdef TORQUE_DEBUG + memTrack = true; + #endif + + smErrorCallback = new Px3ConsoleStream; + smFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, smMemoryAlloc, *smErrorCallback); + smProfileZoneManager = &physx::PxProfileZoneManager::createProfileZoneManager(smFoundation); + gPhysics3SDK = PxCreatePhysics(PX_PHYSICS_VERSION, *smFoundation, physx::PxTolerancesScale(),memTrack,smProfileZoneManager); + + if ( !gPhysics3SDK ) + { + Con::errorf( "PhysX3 failed to initialize!" ); + Platform::messageBox( Con::getVariable( "$appName" ), + avar("PhysX3 could not be started!\r\n"), + MBOk, MIStop ); + Platform::forceShutdown( -1 ); + + // We shouldn't get here, but this shuts up + // source diagnostic tools. + return false; + } + + if(!PxInitExtensions(*gPhysics3SDK)) + { + Con::errorf( "PhysX3 failed to initialize extensions!" ); + Platform::messageBox( Con::getVariable( "$appName" ), + avar("PhysX3 could not be started!\r\n"), + MBOk, MIStop ); + Platform::forceShutdown( -1 ); + return false; + } + + smCooking = PxCreateCooking(PX_PHYSICS_VERSION, *smFoundation, physx::PxCookingParams(physx::PxTolerancesScale())); + if(!smCooking) + { + Con::errorf( "PhysX3 failed to initialize cooking!" ); + Platform::messageBox( Con::getVariable( "$appName" ), + avar("PhysX3 could not be started!\r\n"), + MBOk, MIStop ); + Platform::forceShutdown( -1 ); + return false; + } + + //just for testing-must remove, should really be enabled via console like physx 2 plugin +#ifdef TORQUE_DEBUG + physx::PxVisualDebuggerConnectionFlags connectionFlags(physx::PxVisualDebuggerExt::getAllConnectionFlags()); + smPvdConnection = physx::PxVisualDebuggerExt::createConnection(gPhysics3SDK->getPvdConnectionManager(), + "localhost", 5425, 100, connectionFlags); +#endif + + return true; +} + +void Px3World::destroyWorld() +{ + getPhysicsResults(); + + // Release the tick processing signals. + if ( mProcessList ) + { + mProcessList->preTickSignal().remove( this, &Px3World::getPhysicsResults ); + mProcessList->postTickSignal().remove( this, &Px3World::tickPhysics ); + mProcessList = NULL; + } + + if(mControllerManager) + { + mControllerManager->release(); + mControllerManager = NULL; + } + + // Destroy the scene. + if ( mScene ) + { + // Release the scene. + mScene->release(); + mScene = NULL; + } + +} + +bool Px3World::initWorld( bool isServer, ProcessList *processList ) +{ + if ( !gPhysics3SDK ) + { + Con::errorf( "Physx3World::init - PhysXSDK not initialized!" ); + return false; + } + + mIsServer = isServer; + + physx::PxSceneDesc sceneDesc(gPhysics3SDK->getTolerancesScale()); + + sceneDesc.gravity = px3Cast(mGravity); + sceneDesc.userData = this; + if(!sceneDesc.cpuDispatcher) + { + smCpuDispatcher = physx::PxDefaultCpuDispatcherCreate(PHYSICSMGR->getThreadCount()); + sceneDesc.cpuDispatcher = smCpuDispatcher; + Con::printf("PhysX3 using Cpu: %d workers", smCpuDispatcher->getWorkerCount()); + } + + sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVETRANSFORMS; + + sceneDesc.filterShader = physx::PxDefaultSimulationFilterShader; + + mScene = gPhysics3SDK->createScene(sceneDesc); + + physx::PxDominanceGroupPair debrisDominance( 0.0f, 1.0f ); + mScene->setDominanceGroupPair(0,31,debrisDominance); + + mControllerManager = PxCreateControllerManager(*mScene); + + AssertFatal( processList, "Px3World::init() - We need a process list to create the world!" ); + mProcessList = processList; + mProcessList->preTickSignal().notify( this, &Px3World::getPhysicsResults ); + mProcessList->postTickSignal().notify( this, &Px3World::tickPhysics, 1000.0f ); + + return true; +} +// Most of this borrowed from bullet physics library, see btDiscreteDynamicsWorld.cpp +bool Px3World::_simulate(const F32 dt) +{ + int numSimulationSubSteps = 0; + //fixed timestep with interpolation + mAccumulator += dt; + if (mAccumulator >= smPhysicsStepTime) + { + numSimulationSubSteps = int(mAccumulator / smPhysicsStepTime); + mAccumulator -= numSimulationSubSteps * smPhysicsStepTime; + } + if (numSimulationSubSteps) + { + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt + int clampedSimulationSteps = (numSimulationSubSteps > smPhysicsMaxIterations)? smPhysicsMaxIterations : numSimulationSubSteps; + + for (int i=0;ifetchResults(true); + mScene->simulate(smPhysicsStepTime); + } + } + + mIsSimulating = true; + + return true; +} + +void Px3World::tickPhysics( U32 elapsedMs ) +{ + if ( !mScene || !mIsEnabled ) + return; + + // Did we forget to call getPhysicsResults somewhere? + AssertFatal( !mIsSimulating, "PhysX3World::tickPhysics() - Already simulating!" ); + + // The elapsed time should be non-zero and + // a multiple of TickMs! + AssertFatal( elapsedMs != 0 && + ( elapsedMs % TickMs ) == 0 , "PhysX3World::tickPhysics() - Got bad elapsed time!" ); + + PROFILE_SCOPE(Px3World_TickPhysics); + + // Convert it to seconds. + const F32 elapsedSec = (F32)elapsedMs * 0.001f; + mIsSimulating = _simulate(elapsedSec * mEditorTimeScale); + + //Con::printf( "%s PhysX3World::tickPhysics!", mIsServer ? "Client" : "Server" ); +} + +void Px3World::getPhysicsResults() +{ + if ( !mScene || !mIsSimulating ) + return; + + PROFILE_SCOPE(Px3World_GetPhysicsResults); + + // Get results from scene. + mScene->fetchResults(true); + mIsSimulating = false; + mTickCount++; + + // Con::printf( "%s PhysXWorld::getPhysicsResults!", this == smClientWorld ? "Client" : "Server" ); +} + +void Px3World::releaseWriteLocks() +{ + Px3World *world = dynamic_cast( PHYSICSMGR->getWorld( "server" ) ); + + if ( world ) + world->releaseWriteLock(); + + world = dynamic_cast( PHYSICSMGR->getWorld( "client" ) ); + + if ( world ) + world->releaseWriteLock(); +} + +void Px3World::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( true ); + //AssertFatal( mScene->isWritable(), "PhysX3World::releaseWriteLock() - We should have been writable now!" ); +} + +bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse ) +{ + + physx::PxVec3 orig = px3Cast( startPnt ); + physx::PxVec3 dir = px3Cast( endPnt - startPnt ); + physx::PxF32 maxDist = dir.magnitude(); + dir.normalize(); + + U32 groups = 0xffffffff; + groups &= ~( PX3_TRIGGER ); // No trigger shapes! + + physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::eIMPACT | physx::PxHitFlag::eNORMAL); + physx::PxQueryFilterData filterData(physx::PxQueryFlag::eSTATIC|physx::PxQueryFlag::eDYNAMIC); + filterData.data.word0 = groups; + physx::PxRaycastBuffer buf; + + if(!mScene->raycast(orig,dir,maxDist,buf,outFlags,filterData)) + return false; + if(!buf.hasBlock) + return false; + + const physx::PxRaycastHit hit = buf.block; + physx::PxRigidActor *actor = hit.actor; + PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); + + if ( ri ) + { + ri->object = ( userData != NULL ) ? userData->getObject() : NULL; + + if ( ri->object == NULL ) + + ri->distance = hit.distance; + ri->normal = px3Cast( hit.normal ); + ri->point = px3Cast( hit.position ); + ri->t = maxDist / hit.distance; + } + + if ( impulse.isZero() || + !actor->isRigidDynamic() || + actor->is()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC ) + return true; + + physx::PxRigidBody *body = actor->is(); + physx::PxVec3 force = px3Cast( impulse ); + physx::PxRigidBodyExt::addForceAtPos(*body,force,hit.position,physx::PxForceMode::eIMPULSE); + + return true; +} + +PhysicsBody* Px3World::castRay( const Point3F &start, const Point3F &end, U32 bodyTypes ) +{ + physx::PxVec3 orig = px3Cast( start ); + physx::PxVec3 dir = px3Cast( end - start ); + physx::PxF32 maxDist = dir.magnitude(); + dir.normalize(); + + U32 groups = 0xFFFFFFFF; + if ( !( bodyTypes & BT_Player ) ) + groups &= ~( PX3_PLAYER ); + + // TODO: For now always skip triggers and debris, + // but we should consider how game specifc this API + // should be in the future. + groups &= ~( PX3_TRIGGER ); // triggers + groups &= ~( PX3_DEBRIS ); // debris + + physx::PxHitFlags outFlags(physx::PxHitFlag::eDISTANCE | physx::PxHitFlag::eIMPACT | physx::PxHitFlag::eNORMAL); + physx::PxQueryFilterData filterData; + if(bodyTypes & BT_Static) + filterData.flags |= physx::PxQueryFlag::eSTATIC; + if(bodyTypes & BT_Dynamic) + filterData.flags |= physx::PxQueryFlag::eDYNAMIC; + + filterData.data.word0 = groups; + physx::PxRaycastBuffer buf; + + if( !mScene->raycast(orig,dir,maxDist,buf,outFlags,filterData) ) + return NULL; + if(!buf.hasBlock) + return NULL; + + physx::PxRigidActor *actor = buf.block.actor; + PhysicsUserData *userData = PhysicsUserData::cast( actor->userData ); + if( !userData ) + return NULL; + + return userData->getBody(); +} + +void Px3World::explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ) +{ + physx::PxVec3 nxPos = px3Cast( pos ); + const physx::PxU32 bufferSize = 10; + physx::PxSphereGeometry worldSphere(radius); + physx::PxTransform pose(nxPos); + physx::PxOverlapBufferN buffer; + + if(!mScene->overlap(worldSphere,pose,buffer)) + return; + + for ( physx::PxU32 i = 0; i < buffer.nbTouches; i++ ) + { + physx::PxRigidActor *actor = buffer.touches[i].actor; + + bool dynamic = actor->isRigidDynamic(); + + if ( !dynamic ) + continue; + + bool kinematic = actor->is()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC; + + if ( kinematic ) + continue; + + physx::PxVec3 force = actor->getGlobalPose().p - nxPos; + force.normalize(); + force *= forceMagnitude; + + physx::PxRigidBody *body = actor->is(); + physx::PxRigidBodyExt::addForceAtPos(*body,force,nxPos,physx::PxForceMode::eIMPULSE); + } +} + +void Px3World::setEnabled( bool enabled ) +{ + mIsEnabled = enabled; + + if ( !mIsEnabled ) + getPhysicsResults(); +} + +physx::PxController* Px3World::createController( physx::PxControllerDesc &desc ) +{ + if ( !mScene ) + return NULL; + + // We need the writelock! + releaseWriteLock(); + physx::PxController* pController = mControllerManager->createController(desc); + AssertFatal( pController, "Px3World::createController - Got a null!" ); + return pController; +} + +static ColorI getDebugColor( physx::PxU32 packed ) +{ + ColorI col; + col.blue = (packed)&0xff; + col.green = (packed>>8)&0xff; + col.red = (packed>>16)&0xff; + col.alpha = 255; + + return col; +} + +void Px3World::onDebugDraw( const SceneRenderState *state ) +{ + if ( !mScene ) + return; + + mScene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE,1.0f); + mScene->setVisualizationParameter(physx::PxVisualizationParameter::eBODY_AXES,1.0f); + mScene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES,1.0f); + + const physx::PxRenderBuffer *renderBuffer = &mScene->getRenderBuffer(); + + if(!renderBuffer) + return; + + // Render points + { + physx::PxU32 numPoints = renderBuffer->getNbPoints(); + const physx::PxDebugPoint *points = renderBuffer->getPoints(); + + PrimBuild::begin( GFXPointList, numPoints ); + + while ( numPoints-- ) + { + PrimBuild::color( getDebugColor(points->color) ); + PrimBuild::vertex3fv(px3Cast(points->pos)); + points++; + } + + PrimBuild::end(); + } + + // Render lines + { + physx::PxU32 numLines = renderBuffer->getNbLines(); + const physx::PxDebugLine *lines = renderBuffer->getLines(); + + PrimBuild::begin( GFXLineList, numLines * 2 ); + + while ( numLines-- ) + { + PrimBuild::color( getDebugColor( lines->color0 ) ); + PrimBuild::vertex3fv( px3Cast(lines->pos0)); + PrimBuild::color( getDebugColor( lines->color1 ) ); + PrimBuild::vertex3fv( px3Cast(lines->pos1)); + lines++; + } + + PrimBuild::end(); + } + + // Render triangles + { + physx::PxU32 numTris = renderBuffer->getNbTriangles(); + const physx::PxDebugTriangle *triangles = renderBuffer->getTriangles(); + + PrimBuild::begin( GFXTriangleList, numTris * 3 ); + + while ( numTris-- ) + { + PrimBuild::color( getDebugColor( triangles->color0 ) ); + PrimBuild::vertex3fv( px3Cast(triangles->pos0) ); + PrimBuild::color( getDebugColor( triangles->color1 ) ); + PrimBuild::vertex3fv( px3Cast(triangles->pos1)); + PrimBuild::color( getDebugColor( triangles->color2 ) ); + PrimBuild::vertex3fv( px3Cast(triangles->pos2) ); + triangles++; + } + + PrimBuild::end(); + } + +} + +//set simulation timing via script +DefineEngineFunction( physx3SetSimulationTiming, void, ( F32 stepTime, U32 maxSteps ),, "Set simulation timing of the PhysX 3 plugin" ) +{ + Px3World::setTiming(stepTime,maxSteps); +} diff --git a/Engine/source/T3D/physics/physx3/px3World.h b/Engine/source/T3D/physics/physx3/px3World.h new file mode 100644 index 000000000..faf51a41a --- /dev/null +++ b/Engine/source/T3D/physics/physx3/px3World.h @@ -0,0 +1,110 @@ +//----------------------------------------------------------------------------- +// 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 _PHYSX3_WORLD_H_ +#define _PHYSX3_WORLD_H_ + +#ifndef _T3D_PHYSICS_PHYSICSWORLD_H_ +#include "T3D/physics/physicsWorld.h" +#endif +#ifndef _MMATH_H_ +#include "math/mMath.h" +#endif +#ifndef _PHYSX3_H_ +#include "T3D/physics/physx3/px3.h" +#endif +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif + +class Px3ConsoleStream; +class Px3ContactReporter; +class FixedStepper; + +enum Px3CollisionGroup +{ + PX3_DEFAULT = BIT(0), + PX3_PLAYER = BIT(1), + PX3_DEBRIS = BIT(2), + PX3_TRIGGER = BIT(3), +}; + +class Px3World : public PhysicsWorld +{ +protected: + + physx::PxScene* mScene; + + bool mIsEnabled; + bool mIsSimulating; + bool mIsServer; + U32 mTickCount; + ProcessList *mProcessList; + F32 mEditorTimeScale; + bool mErrorReport; + physx::PxControllerManager* mControllerManager; + static Px3ConsoleStream *smErrorCallback; + static physx::PxDefaultAllocator smMemoryAlloc; + static physx::PxFoundation* smFoundation; + static physx::PxCooking *smCooking; + static physx::PxProfileZoneManager* smProfileZoneManager; + static physx::PxDefaultCpuDispatcher* smCpuDispatcher; + static physx::PxVisualDebuggerConnection* smPvdConnection; + static F32 smPhysicsStepTime; + static U32 smPhysicsMaxIterations; + + F32 mAccumulator; + bool _simulate(const F32 dt); + +public: + + Px3World(); + virtual ~Px3World(); + + virtual bool initWorld( bool isServer, ProcessList *processList ); + virtual void destroyWorld(); + virtual void onDebugDraw( const SceneRenderState *state ); + virtual void reset() {} + 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 bool isEnabled() const { return mIsEnabled; } + physx::PxScene* getScene(){ return mScene;} + void setEnabled( bool enabled ); + U32 getTick() { return mTickCount; } + void tickPhysics( U32 elapsedMs ); + void getPhysicsResults(); + void setEditorTimeScale( F32 timeScale ) { mEditorTimeScale = timeScale; } + const F32 getEditorTimeScale() const { return mEditorTimeScale; } + void releaseWriteLock(); + bool isServer(){return mIsServer;} + physx::PxController* createController( physx::PxControllerDesc &desc ); + //static + static bool restartSDK( bool destroyOnly = false, Px3World *clientWorld = NULL, Px3World *serverWorld = NULL ); + static void releaseWriteLocks(); + static physx::PxCooking *getCooking(); + static void setTiming(F32 stepTime,U32 maxIterations); +}; + + + +#endif \ No newline at end of file diff --git a/Tools/projectGenerator/modules/physX3.inc b/Tools/projectGenerator/modules/physX3.inc new file mode 100644 index 000000000..42eb48b5a --- /dev/null +++ b/Tools/projectGenerator/modules/physX3.inc @@ -0,0 +1,106 @@ + From 5303fa4973be374b0bc1711dfe613544a2a44810 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Fri, 28 Feb 2014 12:19:02 +1000 Subject: [PATCH 2/8] Readme update. --- README.md | 177 +++++++++++++++--------------------------------------- 1 file changed, 48 insertions(+), 129 deletions(-) diff --git a/README.md b/README.md index 016232d4f..c4b6649e9 100644 --- a/README.md +++ b/README.md @@ -1,138 +1,57 @@ -Torque 3D v3.5 -============== +Torque 3D v3.5 - PhysX 3.3 Basic Plugin +========================== -MIT Licensed Open Source version of [Torque 3D](http://www.garagegames.com/products/torque-3d) from [GarageGames](http://www.garagegames.com) +This is a basic PhysX 3.3 plugin that does not contain any added features like cloth,particles and CCD. This plugin provides no more features than the bullet plugin and can therefore be used as a direct alternative. It does not modify any files outside of the physx3 folder. A far more advanced physx3 plugin with CCD, cloth and particles can be found on this repository under the physx branch. -More Information ----------------- +Setting up PhysX 3.3 using the Torque 3D Project Manager +------------------------------------------ + - You can find a pre compiled binary of the Torque3D Project Manager that supports PhysX 3.3 here: http://www.narivtech.com/downloads/T3DProjectManager-2-1-devel.zip and source code here: https://github.com/rextimmy/Torque3D-ProjectManager/tree/development + - For the Project Manager to find PhysX 3.3 SDK you have two options 1)Create an environment variable called TORQUE_PHYSX3_PATH and have that pointing to the location you installed the SDK 2)Place the SDK into a folder called "Program Files"/NVIDIA Corporation/NVIDIA PhysX SDK/v3.3.0_win + - Simply choose PhysX 3.3 physics from the modules list in the project manager and everything should be automatically taken care of. -* Torque 3D [main repository](https://github.com/GarageGames/Torque3D) -* Torque 3D [GitHub Wiki](https://github.com/GarageGames/Torque3D/wiki) -* Documentation is in the [Torque3D-Documentation](https://github.com/GarageGames/Torque3D-Documentation) GitHub repo. -* Project Manager is in the [Torque3D-ProjectManager](https://github.com/GarageGames/Torque3D-ProjectManager) GitHub repo. -* T3D [Beginner's Forum](http://www.garagegames.com/community/forums/73) -* T3D [Professional Forum](http://www.garagegames.com/community/forums/63) -* Torque 3D [FPS Tutorial](http://www.garagegames.com/products/torque-3d/fps#/1-setup/1) -* GarageGames [Store](http://www.garagegames.com/products) -* GarageGames [Professional Services](http://services.garagegames.com/) - -Pre-compiled Version --------------------- - -In addition to GitHub we also have a couple of pre-packaged files for you to download if you would prefer to not compile the code yourself: - -* [Complete Torque 3D 3.0 zip package](http://mit.garagegames.com/Torque3D-3-0.zip) with updated TorqueScript documentation, the *Project Manager*, and compiled versions of the templates. -* [Torque 3D Project Manager v2.0](http://mit.garagegames.com/T3DProjectManager-2-0.zip) on its own for use in your T3D forks. - -If you're looking for an older release see the [Torque 3D Archive](https://github.com/GarageGames/Torque3D/wiki/Torque-3D-Archive) - -Creating a New Project Based on a Template +Setting up PhysX 3.3 manually ------------------------------------------ -The templates included with Torque 3D provide a starting point for your project. Once we have created our own project based on a template we may then compile an executable and begin work on our game. The following templates are included in this version of Torque 3D: + - You will need the latest SDK from NVIDIA. This requires signing up for their developer program. If you don't already have access to their developer site then sign up now as access is not immediate. + - Set up a standard Torque3D project, don't include any PhysX or Bullet, just regular Torque Physics in project manager options (if you're using it) + - Generate Projects and open the source code in Visual Studio ( or the IDE of your choice ) + - In the solution explorer in the DLL for your project you should find Source Files -> Engine -> T3D -> physics + - Add a new filter "physx3" and then right click on it and add existing item + - Add all the files found under Engine\Source\T3D\physics\physx3\ + - Now you need to add the PhysX SDK. + - Under the properties for the DLL project, under Linker -> Additional Library Directories add the lib\win32 directory for the PhysX 3.3 SDK. For example, mine is in: C:\Program Files (x86)\NVIDIA Corporation\NVIDIA PhysX SDK\v3.3.0_win\Lib\win32 + - In the same window under C/C++ you should see Additional Include Directories, you need to add the Include directory for the PhysX 3.3 SDK. For example, mine is in: C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA PhysX SDK\v3.3.0_win\Include + - You should now be able to compile now without any issues. -* Empty -* Full +The following libraries will also be needed: + +Release , Debug -### Using PhysX ### + - PhysX3_x86.lib,PhysX3CHECKED_x86.lib + - PhysX3Common_x86.lib,PhysX3CommonCHECKED_x86.lib + - PhysX3Extensions.lib,PhysX3ExtensionsCHECKED.lib + - PhysX3Cooking_x86.lib,PhysX3CookingCHECKED_x86.lib + - PxTask.lib,PxTaskCHECKED.lib + - PhysX3CharacterKinematic_x86.lib,PhysX3CharacterKinematicCHECKED_x86.lib + - PhysXVisualDebuggerSDK.lib, PhysXVisualDebuggerSDKCHECKED.lib + - PhysXProfileSDK.lib, PhysXProfileSDKCHECKED.lib -If you plan on creating a project that uses PhysX you will first need to have the PhysX SDK intalled on your computer. Without the PhysX SDK in place the project generation step will fail when using either the *Project Manager* or manual project generation methods. +With debug build feel free to change CHECKED to DEBUG if you prefer but it will still require the CHECKED dll's though. + +Running a project +------------------------------------------ -PhysX SDK version 2.8.4.6 is required for Torque 3D's PhysX templates. The following steps are used to install this SDK: - -1. In a web browser, go to the [NVidia Support Center](http://supportcenteronline.com/ics/support/default.asp?deptID=1949) -2. If you do not have an account, you will need to register with them to have the support staff create an account for you. -3. If you have an account, login. -4. On the middle of the page, on the right, click on Downloads. -5. On the far right column, under Old downloads, click More. -6. Download the Windows 2.8.4.6 version. -7. Run the installer and follow the steps to install it in the default location. -8. Depending on your operating system version, you may need to reboot after the installation. - -### Using the Project Manager to Create a Project ### - -The *Project Manager* may be used to create a new game project based on one of the templates that are included with Torque 3D. If you are using Torque 3D directly from the [GitHub](https://github.com/GarageGames/Torque3D) repository then you will need to get the *Project Manager* from the [Torque3D-ProjectManager](https://github.com/GarageGames/Torque3D-ProjectManager) repo, or download a pre-compiled version from the [Project Manager Wiki Page](https://github.com/GarageGames/Torque3D/wiki/Project-Manager). - -The following steps use the *Project Manager* to create a new project. This is a quick summary and more detailed instructions may be found on the [Project Manager Wiki Page](https://github.com/GarageGames/Torque3D/wiki/Project-Manager) - -1. Run the *Project Manager*. -2. Click the *New Project* button. -3. Choose a template from the drop down on the right. -4. Pick which modules you want to compile into your project by using the *Choose Modules* button. -5. Give the project a name. -6. Click the *Create* button to create the project. This will open a new dialog window that shows the progress. -7. When it finishes, click the *Finished* button. -8. You may click on the *Open Folder* button to go to the project's directory. - -### Manually Creating a Project ### - -We may also manually create a project based on a template. The following steps outline how to do this: - -1. Open the *Templates* directory. -2. Right-click on the template you would like to use and choose *Copy*. -3. Go to the *My Projects* directory and paste the template there. -4. Rename the pasted template to the name of your project/game. -5. Go into your project's *game* directory and rename all executables, DLL files and the .torsion file (and maybe .torsion.opt) from the template name to that of your project (these files may not be present at this time). -6. Open the .torsion file in a text editor and replace all references to the template's name with that of your project (you only need to do this if you plan on using Torsion). You will need to also do this with the .torsion.opt if it exists. -7. Open you project's *source/torqueConfig.h* file in a text editor and change the `TORQUE_APP_NAME` define to the name of your project. -8. In your project's *buildFiles/config* directory open each .conf file and find each reference to the template's name and replace it with the name of your project. -9. Open your project's *game/main.cs* file in a text editor and change the `$appName` assignment to the name of your project. -10. Go to your project's directory and double click on the *generateProjects.bat* to create your project's solution files. - -Compiling Torque 3D (Windows) ------------------------------ -If this is the first time you will compile Torque 3D, or if you have added or removed any files to either the standard Torque 3D *Engine/source* directory or your project's *source* directory, you will need to run your project's *generateProjects.bat* file. This will rebuild your project's solution and project files. Now follow these steps to compile Torque 3D: - -1. Navigate to your project's *buildFiles/VisualStudio 2010* directory (or the *2008* directory if that is the version of Visual Studio you are using). -2. Double click on your project's .sln file. This will open Visual Studio. -3. When Visual Studio has fully loaded, press `F7` to start compiling your project. - -Compiling Torque 3D (Linux) ------------------------------ -This version of Torque 3D supports being run as a dedicated server under Linux. As with a Windows build you will need to run your project's *generateProjects.command* file to properly generate the required make file. - -Prior to compiling Torque 3D under Linux, you will need to make sure you have the appropriate libraries and tools installed. The exact packages will depend on which Linux distribution you are using. For example, under Ubuntu you will need: - -* build-essential -* nasm -* git -* php5-cli -* libsdl-dev -* libogg-dev - -With everything in place you may now follow these steps to compile Torque 3D: - -1. Change to you project's *buildFiles/Make_Ded* directory. -2. Enter the `make clean` command. -3. Enter the either the `make debug` or `make release` command depending on the type of build you wish to make. -4. Go to your project's *game* directory. -5. To start your game enter the following command (we'll use the name *MyGame* as the example project name): - `./MyGame -dedicated -mission "levels/Empty Terrain.mis"` - where the argument after the `-mission` switch is the path to the mission to load. - -Accessing the Editors ---------------------- -From the Main Menu or while in-game, pressing F10 opens the GUI Editor and pressing F11 opens the World Editor. - -License -------- - -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. + - To run a release project you will need the following from the SDK bin folder: + 1. PhysX3_x86.dll + 2. PhysX3CharacterKinematic_x86.dll + 3. PhysX3Common_x86.dll + 4. PhysX3Cooking_x86.dll + + - To run a debug project you will need the following from the SDK bin folder: + 1. PhysX3CHECKED_x86.dll + 2. nvToolsExt32_1.dll + 3. PhysX3CookingCHECKED_x86.dll + 4. PhysX3CommonCHECKED_x86.dll + 5. PhysX3CharacterKinematicCHECKED_x86.dll + +Place these files along side the exe and this should get you up and running. From c187c92edd152d272db994d7e1b2f1e6cd34dace Mon Sep 17 00:00:00 2001 From: rextimmy Date: Fri, 28 Feb 2014 12:21:10 +1000 Subject: [PATCH 3/8] Readme update #2 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4b6649e9..93e4b09b4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Torque 3D v3.5 - PhysX 3.3 Basic Plugin ========================== -This is a basic PhysX 3.3 plugin that does not contain any added features like cloth,particles and CCD. This plugin provides no more features than the bullet plugin and can therefore be used as a direct alternative. It does not modify any files outside of the physx3 folder. A far more advanced physx3 plugin with CCD, cloth and particles can be found on this repository under the physx branch. +This is a basic PhysX 3.3 plugin that does not contain any added features like cloth,particles and CCD. This plugin provides no more features than the bullet plugin and can therefore be used as a drop in alternative. It does not modify any files outside of the physx3 folder. A far more advanced physx3 plugin with CCD, cloth and particles can be found on this repository under the physx3 branch. Setting up PhysX 3.3 using the Torque 3D Project Manager ------------------------------------------ From 87ba9a70843a1b9a46389274aded6e4e74dd2442 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sat, 7 Jun 2014 12:11:44 +1000 Subject: [PATCH 4/8] code cleanup --- Engine/source/T3D/physics/physx3/px3Body.cpp | 24 +------------------ Engine/source/T3D/physics/physx3/px3Body.h | 2 +- Engine/source/T3D/physics/physx3/px3World.cpp | 21 +--------------- README.md | 14 +++++++++++ 4 files changed, 17 insertions(+), 44 deletions(-) diff --git a/Engine/source/T3D/physics/physx3/px3Body.cpp b/Engine/source/T3D/physics/physx3/px3Body.cpp index 4adc39a3c..026309f08 100644 --- a/Engine/source/T3D/physics/physx3/px3Body.cpp +++ b/Engine/source/T3D/physics/physx3/px3Body.cpp @@ -147,10 +147,6 @@ bool Px3Body::init( PhysicsCollision *shape, { physx::PxRigidDynamic *actor = mActor->is(); physx::PxRigidBodyExt::setMassAndUpdateInertia(*actor,mass); - if(mBodyFlags & BF_CCD) - actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD, true); - else - actor->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD, false); } // This sucks, but it has to happen if we want @@ -223,7 +219,7 @@ void Px3Body::getState( PhysicsState *outState ) outState->linVelocity = px3Cast( actor->getLinearVelocity() ); outState->angVelocity = px3Cast( actor->getAngularVelocity() ); outState->sleeping = actor->isSleeping(); - outState->momentum = px3Cast( (1.0f/actor->getMass()) * actor->getLinearVelocity() );//?? + outState->momentum = px3Cast( (1.0f/actor->getMass()) * actor->getLinearVelocity() ); } @@ -368,24 +364,6 @@ void Px3Body::setSimulationEnabled( bool enabled ) delete [] shapes; } - -void Px3Body::moveKinematicTo( const MatrixF &transform ) -{ - AssertFatal( mActor, "Px3Body::moveKinematicTo - The actor is null!" ); - - const bool isKinematic = mBodyFlags & BF_KINEMATIC; - if (!isKinematic ) - { - Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies."); - return; - } - - mWorld->releaseWriteLock(); - - physx::PxRigidDynamic *actor = mActor->is(); - actor->setKinematicTarget(px3Cast(transform)); -} - void Px3Body::setTransform( const MatrixF &transform ) { AssertFatal( mActor, "Px3Body::setTransform - The actor is null!" ); diff --git a/Engine/source/T3D/physics/physx3/px3Body.h b/Engine/source/T3D/physics/physx3/px3Body.h index 4fcb223d1..79096f57b 100644 --- a/Engine/source/T3D/physics/physx3/px3Body.h +++ b/Engine/source/T3D/physics/physx3/px3Body.h @@ -88,7 +88,6 @@ public: // PhysicsObject virtual PhysicsWorld* getWorld(); virtual void setTransform( const MatrixF &xfm ); - virtual void moveKinematicTo( const MatrixF &xfm ); virtual MatrixF& getTransform( MatrixF *outMatrix ); virtual Box3F getWorldBounds(); virtual void setSimulationEnabled( bool enabled ); @@ -100,6 +99,7 @@ public: U32 bodyFlags, SceneObject *obj, PhysicsWorld *world ); + virtual bool isDynamic() const; virtual PhysicsCollision* getColShape(); virtual void setSleepThreshold( F32 linear, F32 angular ); diff --git a/Engine/source/T3D/physics/physx3/px3World.cpp b/Engine/source/T3D/physics/physx3/px3World.cpp index a7617a723..4f333b733 100644 --- a/Engine/source/T3D/physics/physx3/px3World.cpp +++ b/Engine/source/T3D/physics/physx3/px3World.cpp @@ -54,23 +54,6 @@ physx::PxDefaultAllocator Px3World::smMemoryAlloc; F32 Px3World::smPhysicsStepTime = 1.0f/(F32)TickMs; U32 Px3World::smPhysicsMaxIterations = 4; -//filter shader with support for CCD pairs -static physx::PxFilterFlags sCcdFilterShader( - physx::PxFilterObjectAttributes attributes0, - physx::PxFilterData filterData0, - physx::PxFilterObjectAttributes attributes1, - physx::PxFilterData filterData1, - physx::PxPairFlags& pairFlags, - const void* constantBlock, - physx::PxU32 constantBlockSize) -{ - pairFlags = physx::PxPairFlag::eRESOLVE_CONTACTS; - pairFlags |= physx::PxPairFlag::eCCD_LINEAR; - return physx::PxFilterFlags(); -} - - - Px3World::Px3World(): mScene( NULL ), mProcessList( NULL ), mIsSimulating( false ), @@ -180,7 +163,6 @@ bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *se return false; } - //just for testing-must remove, should really be enabled via console like physx 2 plugin #ifdef TORQUE_DEBUG physx::PxVisualDebuggerConnectionFlags connectionFlags(physx::PxVisualDebuggerExt::getAllConnectionFlags()); smPvdConnection = physx::PxVisualDebuggerExt::createConnection(gPhysics3SDK->getPvdConnectionManager(), @@ -241,8 +223,7 @@ bool Px3World::initWorld( bool isServer, ProcessList *processList ) sceneDesc.flags |= physx::PxSceneFlag::eENABLE_CCD; sceneDesc.flags |= physx::PxSceneFlag::eENABLE_ACTIVETRANSFORMS; - - sceneDesc.filterShader = sCcdFilterShader; + sceneDesc.filterShader = physx::PxDefaultSimulationFilterShader; mScene = gPhysics3SDK->createScene(sceneDesc); diff --git a/README.md b/README.md index 93e4b09b4..c06f58f4e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ +<<<<<<< HEAD Torque 3D v3.5 - PhysX 3.3 Basic Plugin ========================== +======= +Torque 3D v3.5.1 +================ +>>>>>>> GarageGames/development This is a basic PhysX 3.3 plugin that does not contain any added features like cloth,particles and CCD. This plugin provides no more features than the bullet plugin and can therefore be used as a drop in alternative. It does not modify any files outside of the physx3 folder. A far more advanced physx3 plugin with CCD, cloth and particles can be found on this repository under the physx3 branch. @@ -25,6 +30,7 @@ Setting up PhysX 3.3 manually The following libraries will also be needed: +<<<<<<< HEAD Release , Debug - PhysX3_x86.lib,PhysX3CHECKED_x86.lib @@ -39,6 +45,14 @@ Release , Debug With debug build feel free to change CHECKED to DEBUG if you prefer but it will still require the CHECKED dll's though. Running a project +======= +* [Complete Torque 3D 3.5.1 zip package](http://mit.garagegames.com/Torque3D-3-5-1.zip) with updated TorqueScript documentation, the *Project Manager*, and compiled versions of the templates. +* [Torque 3D Project Manager v2.1](http://mit.garagegames.com/T3DProjectManager-2-1.zip) on its own for use in your T3D forks. + +If you're looking for an older release see the [Torque 3D Archive](https://github.com/GarageGames/Torque3D/wiki/Torque-3D-Archive) + +Creating a New Project Based on a Template +>>>>>>> GarageGames/development ------------------------------------------ - To run a release project you will need the following from the SDK bin folder: From 2ddce1a9b3617c45b69334d191153c46bd04ba46 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sat, 7 Jun 2014 12:14:00 +1000 Subject: [PATCH 5/8] README update --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index c06f58f4e..b2199e922 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,5 @@ -<<<<<<< HEAD -Torque 3D v3.5 - PhysX 3.3 Basic Plugin +Torque 3D v3.5.1 - PhysX 3.3 Basic Plugin ========================== -======= -Torque 3D v3.5.1 -================ ->>>>>>> GarageGames/development This is a basic PhysX 3.3 plugin that does not contain any added features like cloth,particles and CCD. This plugin provides no more features than the bullet plugin and can therefore be used as a drop in alternative. It does not modify any files outside of the physx3 folder. A far more advanced physx3 plugin with CCD, cloth and particles can be found on this repository under the physx3 branch. @@ -30,7 +25,6 @@ Setting up PhysX 3.3 manually The following libraries will also be needed: -<<<<<<< HEAD Release , Debug - PhysX3_x86.lib,PhysX3CHECKED_x86.lib From 1ca3190994c01c0b42bd257f12acb7555d2e750e Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sat, 7 Jun 2014 12:23:12 +1000 Subject: [PATCH 6/8] Removed old px3Cast --- Engine/source/T3D/physics/physx3/px3Cast.h | 137 --------------------- 1 file changed, 137 deletions(-) delete mode 100644 Engine/source/T3D/physics/physx3/px3Cast.h diff --git a/Engine/source/T3D/physics/physx3/px3Cast.h b/Engine/source/T3D/physics/physx3/px3Cast.h deleted file mode 100644 index 971e830c8..000000000 --- a/Engine/source/T3D/physics/physx3/px3Cast.h +++ /dev/null @@ -1,137 +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 _PHYSX3_CASTS_H_ -#define _PHYSX3_CASTS_H_ - -#ifndef _MPOINT3_H_ -#include "math/mPoint3.h" -#endif -#ifndef _MMATRIX_H_ -#include "math/mMatrix.h" -#endif -#ifndef _MBOX_H_ -#include "math/mBox.h" -#endif -#ifndef _MQUAT_H_ -#include "math/mQuat.h" -#endif -#ifndef _MTRANSFORM_H_ -#include "math/mTransform.h" -#endif - - -template inline T px3Cast( const F &from ); - -//------------------------------------------------------------------------- - -template<> -inline Point3F px3Cast( const physx::PxVec3 &vec ) -{ - return Point3F( vec.x, vec.y, vec.z ); -} - -template<> -inline physx::PxVec3 px3Cast( const Point3F &point ) -{ - return physx::PxVec3( point.x, point.y, point.z ); -} -//------------------------------------------------------------------------- -template<> -inline QuatF px3Cast( const physx::PxQuat &quat ) -{ - /// The Torque quat has the opposite winding order. - return QuatF( -quat.x, -quat.y, -quat.z, quat.w ); -} - -template<> -inline physx::PxQuat px3Cast( const QuatF &quat ) -{ - /// The Torque quat has the opposite winding order. - physx::PxQuat result( -quat.x, -quat.y, -quat.z, quat.w ); - return result; -} -//------------------------------------------------------------------------- - -template<> -inline physx::PxExtendedVec3 px3Cast( const Point3F &point ) -{ - return physx::PxExtendedVec3( point.x, point.y, point.z ); -} - -template<> -inline Point3F px3Cast( const physx::PxExtendedVec3 &xvec ) -{ - return Point3F( xvec.x, xvec.y, xvec.z ); -} - -//------------------------------------------------------------------------- - -template<> -inline physx::PxBounds3 px3Cast( const Box3F &box ) -{ - physx::PxBounds3 bounds(px3Cast(box.minExtents), - px3Cast(box.maxExtents)); - return bounds; -} - -template<> -inline Box3F px3Cast( const physx::PxBounds3 &bounds ) -{ - return Box3F( bounds.minimum.x, - bounds.minimum.y, - bounds.minimum.z, - bounds.maximum.x, - bounds.maximum.y, - bounds.maximum.z ); -} - -//------------------------------------------------------------------------- - -template<> -inline physx::PxTransform px3Cast( const MatrixF &xfm ) -{ - physx::PxTransform out; - QuatF q; - q.set(xfm); - out.q = px3Cast(q); - out.p = px3Cast(xfm.getPosition()); - return out; -} - -template<> -inline TransformF px3Cast(const physx::PxTransform &xfm) -{ - TransformF out(px3Cast(xfm.p),AngAxisF(px3Cast(xfm.q))); - return out; -} - -template<> -inline MatrixF px3Cast( const physx::PxTransform &xfm ) -{ - MatrixF out; - TransformF t = px3Cast(xfm); - out = t.getMatrix(); - return out; -} - -#endif From b0c83601d1bdc1a1eb5a7f6b64ddd8d4360d9a32 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sat, 7 Jun 2014 12:32:42 +1000 Subject: [PATCH 7/8] Readme fixup --- README.md | 175 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 124 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index b2199e922..d2085998f 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,138 @@ -Torque 3D v3.5.1 - PhysX 3.3 Basic Plugin -========================== +Torque 3D v3.5.1 +================ -This is a basic PhysX 3.3 plugin that does not contain any added features like cloth,particles and CCD. This plugin provides no more features than the bullet plugin and can therefore be used as a drop in alternative. It does not modify any files outside of the physx3 folder. A far more advanced physx3 plugin with CCD, cloth and particles can be found on this repository under the physx3 branch. +MIT Licensed Open Source version of [Torque 3D](http://www.garagegames.com/products/torque-3d) from [GarageGames](http://www.garagegames.com) -Setting up PhysX 3.3 using the Torque 3D Project Manager ------------------------------------------- - - You can find a pre compiled binary of the Torque3D Project Manager that supports PhysX 3.3 here: http://www.narivtech.com/downloads/T3DProjectManager-2-1-devel.zip and source code here: https://github.com/rextimmy/Torque3D-ProjectManager/tree/development - - For the Project Manager to find PhysX 3.3 SDK you have two options 1)Create an environment variable called TORQUE_PHYSX3_PATH and have that pointing to the location you installed the SDK 2)Place the SDK into a folder called "Program Files"/NVIDIA Corporation/NVIDIA PhysX SDK/v3.3.0_win - - Simply choose PhysX 3.3 physics from the modules list in the project manager and everything should be automatically taken care of. +More Information +---------------- -Setting up PhysX 3.3 manually ------------------------------------------- +* Torque 3D [main repository](https://github.com/GarageGames/Torque3D) +* Torque 3D [GitHub Wiki](https://github.com/GarageGames/Torque3D/wiki) +* Documentation is in the [Torque3D-Documentation](https://github.com/GarageGames/Torque3D-Documentation) GitHub repo. +* Project Manager is in the [Torque3D-ProjectManager](https://github.com/GarageGames/Torque3D-ProjectManager) GitHub repo. +* T3D [Beginner's Forum](http://www.garagegames.com/community/forums/73) +* T3D [Professional Forum](http://www.garagegames.com/community/forums/63) +* Torque 3D [FPS Tutorial](http://www.garagegames.com/products/torque-3d/fps#/1-setup/1) +* GarageGames [Store](http://www.garagegames.com/products) +* GarageGames [Professional Services](http://services.garagegames.com/) - - You will need the latest SDK from NVIDIA. This requires signing up for their developer program. If you don't already have access to their developer site then sign up now as access is not immediate. - - Set up a standard Torque3D project, don't include any PhysX or Bullet, just regular Torque Physics in project manager options (if you're using it) - - Generate Projects and open the source code in Visual Studio ( or the IDE of your choice ) - - In the solution explorer in the DLL for your project you should find Source Files -> Engine -> T3D -> physics - - Add a new filter "physx3" and then right click on it and add existing item - - Add all the files found under Engine\Source\T3D\physics\physx3\ - - Now you need to add the PhysX SDK. - - Under the properties for the DLL project, under Linker -> Additional Library Directories add the lib\win32 directory for the PhysX 3.3 SDK. For example, mine is in: C:\Program Files (x86)\NVIDIA Corporation\NVIDIA PhysX SDK\v3.3.0_win\Lib\win32 - - In the same window under C/C++ you should see Additional Include Directories, you need to add the Include directory for the PhysX 3.3 SDK. For example, mine is in: C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA PhysX SDK\v3.3.0_win\Include - - You should now be able to compile now without any issues. +Pre-compiled Version +-------------------- -The following libraries will also be needed: +In addition to GitHub we also have a couple of pre-packaged files for you to download if you would prefer to not compile the code yourself: -Release , Debug - - - PhysX3_x86.lib,PhysX3CHECKED_x86.lib - - PhysX3Common_x86.lib,PhysX3CommonCHECKED_x86.lib - - PhysX3Extensions.lib,PhysX3ExtensionsCHECKED.lib - - PhysX3Cooking_x86.lib,PhysX3CookingCHECKED_x86.lib - - PxTask.lib,PxTaskCHECKED.lib - - PhysX3CharacterKinematic_x86.lib,PhysX3CharacterKinematicCHECKED_x86.lib - - PhysXVisualDebuggerSDK.lib, PhysXVisualDebuggerSDKCHECKED.lib - - PhysXProfileSDK.lib, PhysXProfileSDKCHECKED.lib - -With debug build feel free to change CHECKED to DEBUG if you prefer but it will still require the CHECKED dll's though. - -Running a project -======= * [Complete Torque 3D 3.5.1 zip package](http://mit.garagegames.com/Torque3D-3-5-1.zip) with updated TorqueScript documentation, the *Project Manager*, and compiled versions of the templates. * [Torque 3D Project Manager v2.1](http://mit.garagegames.com/T3DProjectManager-2-1.zip) on its own for use in your T3D forks. If you're looking for an older release see the [Torque 3D Archive](https://github.com/GarageGames/Torque3D/wiki/Torque-3D-Archive) Creating a New Project Based on a Template ->>>>>>> GarageGames/development ------------------------------------------ - - To run a release project you will need the following from the SDK bin folder: - 1. PhysX3_x86.dll - 2. PhysX3CharacterKinematic_x86.dll - 3. PhysX3Common_x86.dll - 4. PhysX3Cooking_x86.dll - - - To run a debug project you will need the following from the SDK bin folder: - 1. PhysX3CHECKED_x86.dll - 2. nvToolsExt32_1.dll - 3. PhysX3CookingCHECKED_x86.dll - 4. PhysX3CommonCHECKED_x86.dll - 5. PhysX3CharacterKinematicCHECKED_x86.dll - -Place these files along side the exe and this should get you up and running. +The templates included with Torque 3D provide a starting point for your project. Once we have created our own project based on a template we may then compile an executable and begin work on our game. The following templates are included in this version of Torque 3D: + +* Empty +* Full + +### Using PhysX ### + +If you plan on creating a project that uses PhysX you will first need to have the PhysX SDK intalled on your computer. Without the PhysX SDK in place the project generation step will fail when using either the *Project Manager* or manual project generation methods. + +PhysX SDK version 2.8.4.6 is required for Torque 3D's PhysX templates. The following steps are used to install this SDK: + +1. In a web browser, go to the [NVidia Support Center](http://supportcenteronline.com/ics/support/default.asp?deptID=1949) +2. If you do not have an account, you will need to register with them to have the support staff create an account for you. +3. If you have an account, login. +4. On the middle of the page, on the right, click on Downloads. +5. On the far right column, under Old downloads, click More. +6. Download the Windows 2.8.4.6 version. +7. Run the installer and follow the steps to install it in the default location. +8. Depending on your operating system version, you may need to reboot after the installation. + +### Using the Project Manager to Create a Project ### + +The *Project Manager* may be used to create a new game project based on one of the templates that are included with Torque 3D. If you are using Torque 3D directly from the [GitHub](https://github.com/GarageGames/Torque3D) repository then you will need to get the *Project Manager* from the [Torque3D-ProjectManager](https://github.com/GarageGames/Torque3D-ProjectManager) repo, or download a pre-compiled version from the [Project Manager Wiki Page](https://github.com/GarageGames/Torque3D/wiki/Project-Manager). + +The following steps use the *Project Manager* to create a new project. This is a quick summary and more detailed instructions may be found on the [Project Manager Wiki Page](https://github.com/GarageGames/Torque3D/wiki/Project-Manager) + +1. Run the *Project Manager*. +2. Click the *New Project* button. +3. Choose a template from the drop down on the right. +4. Pick which modules you want to compile into your project by using the *Choose Modules* button. +5. Give the project a name. +6. Click the *Create* button to create the project. This will open a new dialog window that shows the progress. +7. When it finishes, click the *Finished* button. +8. You may click on the *Open Folder* button to go to the project's directory. + +### Manually Creating a Project ### + +We may also manually create a project based on a template. The following steps outline how to do this: + +1. Open the *Templates* directory. +2. Right-click on the template you would like to use and choose *Copy*. +3. Go to the *My Projects* directory and paste the template there. +4. Rename the pasted template to the name of your project/game. +5. Go into your project's *game* directory and rename all executables, DLL files and the .torsion file (and maybe .torsion.opt) from the template name to that of your project (these files may not be present at this time). +6. Open the .torsion file in a text editor and replace all references to the template's name with that of your project (you only need to do this if you plan on using Torsion). You will need to also do this with the .torsion.opt if it exists. +7. Open you project's *source/torqueConfig.h* file in a text editor and change the `TORQUE_APP_NAME` define to the name of your project. +8. In your project's *buildFiles/config* directory open each .conf file and find each reference to the template's name and replace it with the name of your project. +9. Open your project's *game/main.cs* file in a text editor and change the `$appName` assignment to the name of your project. +10. Go to your project's directory and double click on the *generateProjects.bat* to create your project's solution files. + +Compiling Torque 3D (Windows) +----------------------------- +If this is the first time you will compile Torque 3D, or if you have added or removed any files to either the standard Torque 3D *Engine/source* directory or your project's *source* directory, you will need to run your project's *generateProjects.bat* file. This will rebuild your project's solution and project files. Now follow these steps to compile Torque 3D: + +1. Navigate to your project's *buildFiles/VisualStudio 2010* directory (or the *2008* directory if that is the version of Visual Studio you are using). +2. Double click on your project's .sln file. This will open Visual Studio. +3. When Visual Studio has fully loaded, press `F7` to start compiling your project. + +Compiling Torque 3D (Linux) +----------------------------- +This version of Torque 3D supports being run as a dedicated server under Linux. As with a Windows build you will need to run your project's *generateProjects.command* file to properly generate the required make file. + +Prior to compiling Torque 3D under Linux, you will need to make sure you have the appropriate libraries and tools installed. The exact packages will depend on which Linux distribution you are using. For example, under Ubuntu you will need: + +* build-essential +* nasm +* git +* php5-cli +* libsdl-dev +* libogg-dev + +With everything in place you may now follow these steps to compile Torque 3D: + +1. Change to you project's *buildFiles/Make_Ded* directory. +2. Enter the `make clean` command. +3. Enter the either the `make debug` or `make release` command depending on the type of build you wish to make. +4. Go to your project's *game* directory. +5. To start your game enter the following command (we'll use the name *MyGame* as the example project name): + `./MyGame -dedicated -mission "levels/Empty Terrain.mis"` + where the argument after the `-mission` switch is the path to the mission to load. + +Accessing the Editors +--------------------- +From the Main Menu or while in-game, pressing F10 opens the GUI Editor and pressing F11 opens the World Editor. + +License +------- + +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. \ No newline at end of file From 664595ef9e5828d1f7e5e02cc4abecdd01a82b11 Mon Sep 17 00:00:00 2001 From: rextimmy Date: Sat, 8 Nov 2014 14:08:59 +1000 Subject: [PATCH 8/8] - Fixed memory leak when creating terrain with physx 3 - Fixed terrain tessellation with physx 3 --- Engine/source/T3D/physics/physx3/px3Collision.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/physics/physx3/px3Collision.cpp b/Engine/source/T3D/physics/physx3/px3Collision.cpp index e24b097e3..e03a0f00b 100644 --- a/Engine/source/T3D/physics/physx3/px3Collision.cpp +++ b/Engine/source/T3D/physics/physx3/px3Collision.cpp @@ -191,9 +191,9 @@ bool Px3Collision::addHeightfield( const U16 *heights, int flag = ( column + tess ) % 2; if(flag) - currentSample->setTessFlag(); - else currentSample->clearTessFlag(); + else + currentSample->setTessFlag(); currentByte += heightFieldDesc.samples.stride; } @@ -211,5 +211,7 @@ bool Px3Collision::addHeightfield( const U16 *heights, desc->pose = pose2; mColShapes.push_back(desc); + + SAFE_DELETE(samples); return true; }