Browse Source

PhysX3 basic plugin.

rextimmy 11 years ago
parent
commit
d4b189e175

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

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

@@ -0,0 +1,421 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "T3D/physics/physx3/px3Body.h"
+
+#include "T3D/physics/physx3/px3.h"
+#include "T3D/physics/physx3/px3Cast.h"
+#include "T3D/physics/physx3/px3World.h"
+#include "T3D/physics/physx3/px3Collision.h"
+
+#include "console/console.h"
+#include "console/consoleTypes.h"
+
+
+Px3Body::Px3Body() :
+   mActor( NULL ),
+   mMaterial( NULL ),
+   mWorld( NULL ),
+   mBodyFlags( 0 ),
+   mIsEnabled( true ),
+   mIsStatic(false)
+{
+}
+
+Px3Body::~Px3Body()
+{
+   _releaseActor();
+}
+
+void Px3Body::_releaseActor()
+{
+   if ( !mActor )
+      return;
+
+   mWorld->releaseWriteLock();
+
+   mActor->userData = NULL;
+
+   mActor->release();
+   mActor = NULL;
+   mBodyFlags = 0;
+
+   if ( mMaterial )
+   {
+      mMaterial->release();
+   }
+
+   mColShape = NULL;
+}
+
+bool Px3Body::init(   PhysicsCollision *shape, 
+                     F32 mass,
+                     U32 bodyFlags,
+                     SceneObject *obj, 
+                     PhysicsWorld *world )
+{
+   AssertFatal( obj, "Px3Body::init - Got a null scene object!" );
+   AssertFatal( world, "Px3Body::init - Got a null world!" );
+   AssertFatal( dynamic_cast<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,desc->pose);
+	   physx::PxFilterData colData;
+	   if(isDebris)
+			colData.word0 = PX3_DEBRIS;
+	   else if(isTrigger)
+      {
+         //We don't want trigger shapes taking part in shape pair intersection tests
+         pShape->setFlag(physx::PxShapeFlag::eSIMULATION_SHAPE, false);
+		   colData.word0 = PX3_TRIGGER;
+      }
+	   else
+		   colData.word0 = PX3_DEFAULT;
+
+      //set the skin width
+      pShape->setContactOffset(0.01f);
+      pShape->setFlag(physx::PxShapeFlag::eSCENE_QUERY_SHAPE,true);
+		pShape->setSimulationFilterData(colData);
+		pShape->setQueryFilterData(colData);
+   }
+
+   //mass & intertia has to be set after creating the shape
+   if ( mass > 0.0f )
+   {
+		physx::PxRigidDynamic *actor = mActor->is<physx::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);
+
+}
+

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

