Răsfoiți Sursa

Merge pull request #685 from rextimmy/physx3_basic

Physx3 Physics Plugin
Daniel Buckmaster 10 ani în urmă
părinte
comite
a0e1fca057

+ 53 - 0
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_WIN) && !defined(WIN32)
+   #define WIN32
+#endif
+
+//-------------------------------------------------------------------------
+
+#include <PxPhysicsAPI.h>
+#include <PxExtensionsAPI.h>
+#include <PxDefaultErrorCallback.h>
+#include <PxDefaultAllocator.h>
+#include <PxDefaultSimulationFilterShader.h>
+#include <PxDefaultCpuDispatcher.h>
+#include <PxShapeExt.h>
+#include <PxSimpleFactory.h>
+#include <PxFoundation.h>
+#include <PxController.h>
+#include <PxIO.h> 
+
+
+extern physx::PxPhysics* gPhysics3SDK;
+
+#endif // _PHYSX3_

+ 419 - 0
Engine/source/T3D/physics/physx3/px3Body.cpp

@@ -0,0 +1,419 @@
+//-----------------------------------------------------------------------------
+// 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/px3Casts.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<Px3World*>( world ), "Px3Body::init - The world is the wrong type!" );
+   AssertFatal( shape, "Px3Body::init - Got a null collision shape!" );
+   AssertFatal( dynamic_cast<Px3Collision*>( 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<physx::PxRigidDynamic>();
+		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<Px3CollisionDesc*> &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);
+	   physx::PxFilterData colData;
+	   if(isDebris)
+			colData.word0 = PX3_DEBRIS;
+	   else if(isTrigger)
+        colData.word0 = PX3_TRIGGER;
+	   else
+		   colData.word0 = PX3_DEFAULT;
+
+      //set local pose - actor->createShape with a local pose is deprecated in physx 3.3
+      pShape->setLocalPose(desc->pose);
+      //set the skin width
+      pShape->setContactOffset(0.01f);
+      pShape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, !isTrigger);
+      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::PxRigidDynamic>();
+		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<physx::PxRigidDynamic>();
+      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::PxRigidDynamic>();
+   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<physx::PxRigidDynamic>();
+   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<Point3F>( mActor->getGlobalPose().p );
+   outState->orientation = px3Cast<QuatF>( mActor->getGlobalPose().q );
+
+   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
+   outState->linVelocity = px3Cast<Point3F>( actor->getLinearVelocity() ); 
+   outState->angVelocity = px3Cast<Point3F>( actor->getAngularVelocity() );
+   outState->sleeping = actor->isSleeping();
+   outState->momentum = px3Cast<Point3F>( (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<physx::PxRigidDynamic>();
+   return actor->getMass();
+}
+
+Point3F Px3Body::getCMassPosition() const
+{
+   AssertFatal( mActor, "Px3Body::getCMassPosition - The actor is null!" );
+   if(mIsStatic)
+	   return px3Cast<Point3F>(mActor->getGlobalPose().p);
+
+   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
+   physx::PxTransform pose = actor->getGlobalPose() * actor->getCMassLocalPose();
+   return px3Cast<Point3F>(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<physx::PxRigidDynamic>();
+   actor->setLinearVelocity( px3Cast<physx::PxVec3>( 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<physx::PxRigidDynamic>();
+   actor->setAngularVelocity(px3Cast<physx::PxVec3>( 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<physx::PxRigidDynamic>();
+   return px3Cast<Point3F>( 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<physx::PxRigidDynamic>();
+   return px3Cast<Point3F>( 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<physx::PxRigidDynamic>();
+   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<MatrixF>(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<Box3F>( 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<physx::PxTransform>(transform),false);
+
+   if(mIsStatic)
+	   return;
+
+	physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
+	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<physx::PxTransform>(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<physx::PxRigidDynamic>();
+   if ( mIsEnabled && isDynamic() )
+   physx::PxRigidBodyExt::addForceAtPos(*actor,px3Cast<physx::PxVec3>(force),
+												px3Cast<physx::PxVec3>(origin),
+												physx::PxForceMode::eIMPULSE);
+
+}
+

+ 122 - 0
Engine/source/T3D/physics/physx3/px3Body.h

@@ -0,0 +1,122 @@
+//-----------------------------------------------------------------------------
+// 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 _PX3BODY_H_
+#define _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<Px3Collision> 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 // _PX3BODY_H_

+ 137 - 0
Engine/source/T3D/physics/physx3/px3Casts.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 _PX3CASTS_H_
+#define _PX3CASTS_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 <class T, class F> 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<physx::PxVec3>(box.minExtents),
+							px3Cast<physx::PxVec3>(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<physx::PxQuat>(q);
+   out.p = px3Cast<physx::PxVec3>(xfm.getPosition());
+   return out;
+}
+
+template<>
+inline TransformF px3Cast(const physx::PxTransform &xfm)
+{
+	TransformF out(px3Cast<Point3F>(xfm.p),AngAxisF(px3Cast<QuatF>(xfm.q)));
+	return out;
+}
+
+template<>
+inline MatrixF px3Cast( const physx::PxTransform &xfm )
+{
+   MatrixF out;
+   TransformF t = px3Cast<TransformF>(xfm);
+   out = t.getMatrix();
+   return out;
+}
+
+#endif //_PX3CASTS_H_

+ 217 - 0
Engine/source/T3D/physics/physx3/px3Collision.cpp

@@ -0,0 +1,217 @@
+//-----------------------------------------------------------------------------
+// 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/px3Casts.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<physx::PxVec3>(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<physx::PxVec3>(halfWidth));
+	desc->pose = px3Cast<physx::PxTransform>(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<physx::PxTransform>(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<physx::PxTransform>(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;
+   physx::PxVec3 scale = px3Cast<physx::PxVec3>(localXfm.getScale());
+   physx::PxQuat rotation = px3Cast<physx::PxQuat>(QuatF(localXfm));
+   physx::PxMeshScale meshScale(scale,rotation);
+	desc->pGeometry = new physx::PxConvexMeshGeometry(convexMesh,meshScale);
+	desc->pose = px3Cast<physx::PxTransform>(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<physx::PxTransform>(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 = physx::PxHeightFieldMaterial::eHOLE;
+            currentSample->materialIndex1 = physx::PxHeightFieldMaterial::eHOLE;
+         }
+         else
+         {
+            currentSample->materialIndex0 = 0;
+            currentSample->materialIndex1 = 0;
+         }
+
+		int flag = ( column + tess ) % 2;
+		if(flag)
+			currentSample->clearTessFlag();
+		else
+			currentSample->setTessFlag();
+
+         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);
+
+   SAFE_DELETE(samples);
+	return true;
+}

+ 87 - 0
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 _PX3COLLISION_H_
+#define _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
+
+#include <foundation/PxTransform.h>
+
+//forward declare
+namespace physx{class PxGeometry;}
+
+
+struct Px3CollisionDesc
+{
+	physx::PxGeometry *pGeometry;
+	physx::PxTransform pose;
+};
+
+class Px3Collision : public PhysicsCollision
+{
+	typedef Vector<Px3CollisionDesc*> 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 // _PX3COLLISION_H_

+ 331 - 0
Engine/source/T3D/physics/physx3/px3Player.cpp

@@ -0,0 +1,331 @@
+//-----------------------------------------------------------------------------
+// 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/px3Casts.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<Px3World*>( 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<Point3F>( 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<Point3F>( 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<Point3F>( hit.worldNormal );
+   col.point = px3Cast<Point3F>( 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<SceneObject*> *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<Point3F>( sweepHit.normal );
+      }
+   }
+
+  // Check for overlapped objects ( triggers )
+
+   if ( !outOverlapObjects )
+      return;
+
+   filterData.data.word0 = PX3_TRIGGER;
+
+	const physx::PxU32 bufferSize = 10;
+   physx::PxOverlapBufferN<bufferSize> 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<Point3F>(mController->getPosition());
+   
+   if ( !(newPos - curPos ).isZero() )
+      mController->setPosition( px3Cast<physx::PxExtendedVec3>(newPos) );
+}
+
+MatrixF& Px3Player::getTransform( MatrixF *outMatrix )
+{
+   AssertFatal( mController, "Px3Player::getTransform - The controller is null!" );
+
+   Point3F newPos = px3Cast<Point3F>( mController->getPosition() );
+   newPos.z -= mOriginOffset;
+   outMatrix->setPosition( newPos );
+
+   return *outMatrix;
+}
+
+void Px3Player::setScale( const Point3F &scale )
+{
+   //Ignored
+}
+
+Box3F Px3Player::getWorldBounds()
+{
+   physx::PxBounds3 bounds;
+   physx::PxRigidDynamic *actor = mController->getActor();
+   physx::PxShape *shape = px3GetFirstShape(actor);
+   bounds = physx::PxShapeExt::getWorldBounds(*shape,*actor);
+   return px3Cast<Box3F>( bounds );
+}
+

+ 104 - 0
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<SceneObject*> *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 // _PX3PLAYER_H_

+ 226 - 0
Engine/source/T3D/physics/physx3/px3Plugin.cpp

@@ -0,0 +1,226 @@
+//-----------------------------------------------------------------------------
+// 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<PhysicsPlugin>::add( "PhysX3", &Px3Plugin::create );
+
+   #if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)   
+      NamedFactory<PhysicsPlugin>::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<StringNoCase, PhysicsWorld*>::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<StringNoCase, PhysicsWorld*>::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<Px3World*>( getWorld( smClientWorldName ) );
+   if ( world )
+   {
+      ret = world->isEnabled();
+      return ret;
+   }
+
+   world = static_cast<Px3World*>( getWorld( smServerWorldName ) );
+   if ( world )
+   {
+      ret = world->isEnabled();
+      return ret;
+   }
+
+   return ret;
+}
+
+void Px3Plugin::enableSimulation( const String &worldName, bool enable )
+{
+   Px3World *world = static_cast<Px3World*>( 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<Px3World*>( getWorld( smClientWorldName ) );
+   if ( world )
+      world->setEditorTimeScale( timeScale );
+
+   world = static_cast<Px3World*>( 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<Px3World*>( getWorld( smClientWorldName ) );
+   if ( !world )
+   {
+      world = static_cast<Px3World*>( getWorld( smServerWorldName ) );
+      if ( !world )
+         return 0.0f;
+   }
+   
+   return world->getEditorTimeScale();
+}
+
+bool Px3Plugin::createWorld( const String &worldName )
+{
+   Map<StringNoCase, PhysicsWorld*>::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<StringNoCase, PhysicsWorld*>::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<StringNoCase, PhysicsWorld*>::ConstIterator iter = mPhysicsWorldLookup.find( worldName );
+
+   return iter != mPhysicsWorldLookup.end() ? (*iter).value : NULL;
+}
+
+PhysicsWorld* Px3Plugin::getWorld() const
+{
+   if ( mPhysicsWorldLookup.size() == 0 )
+      return NULL;
+
+   Map<StringNoCase, PhysicsWorld*>::ConstIterator iter = mPhysicsWorldLookup.begin();
+   return iter->value;
+}
+
+U32 Px3Plugin::getWorldCount() const
+{ 
+   return mPhysicsWorldLookup.size(); 
+}

+ 59 - 0
Engine/source/T3D/physics/physx3/px3Plugin.h

@@ -0,0 +1,59 @@
+//-----------------------------------------------------------------------------
+// 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 _PX3PLUGIN_H_
+#define _PX3PLUGIN_H_
+
+#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_
+#include "T3D/physics/physicsPlugin.h"
+#endif
+
+class Px3ClothShape;
+
+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  // _PX3PLUGIN_H_

+ 92 - 0
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 );
+}

+ 77 - 0
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 _PX3STREAM_H_
+#define _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 // _PX3STREAM_H_

+ 32 - 0
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];
+}

+ 34 - 0
Engine/source/T3D/physics/physx3/px3Utils.h

@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------------
+// 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 _PX3UTILS_H_
+#define _PX3UTILS_H_
+
+namespace physx
+{
+	class PxRigidActor;
+   class PxShape;
+}
+
+extern physx::PxShape* px3GetFirstShape(physx::PxRigidActor *actor);
+
+#endif // _PX3UTILS_H_

+ 565 - 0
Engine/source/T3D/physics/physx3/px3World.cpp

@@ -0,0 +1,565 @@
+//-----------------------------------------------------------------------------
+// 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/px3Casts.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;
+	}
+
+#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<physx::PxVec3>(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_CCD;
+   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;i<clampedSimulationSteps;i++)
+		{
+			mScene->fetchResults(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<Px3World*>( PHYSICSMGR->getWorld( "server" ) );
+
+	if ( world )
+		world->releaseWriteLock();
+
+	world = dynamic_cast<Px3World*>( 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<physx::PxVec3>( startPnt );
+   physx::PxVec3 dir = px3Cast<physx::PxVec3>( 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<Point3F>( hit.normal );
+      ri->point = px3Cast<Point3F>( hit.position );
+      ri->t = maxDist / hit.distance;
+   }
+
+   if ( impulse.isZero() ||
+        !actor->isRigidDynamic() ||
+        actor->is<physx::PxRigidDynamic>()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC )
+      return true;
+  
+   physx::PxRigidBody *body = actor->is<physx::PxRigidBody>();
+   physx::PxVec3 force = px3Cast<physx::PxVec3>( 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<physx::PxVec3>( start );
+   physx::PxVec3 dir = px3Cast<physx::PxVec3>( 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<physx::PxVec3>( pos );
+   const physx::PxU32 bufferSize = 10;
+   physx::PxSphereGeometry worldSphere(radius);
+   physx::PxTransform pose(nxPos);
+   physx::PxOverlapBufferN<bufferSize> 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<physx::PxRigidDynamic>()->getRigidDynamicFlags() & physx::PxRigidDynamicFlag::eKINEMATIC;
+      
+      if ( kinematic )
+         continue;
+
+      physx::PxVec3 force = actor->getGlobalPose().p - nxPos;
+      force.normalize();
+      force *= forceMagnitude;
+
+      physx::PxRigidBody *body = actor->is<physx::PxRigidBody>();
+      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<Point3F>(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<Point3F>(lines->pos0));
+         PrimBuild::color( getDebugColor( lines->color1 ) );
+         PrimBuild::vertex3fv( px3Cast<Point3F>(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<Point3F>(triangles->pos0) );
+         PrimBuild::color( getDebugColor( triangles->color1 ) );
+         PrimBuild::vertex3fv( px3Cast<Point3F>(triangles->pos1));
+         PrimBuild::color( getDebugColor( triangles->color2 ) );
+         PrimBuild::vertex3fv( px3Cast<Point3F>(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);
+}

+ 106 - 0
Engine/source/T3D/physics/physx3/px3World.h

@@ -0,0 +1,106 @@
+//-----------------------------------------------------------------------------
+// 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 _PX3WORLD_H_
+#define _PX3WORLD_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 // _PX3WORLD_H_

+ 1 - 1
README.md

@@ -137,4 +137,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 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
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE.
+IN THE SOFTWARE.

+ 112 - 0
Tools/projectGenerator/modules/physX3.inc

@@ -0,0 +1,112 @@
+<?php
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+beginModule( 'physX3' );
+
+   // Look for the optional global from the project.conf.
+   global $PHYSX3_SDK_PATH;
+   if (!$PHYSX3_SDK_PATH)
+   {
+      // First look for an environment var.
+      $PHYSX3_SDK_PATH = getenv( "TORQUE_PHYSX3_PATH" );
+
+      if (strlen($PHYSX3_SDK_PATH) == 0 || !file_exists($PHYSX3_SDK_PATH))
+      {
+         // Sometimes users get confused and use this var.
+         $PHYSX3_SDK_PATH = getenv( "PHYSX3_SDK_PATH" );
+
+         if (strlen($PHYSX3_SDK_PATH) == 0 || !file_exists($PHYSX3_SDK_PATH))
+         {
+            // Since neither environment var worked try for 
+            $PHYSX3_SDK_PATH = getenv("ProgramFiles") . "/NVIDIA Corporation/NVIDIA PhysX SDK/v3.3.0_win";
+
+            // Last channce... try the x86 program files
+            if (!file_exists($PHYSX_SDK_PATH))
+               $PHYSX3_SDK_PATH = getenv("ProgramFiles(x86)") . "/NVIDIA Corporation/NVIDIA PhysX SDK/v3.3.0_win";
+         }
+      }
+
+      // We need forward slashes for paths.
+      $PHYSX3_SDK_PATH = str_replace( "\\", "/", $PHYSX3_SDK_PATH);
+
+      // Remove trailing slashes.
+      $PHYSX3_SDK_PATH = rtrim($PHYSX3_SDK_PATH, " /");
+   }
+
+   // If we still don't have the SDK path then let the user know.
+   if (!file_exists($PHYSX3_SDK_PATH))
+   {
+      trigger_error( 
+            "\n*******************************************************************".
+            "\n".
+            "\n  We were not able to find a valid path to the PhysX 3 SDK!".
+            "\n".
+            "\n  You must install the latest PhysX3 SDK and set the path via a".
+            "\n  \$PHYSX3_SDK_PATH variable in your buildFiles/project.conf file".
+            "\n  or by setting the TORQUE_PHYSX3_PATH system environment variable".
+            "\n  (may require a reboot).".
+            "\n".
+            "\n*******************************************************************".
+            "\n", E_USER_ERROR );
+   }
+
+   addProjectDefine( "TORQUE_PHYSICS_PHYSX3" );
+   addProjectDefine( "TORQUE_PHYSICS_ENABLED" );
+
+   // Source
+   addEngineSrcDir( "T3D/physics/physx3" );
+   addEngineSrcDir( "T3D/physics/physx3/Cloth" );
+   addEngineSrcDir( "T3D/physics/physx3/Particles" );
+
+   // Includes
+   addIncludePath( $PHYSX3_SDK_PATH . "/Include" );
+   addIncludePath( $PHYSX3_SDK_PATH . "/Include/extensions" );
+   addIncludePath( $PHYSX3_SDK_PATH . "/Include/foundation" );
+   addIncludePath( $PHYSX3_SDK_PATH . "/Include/characterkinematic" );
+   addIncludePath( $PHYSX3_SDK_PATH . "/Include/common" );
+      
+   // Libs
+   addProjectLibDir( $PHYSX3_SDK_PATH . "/Lib/win32" );
+   addProjectLibInput( "PhysX3_x86.lib","PhysX3CHECKED_x86.lib" );
+   addProjectLibInput( "PhysX3Common_x86.lib","PhysX3CommonCHECKED_x86.lib");
+   addProjectLibInput( "PhysX3Extensions.lib","PhysX3ExtensionsCHECKED.lib" );
+   addProjectLibInput( "PhysX3Cooking_x86.lib","PhysX3CookingCHECKED_x86.lib");
+   addProjectLibInput( "PxTask.lib","PxTaskCHECKED.lib" );
+   addProjectLibInput( "PhysX3CharacterKinematic_x86.lib","PhysX3CharacterKinematicCHECKED_x86.lib" );
+   addProjectLibInput( "PhysXVisualDebuggerSDK.lib", "PhysXVisualDebuggerSDKCHECKED.lib");
+   addProjectLibInput( "PhysXProfileSDK.lib", "PhysXProfileSDKCHECKED.lib");
+          
+   // File Copy
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/nvToolsExt32_1.dll", "/game/nvToolsExt32_1.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3_x86.dll",  "/game/PhysX3_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3CharacterKinematic_x86.dll",     "/game/PhysX3CharacterKinematic_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3CharacterKinematicCHECKED_x86.dll",   "/game/PhysX3CharacterKinematicCHECKED_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3CHECKED_x86.dll",   "/game/PhysX3CHECKED_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3Common_x86.dll",   "/game/PhysX3Common_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3CommonCHECKED_x86.dll",   "/game/PhysX3CommonCHECKED_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3Cooking_x86.dll",   "/game/PhysX3Cooking_x86.dll" );
+   copyFileToProject( $PHYSX3_SDK_PATH . "/Bin/win32/PhysX3CookingCHECKED_x86.dll",   "/game/PhysX3CookingCHECKED_x86.dll" );
+
+endModule();
+
+?>