@@ -0,0 +1,121 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _T3D_PHYSICS_PX3BODY_H_
+#define _T3D_PHYSICS_PX3BODY_H_
+
+#ifndef _T3D_PHYSICS_PHYSICSBODY_H_
+#include "T3D/physics/physicsBody.h"
+#endif
+#ifndef _PHYSICS_PHYSICSUSERDATA_H_
+#include "T3D/physics/physicsUserData.h"
+#endif
+#ifndef _REFBASE_H_
+#include "core/util/refBase.h"
+#endif
+#ifndef _MMATRIX_H_
+#include "math/mMatrix.h"
+#endif
+
+class Px3World;
+class Px3Collision;
+struct Px3CollisionDesc;
+
+namespace physx{
+	class PxRigidActor;
+	class PxMaterial;
+	class PxShape;
+}
+
+
+class Px3Body : public PhysicsBody
+{
+protected:
+
+   /// The physics world we are in.
+   Px3World *mWorld;
+
+   /// The physics actor.
+   physx::PxRigidActor *mActor;
+
+   /// The unshared local material used on all the 
+   /// shapes on this actor.
+   physx::PxMaterial *mMaterial;
+
+   /// We hold the collision reference as it contains
+   /// allocated objects that we own and must free.
+   StrongRefPtr<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 

+ 137 - 0
Engine/source/T3D/physics/physx3/px3Cast.h

@@ -0,0 +1,137 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _PHYSX3_CASTS_H_
+#define _PHYSX3_CASTS_H_
+
+#ifndef _MPOINT3_H_
+#include "math/mPoint3.h"
+#endif
+#ifndef _MMATRIX_H_
+#include "math/mMatrix.h"
+#endif
+#ifndef _MBOX_H_
+#include "math/mBox.h"
+#endif
+#ifndef _MQUAT_H_
+#include "math/mQuat.h"
+#endif
+#ifndef _MTRANSFORM_H_
+#include "math/mTransform.h"
+#endif
+
+
+template <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

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

@@ -0,0 +1,212 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "T3D/physics/physx3/px3Collision.h"
+
+#include "math/mPoint3.h"
+#include "math/mMatrix.h"
+#include "T3D/physics/physx3/px3.h"
+#include "T3D/physics/physx3/px3Cast.h"
+#include "T3D/physics/physx3/px3World.h"
+#include "T3D/physics/physx3/px3Stream.h"
+
+
+Px3Collision::Px3Collision()
+{
+}
+
+Px3Collision::~Px3Collision()
+{
+	
+	for ( U32 i=0; i < mColShapes.size(); i++ )
+	{
+		Px3CollisionDesc *desc = mColShapes[i];
+		delete desc->pGeometry;
+		// Delete the descriptor.
+		delete desc;
+	}
+
+	mColShapes.clear();
+}
+
+void Px3Collision::addPlane( const PlaneF &plane )
+{
+	physx::PxVec3 pos = px3Cast<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;
+	desc->pGeometry = new physx::PxConvexMeshGeometry(convexMesh);
+	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 = 0;
+            currentSample->materialIndex1 = 0;
+         }
+         else
+         {
+            currentSample->materialIndex0 = 1;
+            currentSample->materialIndex1 = 1;
+         }
+
+		int flag = ( column + tess ) % 2;
+		if(flag)
+			currentSample->setTessFlag();
+		else
+			currentSample->clearTessFlag();
+
+         currentByte += heightFieldDesc.samples.stride;    
+      }
+   }
+
+	physx::PxHeightField * hf = gPhysics3SDK->createHeightField(heightFieldDesc);
+	physx::PxHeightFieldGeometry *geom = new physx::PxHeightFieldGeometry(hf,physx::PxMeshGeometryFlags(),heightScale,metersPerSample,metersPerSample);
+		
+	physx::PxTransform pose= physx::PxTransform(physx::PxQuat(Float_HalfPi, physx::PxVec3(1, 0, 0 )));
+	physx::PxTransform pose1= physx::PxTransform(physx::PxQuat(Float_Pi, physx::PxVec3(0, 0, 1 )));
+	physx::PxTransform pose2 = pose1 * pose;
+	pose2.p = physx::PxVec3(( blockSize - 1 ) * metersPerSample, 0, 0 );
+	Px3CollisionDesc *desc = new Px3CollisionDesc;
+	desc->pGeometry = geom;
+	desc->pose = pose2;
+
+	mColShapes.push_back(desc);
+	return true;
+}

+ 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 _T3D_PHYSICS_PX3COLLISION_H_
+#define _T3D_PHYSICS_PX3COLLISION_H_
+
+#ifndef _T3D_PHYSICS_PHYSICSCOLLISION_H_
+#include "T3D/physics/physicsCollision.h"
+#endif
+#ifndef _TVECTOR_H_
+#include "core/util/tVector.h"
+#endif
+#ifndef _MMATRIX_H_
+#include "math/mMatrix.h"
+#endif
+//nasty hate doing this!
+#include <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 

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

@@ -0,0 +1,328 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "T3D/physics/physx3/px3Player.h"
+#include "T3D/physics/physicsPlugin.h"
+#include "T3D/physics/physx3/px3World.h"
+#include "T3D/physics/physx3/px3Cast.h"
+#include "T3D/physics/physx3/px3Utils.h"
+#include "collision/collision.h"
+
+
+Px3Player::Px3Player()
+   :  PhysicsPlayer(),
+      mController( NULL ),
+      mWorld( NULL ),
+      mObject( NULL ),
+      mSkinWidth( 0.05f ),
+      mOriginOffset( 0.0f ),
+      mElapsed(0)
+{
+   PHYSICSMGR->getPhysicsResetSignal().notify( this, &Px3Player::_onPhysicsReset );
+}
+
+Px3Player::~Px3Player()
+{
+   _releaseController();
+   PHYSICSMGR->getPhysicsResetSignal().remove( this, &Px3Player::_onPhysicsReset );
+}
+
+void Px3Player::_releaseController()
+{
+   if ( mController )
+   {
+      mController->getActor()->userData = NULL;
+      mWorld->getStaticChangedSignal().remove( this, &Px3Player::_onStaticChanged );
+      mController->release();
+   }
+}
+
+void Px3Player::init( const char *type,
+                     const Point3F &size,
+                     F32 runSurfaceCos,
+                     F32 stepHeight,
+                     SceneObject *obj, 
+                     PhysicsWorld *world )
+{
+   AssertFatal( obj, "Px3Player::init - Got a null scene object!" );
+   AssertFatal( world, "Px3Player::init - Got a null world!" );
+   AssertFatal( dynamic_cast<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()
+{
+   Con::warnf( "Px3Player::getWorldBounds - not implemented" );
+   return Box3F::Invalid;
+}
+

+ 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 // _PXPLAYER_H

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

@@ -0,0 +1,227 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "console/consoleTypes.h"
+#include "T3D/physics/physx3/px3World.h"
+#include "T3D/physics/physx3/px3Plugin.h"
+#include "T3D/physics/physx3/px3Collision.h"
+#include "T3D/physics/physx3/px3Body.h"
+#include "T3D/physics/physx3/px3Player.h"
+
+#include "T3D/physics/physicsShape.h"
+#include "T3D/gameBase/gameProcess.h"
+#include "core/util/tNamedFactory.h"
+
+
+AFTER_MODULE_INIT( Sim )
+{
+   NamedFactory<PhysicsPlugin>::add( "PhysX3", &Px3Plugin::create );
+
+   #if defined(TORQUE_OS_WIN32) || 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(); 
+}
+

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

@@ -0,0 +1,58 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _T3D_PHYSICS_PX3PLUGIN_H_
+#define _T3D_PHYSICS_PX3PLUGIN_H_
+
+#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_
+#include "T3D/physics/physicsPlugin.h"
+#endif
+
+class Px3Plugin : public PhysicsPlugin
+{
+public:
+
+   Px3Plugin();
+   ~Px3Plugin();
+
+   /// Create function for factory.
+   static PhysicsPlugin* create();
+
+   // PhysicsPlugin
+   virtual void destroyPlugin();
+   virtual void reset();
+   virtual PhysicsCollision* createCollision();
+   virtual PhysicsBody* createBody();
+   virtual PhysicsPlayer* createPlayer();
+   virtual bool isSimulationEnabled() const;
+   virtual void enableSimulation( const String &worldName, bool enable );
+   virtual void setTimeScale( const F32 timeScale );
+   virtual const F32 getTimeScale() const;
+   virtual bool createWorld( const String &worldName );
+   virtual void destroyWorld( const String &worldName );
+   virtual PhysicsWorld* getWorld( const String &worldName ) const;
+   virtual PhysicsWorld* getWorld() const;
+   virtual U32 getWorldCount() const;
+
+};
+
+#endif 

+ 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 _T3D_PHYSICS_PX3STREAM_H_
+#define _T3D_PHYSICS_PX3STREAM_H_
+
+#ifndef _PHYSX3_H_
+#include "T3D/physics/physx3/px3.h"
+#endif
+#ifndef _MEMSTREAM_H_
+#include "core/stream/memStream.h"
+#endif
+
+
+class Px3MemOutStream : public physx::PxOutputStream
+{
+public:
+   
+   Px3MemOutStream();
+	virtual ~Px3MemOutStream();
+			
+   void resetPosition();
+
+	virtual physx::PxU32  write(const void *src, physx::PxU32 count);
+	physx::PxU32 getSize() const {return mMemStream.getStreamSize();}
+	physx::PxU8* getData() const {return (physx::PxU8*)mMemStream.getBuffer();}
+
+protected:
+
+   mutable MemStream mMemStream;
+};
+
+class Px3MemInStream: public physx::PxInputData
+{
+	public:
+		Px3MemInStream(physx::PxU8* data, physx::PxU32 length);
+		virtual physx::PxU32 read(void* dest, physx::PxU32 count);
+		physx::PxU32 getLength() const;
+		virtual void seek(physx::PxU32 pos);
+		virtual physx::PxU32 tell() const;
+protected:
+   mutable MemStream mMemStream;
+
+	};
+
+class Px3ConsoleStream : public physx::PxDefaultErrorCallback
+{
+protected:
+
+  virtual void reportError( physx::PxErrorCode code, const char *message, const char* file, int line );
+
+public:
+
+   Px3ConsoleStream();
+   virtual ~Px3ConsoleStream();
+};
+
+#endif

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

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

@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _PHYSX3_UTILS_H_
+#define _PHYSX3_UTILS_H_
+
+namespace physx
+{
+	class PxRigidActor;
+   class PxShape;
+}
+
+extern physx::PxShape* px3GetFirstShape(physx::PxRigidActor *actor);
+
+
+#endif

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

@@ -0,0 +1,567 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "platform/platform.h"
+#include "T3D/physics/physx3/px3World.h"
+
+#include "T3D/physics/physx3/px3.h"
+#include "T3D/physics/physx3/px3Plugin.h"
+#include "T3D/physics/physx3/px3Cast.h"
+#include "T3D/physics/physx3/px3Stream.h"
+#include "T3D/physics/physicsUserData.h"
+
+#include "console/engineAPI.h"
+#include "core/stream/bitStream.h"
+#include "platform/profiler.h"
+#include "sim/netConnection.h"
+#include "console/console.h"
+#include "console/consoleTypes.h"
+#include "core/util/safeDelete.h"
+#include "collision/collision.h"
+#include "T3D/gameBase/gameProcess.h"
+#include "gfx/sim/debugDraw.h"
+#include "gfx/primBuilder.h"
+
+
+physx::PxPhysics* gPhysics3SDK = NULL;
+physx::PxCooking* Px3World::smCooking = NULL;
+physx::PxFoundation* Px3World::smFoundation = NULL;
+physx::PxProfileZoneManager* Px3World::smProfileZoneManager = NULL;
+physx::PxDefaultCpuDispatcher* Px3World::smCpuDispatcher=NULL;
+Px3ConsoleStream* Px3World::smErrorCallback = NULL;
+physx::PxVisualDebuggerConnection* Px3World::smPvdConnection=NULL;
+physx::PxDefaultAllocator Px3World::smMemoryAlloc;
+//Physics timing
+F32 Px3World::smPhysicsStepTime = 1.0f/(F32)TickMs;
+U32 Px3World::smPhysicsMaxIterations = 4;
+
+Px3World::Px3World(): mScene( NULL ),
+   mProcessList( NULL ),
+   mIsSimulating( false ),
+   mErrorReport( false ),
+   mTickCount( 0 ),
+   mIsEnabled( false ),
+   mEditorTimeScale( 1.0f ),
+   mAccumulator( 0 ),
+   mControllerManager( NULL )
+{
+}
+
+Px3World::~Px3World()
+{
+}
+
+physx::PxCooking *Px3World::getCooking()
+{
+	return smCooking;
+}
+
+void Px3World::setTiming(F32 stepTime,U32 maxIterations)
+{
+   smPhysicsStepTime = stepTime;
+   smPhysicsMaxIterations = maxIterations;
+}
+
+bool Px3World::restartSDK( bool destroyOnly, Px3World *clientWorld, Px3World *serverWorld)
+{
+	// If either the client or the server still exist
+	// then we cannot reset the SDK.
+	if ( clientWorld || serverWorld )
+		return false;
+
+	if(smPvdConnection)
+		smPvdConnection->release();
+
+	if(smCooking)
+		smCooking->release();
+
+	if(smCpuDispatcher)
+		smCpuDispatcher->release();
+
+   // Destroy the existing SDK.
+	if ( gPhysics3SDK )
+	{
+		PxCloseExtensions();
+		gPhysics3SDK->release();
+	}
+
+   if(smErrorCallback)
+   {
+      SAFE_DELETE(smErrorCallback);
+   }
+
+	if(smFoundation)
+	{
+		smFoundation->release();
+		SAFE_DELETE(smErrorCallback);
+	}
+
+	// If we're not supposed to restart... return.
+	if ( destroyOnly )
+      return true;
+
+	bool memTrack = false;
+ #ifdef TORQUE_DEBUG
+	memTrack = true;
+ #endif
+
+	smErrorCallback  = new Px3ConsoleStream;
+	smFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, smMemoryAlloc, *smErrorCallback);
+	smProfileZoneManager = &physx::PxProfileZoneManager::createProfileZoneManager(smFoundation);
+	gPhysics3SDK = PxCreatePhysics(PX_PHYSICS_VERSION, *smFoundation, physx::PxTolerancesScale(),memTrack,smProfileZoneManager);
+
+	if ( !gPhysics3SDK )
+	{
+		Con::errorf( "PhysX3 failed to initialize!" );
+		Platform::messageBox(   Con::getVariable( "$appName" ),
+                              avar("PhysX3 could not be started!\r\n"),
+                              MBOk, MIStop );
+		Platform::forceShutdown( -1 );
+      
+		// We shouldn't get here, but this shuts up
+		// source diagnostic tools.
+		return false;
+	}
+
+	if(!PxInitExtensions(*gPhysics3SDK))
+	{
+		Con::errorf( "PhysX3 failed to initialize extensions!" );
+		Platform::messageBox(   Con::getVariable( "$appName" ),
+                              avar("PhysX3 could not be started!\r\n"),
+                              MBOk, MIStop );
+		Platform::forceShutdown( -1 );
+		return false;
+	}
+
+	smCooking = PxCreateCooking(PX_PHYSICS_VERSION, *smFoundation, physx::PxCookingParams(physx::PxTolerancesScale()));
+	if(!smCooking)
+	{
+		Con::errorf( "PhysX3 failed to initialize cooking!" );
+		Platform::messageBox(   Con::getVariable( "$appName" ),
+                              avar("PhysX3 could not be started!\r\n"),
+                              MBOk, MIStop );
+		Platform::forceShutdown( -1 );      
+		return false;
+	}
+
+   //just for testing-must remove, should really be enabled via console like physx 2 plugin
+#ifdef TORQUE_DEBUG
+	physx::PxVisualDebuggerConnectionFlags connectionFlags(physx::PxVisualDebuggerExt::getAllConnectionFlags());
+	smPvdConnection = physx::PxVisualDebuggerExt::createConnection(gPhysics3SDK->getPvdConnectionManager(), 
+				"localhost", 5425, 100, connectionFlags);	
+#endif
+
+	return true;
+}
+
+void Px3World::destroyWorld()
+{
+	getPhysicsResults();
+
+	// Release the tick processing signals.
+	if ( mProcessList )
+	{
+		mProcessList->preTickSignal().remove( this, &Px3World::getPhysicsResults );
+		mProcessList->postTickSignal().remove( this, &Px3World::tickPhysics );
+		mProcessList = NULL;
+	}
+
+   if(mControllerManager)
+   {
+      mControllerManager->release();
+      mControllerManager = NULL;
+   }
+   
+	// Destroy the scene.
+	if ( mScene )
+	{
+		// Release the scene.
+		mScene->release();
+		mScene = NULL;
+	}
+
+}
+
+bool Px3World::initWorld( bool isServer, ProcessList *processList )
+{
+	if ( !gPhysics3SDK )
+	{
+		Con::errorf( "Physx3World::init - PhysXSDK not initialized!" );
+		return false;
+	}
+
+	mIsServer = isServer;
+	
+	physx::PxSceneDesc sceneDesc(gPhysics3SDK->getTolerancesScale());
+
+	sceneDesc.gravity = px3Cast<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_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);
+}

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

@@ -0,0 +1,110 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _PHYSX3_WORLD_H_
+#define _PHYSX3_WORLD_H_
+
+#ifndef _T3D_PHYSICS_PHYSICSWORLD_H_
+#include "T3D/physics/physicsWorld.h"
+#endif
+#ifndef _MMATH_H_
+#include "math/mMath.h"
+#endif
+#ifndef _PHYSX3_H_
+#include "T3D/physics/physx3/px3.h"
+#endif
+#ifndef _TVECTOR_H_
+#include "core/util/tVector.h"
+#endif
+
+class Px3ConsoleStream;
+class Px3ContactReporter;
+class FixedStepper;
+
+enum Px3CollisionGroup
+{
+	PX3_DEFAULT = BIT(0),
+	PX3_PLAYER = BIT(1),
+	PX3_DEBRIS = BIT(2),
+	PX3_TRIGGER = BIT(3),
+};
+
+class Px3World : public PhysicsWorld
+{
+protected:
+
+	physx::PxScene* mScene;
+
+	bool mIsEnabled;
+	bool mIsSimulating;
+	bool mIsServer;
+	U32 mTickCount;
+	ProcessList *mProcessList;
+	F32 mEditorTimeScale;
+	bool mErrorReport;
+	physx::PxControllerManager* mControllerManager;
+	static Px3ConsoleStream *smErrorCallback;
+	static physx::PxDefaultAllocator smMemoryAlloc;
+	static physx::PxFoundation* smFoundation;
+	static physx::PxCooking *smCooking;
+	static physx::PxProfileZoneManager* smProfileZoneManager;
+	static physx::PxDefaultCpuDispatcher* smCpuDispatcher;
+	static physx::PxVisualDebuggerConnection* smPvdConnection;
+   static F32 smPhysicsStepTime;
+   static U32 smPhysicsMaxIterations;
+
+	F32 mAccumulator;
+	bool _simulate(const F32 dt);
+
+public:
+
+	Px3World();
+	virtual ~Px3World();
+
+	virtual bool initWorld( bool isServer, ProcessList *processList );
+	virtual void destroyWorld();
+	virtual void onDebugDraw( const SceneRenderState *state );
+	virtual void reset() {}
+	virtual bool castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse );
+	virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All );
+	virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ); 
+	virtual bool isEnabled() const { return mIsEnabled; }
+	physx::PxScene* getScene(){ return mScene;}
+	void setEnabled( bool enabled );
+	U32 getTick() { return mTickCount; }
+   void tickPhysics( U32 elapsedMs );
+	void getPhysicsResults();
+	void setEditorTimeScale( F32 timeScale ) { mEditorTimeScale = timeScale; }
+	const F32 getEditorTimeScale() const { return mEditorTimeScale; }
+	void releaseWriteLock();
+	bool isServer(){return mIsServer;}
+	physx::PxController* createController( physx::PxControllerDesc &desc );
+	//static
+	static bool restartSDK( bool destroyOnly = false, Px3World *clientWorld = NULL, Px3World *serverWorld = NULL );
+	static void releaseWriteLocks();
+	static physx::PxCooking *getCooking();
+   static void setTiming(F32 stepTime,U32 maxIterations);
+};
+
+
+
+#endif

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

@@ -0,0 +1,106 @@
+<?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" );
+
+   // Includes
+   addIncludePath( $PHYSX3_SDK_PATH . "/Include" );
+
+   // 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();
+
+?>