浏览代码

Added cpp and inl files for most of the physics classes.
Basic API for rigid bodies and constraints should be near done (a lot of it is currently untested and/or not working yet though).

Chris Culy 14 年之前
父节点
当前提交
ac502bafcd

+ 14 - 0
gameplay/gameplay.vcxproj

@@ -43,8 +43,15 @@
     <ClCompile Include="src\Node.cpp" />
     <ClCompile Include="src\Node.cpp" />
     <ClCompile Include="src\Package.cpp" />
     <ClCompile Include="src\Package.cpp" />
     <ClCompile Include="src\ParticleEmitter.cpp" />
     <ClCompile Include="src\ParticleEmitter.cpp" />
+    <ClCompile Include="src\PhysicsConstraint.cpp" />
     <ClCompile Include="src\PhysicsController.cpp" />
     <ClCompile Include="src\PhysicsController.cpp" />
+    <ClCompile Include="src\PhysicsFixedConstraint.cpp" />
+    <ClCompile Include="src\PhysicsGenericConstraint.cpp" />
+    <ClCompile Include="src\PhysicsHingeConstraint.cpp" />
+    <ClCompile Include="src\PhysicsMotionState.cpp" />
     <ClCompile Include="src\PhysicsRigidBody.cpp" />
     <ClCompile Include="src\PhysicsRigidBody.cpp" />
+    <ClCompile Include="src\PhysicsSocketConstraint.cpp" />
+    <ClCompile Include="src\PhysicsSpringConstraint.cpp" />
     <ClCompile Include="src\Plane.cpp" />
     <ClCompile Include="src\Plane.cpp" />
     <ClCompile Include="src\PlatformQNX.cpp" />
     <ClCompile Include="src\PlatformQNX.cpp" />
     <ClCompile Include="src\PlatformWin32.cpp" />
     <ClCompile Include="src\PlatformWin32.cpp" />
@@ -133,6 +140,13 @@
     <ClInclude Include="src\VertexFormat.h" />
     <ClInclude Include="src\VertexFormat.h" />
     <ClInclude Include="src\Viewport.h" />
     <ClInclude Include="src\Viewport.h" />
   </ItemGroup>
   </ItemGroup>
+  <ItemGroup>
+    <None Include="src\PhysicsConstraint.inl" />
+    <None Include="src\PhysicsFixedConstraint.inl" />
+    <None Include="src\PhysicsGenericConstraint.inl" />
+    <None Include="src\PhysicsRigidBody.inl" />
+    <None Include="src\PhysicsSpringConstraint.inl" />
+  </ItemGroup>
   <PropertyGroup Label="Globals">
   <PropertyGroup Label="Globals">
     <ProjectGuid>{1032BA4B-57EB-4348-9E03-29DD63E80E4A}</ProjectGuid>
     <ProjectGuid>{1032BA4B-57EB-4348-9E03-29DD63E80E4A}</ProjectGuid>
     <Keyword>Win32Proj</Keyword>
     <Keyword>Win32Proj</Keyword>

+ 57 - 4
gameplay/gameplay.vcxproj.filters

@@ -168,6 +168,27 @@
     <ClCompile Include="src\PhysicsRigidBody.cpp">
     <ClCompile Include="src\PhysicsRigidBody.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="src\PhysicsConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsHingeConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsFixedConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsGenericConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsSocketConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsSpringConstraint.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
+    <ClCompile Include="src\PhysicsMotionState.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
     <ClInclude Include="src\Animation.h">
@@ -338,9 +359,6 @@
     <ClInclude Include="src\RenderState.h">
     <ClInclude Include="src\RenderState.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="src\Tree.h">
-      <Filter>src</Filter>
-    </ClInclude>
     <ClInclude Include="src\PhysicsController.h">
     <ClInclude Include="src\PhysicsController.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
@@ -350,5 +368,40 @@
     <ClInclude Include="src\PhysicsRigidBody.h">
     <ClInclude Include="src\PhysicsRigidBody.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="src\PhysicsConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsSpringConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsFixedConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsGenericConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsHingeConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+    <ClInclude Include="src\PhysicsSocketConstraint.h">
+      <Filter>src</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="src\PhysicsFixedConstraint.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsGenericConstraint.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsSpringConstraint.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsRigidBody.inl">
+      <Filter>src</Filter>
+    </None>
+    <None Include="src\PhysicsConstraint.inl">
+      <Filter>src</Filter>
+    </None>
   </ItemGroup>
   </ItemGroup>
-</Project>
+</Project>

+ 1 - 1
gameplay/src/Joint.cpp

@@ -73,7 +73,7 @@ const Matrix& Joint::getWorldMatrix() const
     // actual world matrix.
     // actual world matrix.
     if (_parent == NULL && _skin != NULL)
     if (_parent == NULL && _skin != NULL)
     {
     {
-            Matrix::multiply(_skin->_model->getNode()->getWorldMatrix(), Node::getWorldMatrix(), &_jointWorld);
+        Matrix::multiply(_skin->_model->getNode()->getWorldMatrix(), Node::getWorldMatrix(), &_jointWorld);
     }
     }
     else
     else
     {
     {

+ 3 - 3
gameplay/src/MaterialParameter.cpp

@@ -294,7 +294,7 @@ void MaterialParameter::bind(Effect* effect)
 
 
 unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyId) const
 unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyId) const
 {
 {
-    switch (MATERIALPARAMETER_ANIMATE_UNIFORM)
+    switch (ANIMATE_UNIFORM)
     {
     {
         // These types don't support animation.
         // These types don't support animation.
         case NONE:
         case NONE:
@@ -313,7 +313,7 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
 {
 {
     switch (propertyId)
     switch (propertyId)
     {
     {
-        case MATERIALPARAMETER_ANIMATE_UNIFORM:
+        case ANIMATE_UNIFORM:
         {
         {
             switch (_type)
             switch (_type)
             {
             {
@@ -342,7 +342,7 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
 {
 {
     switch (propertyId)
     switch (propertyId)
     {
     {
-        case MATERIALPARAMETER_ANIMATE_UNIFORM:
+        case ANIMATE_UNIFORM:
         {
         {
             switch (_type)
             switch (_type)
             {
             {

+ 1 - 6
gameplay/src/MaterialParameter.h

@@ -37,7 +37,7 @@ class MaterialParameter : public AnimationTarget
 
 
 public:
 public:
 
 
-     /**
+    /**
      * Animates the uniform.
      * Animates the uniform.
      */
      */
     static const int ANIMATE_UNIFORM = 1;
     static const int ANIMATE_UNIFORM = 1;
@@ -47,11 +47,6 @@ public:
      */
      */
     const char* getName() const;
     const char* getName() const;
 
 
-    /**
-     * MaterialParameter's animation target property.
-     */
-    static const int ANIMATE_UNIFORM = 1;
-
     /**
     /**
      * Sets the value of this parameter to a float value.
      * Sets the value of this parameter to a float value.
      */
      */

+ 2 - 13
gameplay/src/Model.cpp

@@ -324,20 +324,9 @@ void Model::validatePartCount()
         _partCount = _mesh->getPartCount();
         _partCount = _mesh->getPartCount();
     }
     }
 }
 }
-
-<<<<<<< HEAD
-void Model::setMaterialNodeBinding(Material *material)
-{
-=======
-Model* Model::create(Mesh* mesh)
-{
-    mesh->addRef();
-    return new Model(mesh);
-}
-
+
 void Model::setMaterialNodeBinding(Material *material)
 void Model::setMaterialNodeBinding(Material *material)
-{
->>>>>>> ccc0fd7... - Working changes for physics development.
+{
     if (_node)
     if (_node)
     {
     {
         material->setNodeBinding(_node);
         material->setNodeBinding(_node);

+ 2 - 11
gameplay/src/Model.h

@@ -150,22 +150,13 @@ private:
      * Destructor. Hidden use release() instead.
      * Destructor. Hidden use release() instead.
      */
      */
     ~Model();
     ~Model();
-
-<<<<<<< HEAD
+
     /**
     /**
      * Sets the MeshSkin for this model.
      * Sets the MeshSkin for this model.
      * 
      * 
      * @param skin The MeshSkin for this model.
      * @param skin The MeshSkin for this model.
      */
      */
-    void setSkin(MeshSkin* skin);
-=======
-    void validatePartCount();
-
-    /**
-     * Sets the specified materia's node binding to this model's node.
-     */
-    void setMaterialNodeBinding(Material *m);
->>>>>>> ccc0fd7... - Working changes for physics development.
+    void setSkin(MeshSkin* skin);
 
 
     /**
     /**
      * Sets the node that is associated with this model.
      * Sets the node that is associated with this model.

+ 0 - 3
gameplay/src/Node.cpp

@@ -400,9 +400,6 @@ const Matrix& Node::getWorldViewProjectionMatrix() const
 }
 }
 
 
 Vector3 Node::getTranslationWorld() const
 Vector3 Node::getTranslationWorld() const
-}
-
-Vector3 Node::getWorldTranslation() const
 {
 {
     Vector3 translation;
     Vector3 translation;
     getWorldMatrix().getTranslation(&translation);
     getWorldMatrix().getTranslation(&translation);

+ 2 - 2
gameplay/src/Node.h

@@ -373,8 +373,8 @@ public:
      * @param mass The mass of the rigid body, in kilograms.
      * @param mass The mass of the rigid body, in kilograms.
      * @param friction The friction of the rigid body (between 0.0 and 1.0, where 0.0 is
      * @param friction The friction of the rigid body (between 0.0 and 1.0, where 0.0 is
      *      minimal friction and 1.0 is maximal friction).
      *      minimal friction and 1.0 is maximal friction).
-     * @param restitution The restitution of the rigid body (this controls the bouncyness of
-     *      the rigid body; between 0.0 and 1.0, where 0.0 is minimal bouncyness and 1.0 is maximal bouncyness).
+     * @param restitution The restitution of the rigid body (this controls the bounciness of
+     *      the rigid body; between 0.0 and 1.0, where 0.0 is minimal bounciness and 1.0 is maximal bounciness).
      * @param linearDamping The percentage of linear velocity lost per second (between 0.0 and 1.0).
      * @param linearDamping The percentage of linear velocity lost per second (between 0.0 and 1.0).
      * @param angularDamping The percentage of angular velocity lost per second (between 0.0 and 1.0).
      * @param angularDamping The percentage of angular velocity lost per second (between 0.0 and 1.0).
      */
      */

+ 38 - 0
gameplay/src/PhysicsConstraint.cpp

@@ -0,0 +1,38 @@
+/*
+ * PhysicsConstraint.cpp
+ */
+
+#include "PhysicsConstraint.h"
+
+#include "Node.h"
+
+namespace gameplay
+{
+
+PhysicsConstraint::PhysicsConstraint() : _constraint(NULL)
+{
+}
+
+PhysicsConstraint::~PhysicsConstraint()
+{
+    if (_constraint)
+    {
+        SAFE_DELETE(_constraint);
+    }
+}
+
+Vector3 PhysicsConstraint::midpoint(Node* a, Node* b)
+{
+    Vector3 tA, tB;
+    a->getWorldMatrix().getTranslation(&tA);
+    b->getWorldMatrix().getTranslation(&tB);
+    
+    Vector3 d(tA, tB);
+    d.scale(0.5f);
+    Vector3 c(tA);
+    c.add(d);
+
+    return c;
+}
+
+}

+ 50 - 4
gameplay/src/PhysicsConstraint.h

@@ -5,28 +5,74 @@
 #ifndef PHYSICSCONSTRAINT_H_
 #ifndef PHYSICSCONSTRAINT_H_
 #define PHYSICSCONSTRAINT_H_
 #define PHYSICSCONSTRAINT_H_
 
 
-#include "PhysicsController.h"
+#include "Base.h"
+#include "Ref.h"
+#include "Vector3.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
+    class Node;
 
 
 /**
 /**
  * Base class for physics constraints.
  * Base class for physics constraints.
  */
  */
-class PhysicsConstraint
+class PhysicsConstraint : public Ref
 {
 {
     friend class PhysicsController;
     friend class PhysicsController;
 
 
 public:
 public:
     /**
     /**
-     * Constructor.
+     * Gets the impulse needed to break the constraint.
+     * 
+     * @return The impulse needed to break the constraint.
+     */
+    inline float getBreakingImpulse() const;
+
+    /**
+     * Sets the impulse needed to break the constraint
+     * (if an impulse greater than or equal to the given
+     * value is applied to the constraint, the constraint
+     * will be broken).
+     * 
+     * @param impulse The impulse needed to break the constraint.
      */
      */
-    PhysicsConstraint() : _constraint(NULL) {}
+    inline void setBreakingImpulse(float impulse);
+
+    /**
+     * Gets whether the constraint is enabled or not.
+     * 
+     * @return Whether the constraint is enabled or not.
+     */
+    inline bool isEnabled() const;
+
+    /**
+     * Sets whether the constraint is enabled or not.
+     * 
+     * @param enabled Whether the constraint is enabled or not.
+     */
+    inline void setEnabled(bool enabled);
 
 
 protected:
 protected:
+    /**
+     * Constructor.
+     */
+    PhysicsConstraint();
+
+    /**
+     * Destructor.
+     */
+    virtual ~PhysicsConstraint();
+
+    /**
+     * Calculates the midpoint between the two nodes.
+     */
+    static Vector3 midpoint(Node* a, Node* b);
+
     btTypedConstraint* _constraint;
     btTypedConstraint* _constraint;
 };
 };
 
 
 }
 }
 
 
+#include "PhysicsConstraint.inl"
+
 #endif
 #endif

+ 30 - 0
gameplay/src/PhysicsConstraint.inl

@@ -0,0 +1,30 @@
+/*
+ * PhysicsConstraint.inl
+ */
+
+#include "PhysicsConstraint.h"
+
+namespace gameplay
+{
+
+inline float PhysicsConstraint::getBreakingImpulse() const
+{
+    return _constraint->getBreakingImpulseThreshold();
+}
+
+inline void PhysicsConstraint::setBreakingImpulse(float impulse)
+{
+    _constraint->setBreakingImpulseThreshold(impulse);
+}
+
+inline bool PhysicsConstraint::isEnabled() const
+{
+    return _constraint->isEnabled();
+}
+
+inline void PhysicsConstraint::setEnabled(bool enabled)
+{
+    _constraint->setEnabled(enabled);
+}
+
+}

+ 61 - 77
gameplay/src/PhysicsController.cpp

@@ -20,7 +20,7 @@ PhysicsController::~PhysicsController()
 {
 {
 }
 }
 
 
-void PhysicsController::setGravity(Vector3 gravity)
+void PhysicsController::setGravity(const Vector3& gravity)
 {
 {
 	_gravity.setX(gravity.x);
 	_gravity.setX(gravity.x);
 	_gravity.setY(gravity.y);
 	_gravity.setY(gravity.y);
@@ -32,13 +32,17 @@ void PhysicsController::setGravity(Vector3 gravity)
 	}
 	}
 }
 }
 
 
-PhysicsFixedConstraint* PhysicsController::createFixedConstraint(PhysicsRigidBody* a, 
-    const Quaternion& rotationOffsetA, const Vector3& translationOffsetA, PhysicsRigidBody* b,
-    const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
+PhysicsFixedConstraint* PhysicsController::createFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
 {
 {
-    PhysicsFixedConstraint* constraint = new PhysicsFixedConstraint(a, rotationOffsetA, 
-        translationOffsetA, b, rotationOffsetB, translationOffsetB);
-    addConstraint(constraint);
+    PhysicsFixedConstraint* constraint = new PhysicsFixedConstraint(a, b);
+    setupConstraint(a, b, constraint);
+    return constraint;
+}
+
+PhysicsGenericConstraint* PhysicsController::createGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    PhysicsGenericConstraint* constraint = new PhysicsGenericConstraint(a, b);
+    setupConstraint(a, b, constraint);
     return constraint;
     return constraint;
 }
 }
 
 
@@ -48,7 +52,7 @@ PhysicsGenericConstraint* PhysicsController::createGenericConstraint(PhysicsRigi
 {
 {
     PhysicsGenericConstraint* constraint = new PhysicsGenericConstraint(a, rotationOffsetA, 
     PhysicsGenericConstraint* constraint = new PhysicsGenericConstraint(a, rotationOffsetA, 
         translationOffsetA, b, rotationOffsetB, translationOffsetB);
         translationOffsetA, b, rotationOffsetB, translationOffsetB);
-    addConstraint(constraint);
+    setupConstraint(a, b, constraint);
     return constraint;
     return constraint;
 }
 }
 
 
@@ -58,7 +62,14 @@ PhysicsHingeConstraint* PhysicsController::createHingeConstraint(PhysicsRigidBod
 {
 {
     PhysicsHingeConstraint* constraint = new PhysicsHingeConstraint(a, rotationOffsetA, 
     PhysicsHingeConstraint* constraint = new PhysicsHingeConstraint(a, rotationOffsetA, 
         translationOffsetA, b, rotationOffsetB, translationOffsetB);
         translationOffsetA, b, rotationOffsetB, translationOffsetB);
-    addConstraint(constraint);
+    setupConstraint(a, b, constraint);
+    return constraint;
+}
+
+PhysicsSocketConstraint* PhysicsController::createSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    PhysicsSocketConstraint* constraint = new PhysicsSocketConstraint(a, b);
+    setupConstraint(a, b, constraint);
     return constraint;
     return constraint;
 }
 }
 
 
@@ -67,7 +78,14 @@ PhysicsSocketConstraint* PhysicsController::createSocketConstraint(PhysicsRigidB
 {
 {
     PhysicsSocketConstraint* constraint = new PhysicsSocketConstraint(a,
     PhysicsSocketConstraint* constraint = new PhysicsSocketConstraint(a,
         translationOffsetA, b, translationOffsetB);
         translationOffsetA, b, translationOffsetB);
-    addConstraint(constraint);
+    setupConstraint(a, b, constraint);
+    return constraint;
+}
+
+PhysicsSpringConstraint* PhysicsController::createSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    PhysicsSpringConstraint* constraint = new PhysicsSpringConstraint(a, b);
+    setupConstraint(a, b, constraint);
     return constraint;
     return constraint;
 }
 }
 
 
@@ -77,7 +95,7 @@ PhysicsSpringConstraint* PhysicsController::createSpringConstraint(PhysicsRigidB
 {
 {
     PhysicsSpringConstraint* constraint = new PhysicsSpringConstraint(a, rotationOffsetA, 
     PhysicsSpringConstraint* constraint = new PhysicsSpringConstraint(a, rotationOffsetA, 
         translationOffsetA, b, rotationOffsetB, translationOffsetB);
         translationOffsetA, b, rotationOffsetB, translationOffsetB);
-    addConstraint(constraint);
+    setupConstraint(a, b, constraint);
     return constraint;
     return constraint;
 }
 }
 
 
@@ -96,57 +114,12 @@ void PhysicsController::initialize()
 
 
 void PhysicsController::finalize()
 void PhysicsController::finalize()
 {
 {
-    // Remove the constraints from the world and delete them.
-	for (int i = _world->getNumConstraints() - 1; i >= 0; i--)
-	{
-		btTypedConstraint* constraint = _world->getConstraint(i);
-		_world->removeConstraint(constraint);
-		delete constraint;
-	}
-
-    // Delete the GamePlay physics constraint objects.
-    for (unsigned int i = 0; i < _constraints.size(); i++)
-    {
-        delete _constraints[i];
-    }
-
-	// Remove the rigid bodies from the world and delete them.
-	for (int i = _world->getNumCollisionObjects() - 1; i >= 0 ; i--)
-	{
-		btCollisionObject* obj = _world->getCollisionObjectArray()[i];
-		btRigidBody* body = btRigidBody::upcast(obj);
-		if (body && body->getMotionState())
-		{
-			delete body->getMotionState();
-		}
-		_world->removeCollisionObject(obj);
-		delete obj;
-	}
-
-	// Delete all of the collision shapes.
-	for (int i = 0; i < _shapes.size(); i++)
-	{
-		btCollisionShape* shape = _shapes[i];
-		_shapes[i] = 0;
-		delete shape;
-	}
-	_shapes.clear();
-
 	// Clean up the world and its various components.
 	// Clean up the world and its various components.
-	delete _world; 
-	_world = NULL;
-
-	delete _solver; 
-	_solver = NULL;
-
-	delete _overlappingPairCache; 
-	_overlappingPairCache = NULL;
-	
-	delete _dispatcher; 
-	_dispatcher = NULL;
-	
-	delete _collisionConfiguration; 
-	_collisionConfiguration = NULL;
+	SAFE_DELETE(_world);
+	SAFE_DELETE(_solver);
+	SAFE_DELETE(_overlappingPairCache);
+	SAFE_DELETE(_dispatcher);
+	SAFE_DELETE(_collisionConfiguration);
 }
 }
 
 
 void PhysicsController::pause()
 void PhysicsController::pause()
@@ -167,20 +140,6 @@ void PhysicsController::update(long elapsedTime)
 	// Note that stepSimulation takes elapsed time in seconds
 	// Note that stepSimulation takes elapsed time in seconds
 	// so we divide by 1000 to convert from milliseconds.
 	// so we divide by 1000 to convert from milliseconds.
 	_world->stepSimulation((float)elapsedTime * 0.001, 10);
 	_world->stepSimulation((float)elapsedTime * 0.001, 10);
-
-    // TODO!!
-    /*
-    // Update the motion states for each rigid body in the scene.
-    for (int i = _world->getNumCollisionObjects() - 1; i >= 0 ; i--)
-	{
-		btCollisionObject* obj = _world->getCollisionObjectArray()[i];
-		btRigidBody* body = btRigidBody::upcast(obj);
-		if (body && body->getMotionState())
-		{
-            ((PhysicsMotionState*)body->getMotionState())->update();
-        }
-    }
-    */
 }
 }
 
 
 btCollisionShape* PhysicsController::getBox(const Vector3& min, const Vector3& max, const btVector3& scale)
 btCollisionShape* PhysicsController::getBox(const Vector3& min, const Vector3& max, const btVector3& scale)
@@ -218,10 +177,35 @@ btCollisionShape* PhysicsController::getHeightfield(void* data, int width, int h
 	return NULL;
 	return NULL;
 }
 }
 
 
-void PhysicsController::addConstraint(PhysicsConstraint* constraint)
+void PhysicsController::setupConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b, PhysicsConstraint* constraint)
 {
 {
+    a->addConstraint(constraint);
+    if (b)
+        b->addConstraint(constraint);
+
     _world->addConstraint(constraint->_constraint);
     _world->addConstraint(constraint->_constraint);
-    _constraints.push_back(constraint);
+}
+
+void PhysicsController::removeConstraint(PhysicsConstraint* constraint)
+{
+    // Find the constraint and remove it from the physics world.
+	for (int i = _world->getNumConstraints() - 1; i >= 0; i--)
+	{
+		btTypedConstraint* currentConstraint = _world->getConstraint(i);
+        if (constraint->_constraint == currentConstraint)
+		    _world->removeConstraint(currentConstraint);
+	}
+}
+
+void PhysicsController::removeRigidBody(PhysicsRigidBody* rigidBody)
+{
+    // Find the rigid body and remove it from the world.
+	for (int i = _world->getNumCollisionObjects() - 1; i >= 0 ; i--)
+	{
+		btCollisionObject* obj = _world->getCollisionObjectArray()[i];
+        if (rigidBody->_body == obj)
+		    _world->removeCollisionObject(obj);
+	}
 }
 }
 
 
 }
 }

+ 102 - 14
gameplay/src/PhysicsController.h

@@ -25,28 +25,46 @@ class PhysicsController
 	friend class PhysicsRigidBody;
 	friend class PhysicsRigidBody;
 
 
 public:
 public:
-    
-	/**
-	 * Destructor
-	 */
-	virtual ~PhysicsController();
-
 	/**
 	/**
 	 * Sets the gravity vector for the simulated physics world.
 	 * Sets the gravity vector for the simulated physics world.
 	 * 
 	 * 
 	 * @param gravity The gravity vector.
 	 * @param gravity The gravity vector.
 	 */
 	 */
-	void setGravity(Vector3 gravity);
+	void setGravity(const Vector3& gravity);
 
 
     /**
     /**
      * Creates a fixed constraint.
      * Creates a fixed constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
      */
      */
-    PhysicsFixedConstraint* createFixedConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
-        const Vector3& translationOffsetA, PhysicsRigidBody* b = NULL, 
-        const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
+    PhysicsFixedConstraint* createFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
+
+    /**
+     * Creates a generic constraint so that the rigid body (or bodies) is
+     * (are) constrained to its (their) current world position(s).
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
+     */
+    PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
 
 
     /**
     /**
      * Creates a generic constraint.
      * Creates a generic constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param rotationOffsetA The rotation offset for the first rigid body 
+     *      (in its local space) with respect to the constraint joint.
+     * @param translationOffsetA The translation offset for the first rigid body
+     *      (in its local space) with respect to the constraint joint.
+     * @param b The second rigid body to constrain (optional).
+     * @param rotationOffsetB The rotation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
+     * @param translationOffsetB The translation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
     PhysicsGenericConstraint* createGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
         const Vector3& translationOffsetA, PhysicsRigidBody* b = NULL, 
         const Vector3& translationOffsetA, PhysicsRigidBody* b = NULL, 
@@ -54,30 +72,88 @@ public:
 
 
     /**
     /**
      * Creates a hinge constraint.
      * Creates a hinge constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param rotationOffsetA The rotation offset for the first rigid body 
+     *      (in its local space) with respect to the constraint joint.
+     * @param translationOffsetA The translation offset for the first rigid body
+     *      (in its local space) with respect to the constraint joint.
+     * @param b The second rigid body to constrain (optional).
+     * @param rotationOffsetB The rotation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
+     * @param translationOffsetB The translation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsHingeConstraint* createHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
     PhysicsHingeConstraint* createHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
         const Vector3& translationOffsetA, PhysicsRigidBody* b = NULL, 
         const Vector3& translationOffsetA, PhysicsRigidBody* b = NULL, 
         const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
         const Quaternion& rotationOffsetB = Quaternion(), const Vector3& translationOffsetB = Vector3());
 
 
+    /**
+     * Creates a socket constraint so that the rigid body (or bodies) is
+     * (are) constrained using its (their) current world position(s) for
+     * the translation offset(s) to the constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
+     */
+    PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b = NULL);
+
     /**
     /**
      * Creates a socket constraint.
      * Creates a socket constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param translationOffsetA The translation offset for the first rigid body
+     *      (in its local space) with respect to the constraint joint.
+     * @param b The second rigid body to constrain (optional).
+     * @param translationOffsetB The translation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA,
     PhysicsSocketConstraint* createSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA,
         PhysicsRigidBody* b = NULL, const Vector3& translationOffsetB = Vector3());
         PhysicsRigidBody* b = NULL, const Vector3& translationOffsetB = Vector3());
 
 
+    /**
+     * Creates a spring constraint so that the rigid body (or bodies) is
+     * (are) constrained using its (their) current world position(s) for
+     * the translation offset(s) to the constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
+     */
+    PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
+
     /**
     /**
      * Creates a spring constraint.
      * Creates a spring constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param rotationOffsetA The rotation offset for the first rigid body 
+     *      (in its local space) with respect to the constraint joint.
+     * @param translationOffsetA The translation offset for the first rigid body
+     *      (in its local space) with respect to the constraint joint.
+     * @param b The second rigid body to constrain (optional).
+     * @param rotationOffsetB The rotation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
+     * @param translationOffsetB The translation offset for the second rigid body
+     *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
     PhysicsSpringConstraint* createSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, 
         const Vector3& translationOffsetA, PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
         const Vector3& translationOffsetA, PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
 
 
 private:
 private:
-	
 	/**
 	/**
 	 * Constructor.
 	 * Constructor.
 	 */
 	 */
 	PhysicsController();
 	PhysicsController();
 
 
+    /**
+	 * Destructor.
+	 */
+	~PhysicsController();
+
 	/**
 	/**
 	 * Controller initialize.
 	 * Controller initialize.
 	 */
 	 */
@@ -103,12 +179,26 @@ private:
 	 */
 	 */
     void update(long elapsedTime);
     void update(long elapsedTime);
 
 
+    // Creates a box collision shape to be used in the creation of a rigid body.
 	btCollisionShape* getBox(const Vector3& min, const Vector3& max, const btVector3& scale);
 	btCollisionShape* getBox(const Vector3& min, const Vector3& max, const btVector3& scale);
+
+    // Creates a sphere collision shape to be used in the creation of a rigid body.
 	btCollisionShape* getSphere(float radius, const btVector3& scale);
 	btCollisionShape* getSphere(float radius, const btVector3& scale);
+
+    // Creates a triangle mesh collision shape to be used in the creation of a rigid body.
 	btCollisionShape* getTriangleMesh(float* vertexData, int vertexPositionStride, unsigned char* indexData, Mesh::IndexFormat indexFormat);
 	btCollisionShape* getTriangleMesh(float* vertexData, int vertexPositionStride, unsigned char* indexData, Mesh::IndexFormat indexFormat);
+
+    // Creates a heightfield collision shape to be used in the creation of a rigid body.
 	btCollisionShape* getHeightfield(void* data, int width, int height);
 	btCollisionShape* getHeightfield(void* data, int width, int height);
+    
+    // Sets up the given constraint for the given two rigid bodies.
+    void setupConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b, PhysicsConstraint* constraint);
+    
+    // Removes the given constraint from the simulated physics world.
+    void removeConstraint(PhysicsConstraint* constraint);
 
 
-    void addConstraint(PhysicsConstraint* constraint);
+    // Removes the given rigid body from the simulated physics world.
+    void removeRigidBody(PhysicsRigidBody* rigidBody);
 
 
 	btVector3 _gravity;
 	btVector3 _gravity;
 	btDefaultCollisionConfiguration* _collisionConfiguration;
 	btDefaultCollisionConfiguration* _collisionConfiguration;
@@ -117,8 +207,6 @@ private:
 	btSequentialImpulseConstraintSolver* _solver;
 	btSequentialImpulseConstraintSolver* _solver;
 	btDynamicsWorld* _world;
 	btDynamicsWorld* _world;
 	btAlignedObjectArray<btCollisionShape*> _shapes;
 	btAlignedObjectArray<btCollisionShape*> _shapes;
-
-    std::vector<PhysicsConstraint*> _constraints;
 };
 };
 
 
 }
 }

+ 24 - 0
gameplay/src/PhysicsFixedConstraint.cpp

@@ -0,0 +1,24 @@
+/**
+ * PhysicsFixedConstraint.cpp
+ */
+
+#include "PhysicsFixedConstraint.h"
+
+namespace gameplay
+{
+
+PhysicsFixedConstraint::PhysicsFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+    : PhysicsGenericConstraint(a, b)
+{
+    PhysicsGenericConstraint::setAngularLowerLimit(Vector3(0.0f, 0.0f, 0.0f));
+    PhysicsGenericConstraint::setAngularUpperLimit(Vector3(0.0f, 0.0f, 0.0f));
+    PhysicsGenericConstraint::setLinearLowerLimit(Vector3(0.0f, 0.0f, 0.0f));
+    PhysicsGenericConstraint::setLinearUpperLimit(Vector3(0.0f, 0.0f, 0.0f));
+}
+
+PhysicsFixedConstraint::~PhysicsFixedConstraint()
+{
+    // DUMMY FUNCTION
+}
+
+}

+ 12 - 174
gameplay/src/PhysicsFixedConstraint.h

@@ -6,50 +6,13 @@
 #define PHYSICSFIXEDCONSTRAINT_H_
 #define PHYSICSFIXEDCONSTRAINT_H_
 
 
 #include "PhysicsGenericConstraint.h"
 #include "PhysicsGenericConstraint.h"
-#include "Vector3.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
 
 
-// TODO!
-/*
-// Taken from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html.
-bool matrixToEulerXYZ(const Matrix& m, Vector3& xyz)
-{
-    if (m.m[8] < 1.0f)
-    {
-            if (m.m[8] > -1.0f)
-            {
-                    xyz.x = atan2f(-m.m[5],m.m[2]);
-                    xyz.y = asinf(m.m[8]);
-                    xyz.z = atan2f(-m.m[4],m.m[0]);
-                    return true;
-            }
-            else
-            {
-                    // WARNING.  Not unique.  XA - ZA = -atan2(r10,r11)
-                    xyz.x = -atan2f(m.m[12],m.m[1]);
-                    xyz.y = -MATH_PIOVER2;
-                    xyz.z = 0.0;
-                    return false;
-            }
-    }
-    else
-    {
-            // WARNING.  Not unique.  XAngle + ZAngle = atan2(r10,r11)
-            xyz.x = atan2f(m.m[12],m.m[1]);
-            xyz.y = MATH_PIOVER2;
-            xyz.z = 0.0;
-    }
-    return false;
-}
-*/
-
 /**
 /**
  * Represents a constraint where two rigid bodies 
  * Represents a constraint where two rigid bodies 
- * (or one rigid body and the world) are bound together
- * with a given orientation and translation offset and all
- * movement is restricted.
+ * (or one rigid body and the world) are bound together.
  *
  *
  * (This is similar in concept to parenting one node to another,
  * (This is similar in concept to parenting one node to another,
  * but can be used in specific situations for a more appropriate effect
  * but can be used in specific situations for a more appropriate effect
@@ -59,130 +22,16 @@ class PhysicsFixedConstraint : public PhysicsGenericConstraint
 {
 {
     friend class PhysicsController;
     friend class PhysicsController;
 
 
-public:
+protected:
     /**
     /**
-     * Sets the angular limits along the constraint's local
-     * X, Y, and Z axes using the values in the given vector.
-     * 
-     * @param limits The angular limits along the local X, Y, and Z axes.
+     * @see PhysicsGenericConstraint
      */
      */
-    void setAngularLimit(const Vector3& limits)
-    {
-        setAngularLowerLimit(limits);
-        setAngularUpperLimit(limits);
-    }
+    PhysicsFixedConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
 
 
     /**
     /**
-     * Sets the linear limits along the constraint's local
-     * X, Y, and Z axes using the values in the given vector.
-     * 
-     * @param limits The linear limits along the local X, Y, and Z axes.
+     * Destructor.
      */
      */
-    void setLinearLimit(const Vector3& limits)
-    {
-        setLinearLowerLimit(limits);
-        setLinearUpperLimit(limits);
-    }
-
-protected:
-
-    void initialize()
-    {
-        /*
-        const BoundingBox& box = joint10->getModel()->getMesh()->getBoundingBox();
-        float a = 0.5f * (box.max.x - box.min.x);
-    
-        const BoundingSphere& sphere = _basketball->getModel()->getMesh()->getBoundingSphere();
-        float b = -sphere.radius;
-    
-        Quaternion r1, r2;
-        joint10->getWorldMatrix().getRotation(&r1);
-        _basketball->getWorldMatrix().getRotation(&r2);
-
-        Vector3 bMin, bMax;
-        joint10->getWorldMatrix().transformPoint(box.min, &bMin);
-        joint10->getWorldMatrix().transformPoint(box.max, &bMax);
-        Vector3 c1(bMin, bMax);
-        c1.scale(0.5f);
-        c1.add(bMin);
-
-        Vector3 c2;
-        _basketball->getWorldMatrix().transformPoint(sphere.center, &c2);
-
-        Vector3 d(c1, c2);
-        d.scale(0.5f);
-
-        Quaternion q;
-        joint10->getWorldMatrix().getRotation(&q);
-        Vector3 v;
-        joint10->getWorldMatrix().getTranslation(&v);
-        Transform t(Vector3::one(), q, v);
-        Matrix w1(t.getMatrix());
-        Matrix w1i; w1.invert(&w1i);
-        Vector3 t1(d);
-        w1i.transformNormal(&t1);
-        t1.x *= 1.0f / joint10->getScaleX();
-        t1.y *= 1.0f / joint10->getScaleY();
-        t1.z *= 1.0f / joint10->getScaleZ();
-
-        _basketball->getWorldMatrix().getRotation(&q);
-        _basketball->getWorldMatrix().getTranslation(&v);
-        t.set(Vector3::one(), q, v);
-        Matrix w2(t.getMatrix());
-        Matrix w2i; w2.invert(&w2i);
-        Vector3 t2(d);
-        t2.negate();
-        w2i.transformNormal(&t2);
-        t2.x *= 1.0f / _basketball->getScaleX();
-        t2.y *= 1.0f / _basketball->getScaleY();
-        t2.z *= 1.0f / _basketball->getScaleZ();
-
-        Quaternion::createFromAxisAngle(Vector3(0.0f, 0.0f, 1.0f), MATH_DEG_TO_RAD(90.0f), &q);
-    
-        // TODO!
-        // Construct the correct rotation limits.
-        r1.inverse();
-        r2.inverse();
-        Matrix mm1;
-        Matrix::createRotation(r1, &mm1);
-        Matrix::multiply(w1, mm1, &mm1);
-        mm1.invert();
-        Matrix mm2;
-        Matrix::createRotation(r2, &mm2);
-        Matrix::multiply(w2, mm2, &mm2);
-        Matrix mm;
-        Matrix::multiply(mm1, mm2, &mm);
-        matrixToEulerXYZ(mm, euler);
-
-        PhysicsGenericConstraint* constraint = Game::getInstance()->getPhysicsController()->createGenericConstraint(joint10->getPhysicsRigidBody(),
-            Quaternion::identity(), t1, _basketball->getPhysicsRigidBody(), Quaternion::identity(), t2);
-
-        Vector3 rz90(0.0f, 0.0f, MATH_DEG_TO_RAD(90.0f));
-        //constraint->setAngularLowerLimit(Vector3(0.0f, 0.0f, 0.0f));
-        //constraint->setAngularUpperLimit(Vector3(0.0f, 0.0f, 0.0f));
-        //constraint->setAngularLowerLimit(rz90);
-        //constraint->setAngularUpperLimit(rz90);
-        constraint->setAngularLowerLimit(euler);
-        constraint->setAngularUpperLimit(euler);
-    
-        d.scale(2.0f);
-        d.x *= 1.0f / _basketball->getScaleX();
-        d.y *= 1.0f / _basketball->getScaleY();
-        d.z *= 1.0f / _basketball->getScaleZ();;
-        w1i.transformNormal(&d);
-        constraint->setLinearLowerLimit(d);
-        constraint->setLinearUpperLimit(d);
-        //*/
-    }
-
-    /**
-     * @see PhysicsGenericConstraint
-     */
-    PhysicsFixedConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
-        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
-        : PhysicsGenericConstraint(a, rotationOffsetA, translationOffsetA, b, rotationOffsetB, translationOffsetB)
-    {
-    }
+    ~PhysicsFixedConstraint();
 
 
     // Note: We make these functions protected to prevent usage
     // Note: We make these functions protected to prevent usage
     // (these are public in the base class, PhysicsGenericConstraint).
     // (these are public in the base class, PhysicsGenericConstraint).
@@ -190,37 +39,26 @@ protected:
     /**
     /**
      * Protected to prevent usage.
      * Protected to prevent usage.
      */
      */
-    inline void setAngularLowerLimit(const Vector3& limit)
-    {
-        PhysicsGenericConstraint::setAngularLowerLimit(limit);
-    }
+    inline void setAngularLowerLimit(const Vector3& limit);
     
     
     /**
     /**
      * Protected to prevent usage.
      * Protected to prevent usage.
      */
      */
-    inline void setAngularUpperLimit(const Vector3& limit)
-    {
-        PhysicsGenericConstraint::setAngularUpperLimit(limit);
-    }
+    inline void setAngularUpperLimit(const Vector3& limit);
     
     
     /**
     /**
      * Protected to prevent usage.
      * Protected to prevent usage.
      */
      */
-    inline void setLinearLowerLimit(const Vector3& limit)
-    {
-        PhysicsGenericConstraint::setLinearLowerLimit(limit);
-    }
+    inline void setLinearLowerLimit(const Vector3& limit);
     
     
     /**
     /**
      * Protected to prevent usage.
      * Protected to prevent usage.
      */
      */
-    inline void setLinearUpperLimit(const Vector3& limit)
-    {
-        PhysicsGenericConstraint::setLinearUpperLimit(limit);
-    }
-
+    inline void setLinearUpperLimit(const Vector3& limit);
 };
 };
 
 
 }
 }
 
 
+#include "PhysicsFixedConstraint.inl"
+
 #endif
 #endif

+ 30 - 0
gameplay/src/PhysicsFixedConstraint.inl

@@ -0,0 +1,30 @@
+/**
+ * PhysicsFixedConstraint.inl
+ */
+
+#include "PhysicsFixedConstraint.h"
+
+namespace gameplay
+{
+
+inline void PhysicsFixedConstraint::setAngularLowerLimit(const Vector3& limit)
+{
+    PhysicsGenericConstraint::setAngularLowerLimit(limit);
+}
+
+inline void PhysicsFixedConstraint::setAngularUpperLimit(const Vector3& limit)
+{
+    PhysicsGenericConstraint::setAngularUpperLimit(limit);
+}
+
+inline void PhysicsFixedConstraint::setLinearLowerLimit(const Vector3& limit)
+{
+    PhysicsGenericConstraint::setLinearLowerLimit(limit);
+}
+
+inline void PhysicsFixedConstraint::setLinearUpperLimit(const Vector3& limit)
+{
+    PhysicsGenericConstraint::setLinearUpperLimit(limit);
+}
+
+}

+ 80 - 0
gameplay/src/PhysicsGenericConstraint.cpp

@@ -0,0 +1,80 @@
+/**
+ * PhysicsGenericConstraint.cpp
+ */
+
+#include "PhysicsGenericConstraint.h"
+
+#include "Node.h"
+#include "PhysicsRigidBody.h"
+
+namespace gameplay
+{
+
+PhysicsGenericConstraint::PhysicsGenericConstraint()
+{
+    // DUMMY FUNCTION
+}
+
+PhysicsGenericConstraint::PhysicsGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    if (b)
+    {
+        // Create a translation matrix that translates to the midpoint
+        // between the two physics rigid bodies.
+        Matrix m;
+        Matrix::createTranslation(midpoint(a->_node, b->_node), &m);
+
+        // Calculate the translation and rotation offsets to the rigid bodies
+        // by transforming the translation matrix above into each rigid body's
+        // local space (multiply by the inverse world matrix and extract components).
+        Matrix mAi;
+        a->_node->getWorldMatrix().invert(&mAi);
+        mAi.multiply(m);
+
+        Matrix mBi;
+        b->_node->getWorldMatrix().invert(&mBi);
+        mBi.multiply(m);
+
+        Quaternion rA, rB;
+        mAi.getRotation(&rA);
+        mBi.getRotation(&rB);
+    
+        Vector3 tA, tB;
+        mAi.getTranslation(&tA);
+        mBi.getTranslation(&tB);
+
+        btTransform frameInA(btQuaternion(rA.x, rA.y, rA.z, rA.w), btVector3(tA.x, tA.y, tA.z));
+        btTransform frameInB(btQuaternion(rB.x, rB.y, rB.z, rB.w), btVector3(tB.x, tB.y, tB.z));
+        _constraint = new btGeneric6DofConstraint(*a->_body, *b->_body, frameInA, frameInB, true);
+    }
+    else
+    {
+        _constraint = new btGeneric6DofConstraint(*a->_body, btTransform::getIdentity(), true);
+    }
+}
+
+PhysicsGenericConstraint::PhysicsGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
+    PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
+{
+    if (b)
+    {
+        btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
+            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
+        btTransform frameInB(btQuaternion(rotationOffsetB.x, rotationOffsetB.y, rotationOffsetB.z, rotationOffsetB.w), 
+            btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
+        _constraint = new btGeneric6DofConstraint(*a->_body, *b->_body, frameInA, frameInB, true);
+    }
+    else
+    {
+        btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
+            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
+        _constraint = new btGeneric6DofConstraint(*a->_body, frameInA, true);
+    }
+}
+
+PhysicsGenericConstraint::~PhysicsGenericConstraint()
+{
+    // DUMMY FUNCTION
+}
+
+}

+ 84 - 43
gameplay/src/PhysicsGenericConstraint.h

@@ -6,12 +6,12 @@
 #define PHYSICSGENERICCONSTRAINT_H_
 #define PHYSICSGENERICCONSTRAINT_H_
 
 
 #include "PhysicsConstraint.h"
 #include "PhysicsConstraint.h"
-#include "PhysicsRigidBody.h"
 #include "Quaternion.h"
 #include "Quaternion.h"
 #include "Vector3.h"
 #include "Vector3.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
+    class PhysicsRigidBody;
 
 
 /**
 /**
  * Represents a completely generic constraint between two
  * Represents a completely generic constraint between two
@@ -24,16 +24,32 @@ class PhysicsGenericConstraint : public PhysicsConstraint
 
 
 public:
 public:
     /**
     /**
-     * Destructor.
+     * Gets the rotation offset for the first rigid body in the constraint.
+     * 
+     * @return The rotation offset.
+     */
+    inline Quaternion getRotationOffsetA();
+
+    /**
+     * Gets the rotation offset for the second rigid body in the constraint.
+     * 
+     * @return The rotation offset.
      */
      */
-    ~PhysicsGenericConstraint()
-    {
-        if (_constraint)
-        {
-            delete _constraint;
-            _constraint = NULL;
-        }
-    }
+    inline Quaternion getRotationOffsetB();
+
+    /**
+     * Gets the translation offset for the first rigid body in the constraint.
+     * 
+     * @return The translation offset.
+     */
+    inline Vector3 getTranslationOffsetA();
+
+    /**
+     * Gets the translation offset for the second rigid body in the constraint.
+     * 
+     * @return The translation offset.
+     */
+    inline Vector3 getTranslationOffsetB();
 
 
     /**
     /**
      * Sets the lower angular limits along the constraint's local
      * Sets the lower angular limits along the constraint's local
@@ -41,10 +57,7 @@ public:
      * 
      * 
      * @param limits The lower angular limits along the local X, Y, and Z axes.
      * @param limits The lower angular limits along the local X, Y, and Z axes.
      */
      */
-    inline void setAngularLowerLimit(const Vector3& limits)
-    {
-        ((btGeneric6DofConstraint*)_constraint)->setAngularLowerLimit(btVector3(limits.x, limits.y, limits.z));
-    }
+    inline void setAngularLowerLimit(const Vector3& limits);
 
 
     /**
     /**
      * Sets the upper angular limits along the constraint's local
      * Sets the upper angular limits along the constraint's local
@@ -52,10 +65,7 @@ public:
      * 
      * 
      * @param limits The upper angular limits along the local X, Y, and Z axes.
      * @param limits The upper angular limits along the local X, Y, and Z axes.
      */
      */
-    inline void setAngularUpperLimit(const Vector3& limits)
-    {
-        ((btGeneric6DofConstraint*)_constraint)->setAngularUpperLimit(btVector3(limits.x, limits.y, limits.z));
-    }
+    inline void setAngularUpperLimit(const Vector3& limits);
     
     
     /**
     /**
      * Sets the lower linear limits along the constraint's local
      * Sets the lower linear limits along the constraint's local
@@ -63,10 +73,7 @@ public:
      * 
      * 
      * @param limits The lower linear limits along the local X, Y, and Z axes.
      * @param limits The lower linear limits along the local X, Y, and Z axes.
      */
      */
-    inline void setLinearLowerLimit(const Vector3& limits)
-    {
-        ((btGeneric6DofConstraint*)_constraint)->setLinearLowerLimit(btVector3(limits.x, limits.y, limits.z));
-    }
+    inline void setLinearLowerLimit(const Vector3& limits);
     
     
     /**
     /**
      * Sets the upper linear limits along the constraint's local
      * Sets the upper linear limits along the constraint's local
@@ -74,12 +81,55 @@ public:
      * 
      * 
      * @param limits The upper linear limits along the local X, Y, and Z axes.
      * @param limits The upper linear limits along the local X, Y, and Z axes.
      */
      */
-    inline void setLinearUpperLimit(const Vector3& limits)
-    {
-        ((btGeneric6DofConstraint*)_constraint)->setLinearUpperLimit(btVector3(limits.x, limits.y, limits.z));
-    }
+    inline void setLinearUpperLimit(const Vector3& limits);
+
+    /**
+     * Sets the rotation offset for the first rigid body in the constraint.
+     * 
+     * @param rotationOffset The rotation offset.
+     */
+    inline void setRotationOffsetA(const Quaternion& rotationOffset);
+
+    /**
+     * Sets the rotation offset for the second rigid body in the constraint.
+     * 
+     * @param rotationOffset The rotation offset.
+     */
+    inline void setRotationOffsetB(const Quaternion& rotationOffset);
+
+    /**
+     * Sets the translation offset for the first rigid body in the constraint.
+     * 
+     * @param translationOffset The translation offset.
+     */
+    inline void setTranslationOffsetA(const Vector3& translationOffset);
+
+    /**
+     * Sets the translation offset for the second rigid body in the constraint.
+     * 
+     * @param translationOffset The translation offset.
+     */
+    inline void setTranslationOffsetB(const Vector3& translationOffset);
 
 
 protected:
 protected:
+    /**
+     * Constructor.
+     *
+     * Note: This should only used by subclasses that do not want
+     * the _constraint member variable to be initialized.
+     */
+    PhysicsGenericConstraint();
+
+    /**
+     * Creates a generic constraint so that the rigid body (or bodies) is
+     * (are) constrained to its (their) current world position(s).
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
+     */
+    PhysicsGenericConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
+
     /**
     /**
      * Creates a generic constraint.
      * Creates a generic constraint.
      * 
      * 
@@ -96,25 +146,16 @@ protected:
      *      (in its local space) with respect to the constraint joint (optional).
      *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
     PhysicsGenericConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
-        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
-    {
-        if (b)
-        {
-            btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
-                btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
-            btTransform frameInB(btQuaternion(rotationOffsetB.x, rotationOffsetB.y, rotationOffsetB.z, rotationOffsetB.w), 
-                btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
-            _constraint = new btGeneric6DofConstraint(*a->_body, *b->_body, frameInA, frameInB, true);
-        }
-        else
-        {
-            btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
-                btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
-            _constraint = new btGeneric6DofConstraint(*a->_body, frameInA, true);
-        }
-    }
+        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
+
+    /**
+     * Destructor.
+     */
+    virtual ~PhysicsGenericConstraint();
 };
 };
 
 
 }
 }
 
 
+#include "PhysicsGenericConstraint.inl"
+
 #endif
 #endif

+ 74 - 0
gameplay/src/PhysicsGenericConstraint.inl

@@ -0,0 +1,74 @@
+/**
+ * PhysicsGenericConstraint.inl
+ */
+
+#include "PhysicsGenericConstraint.h"
+
+namespace gameplay
+{
+
+inline Quaternion PhysicsGenericConstraint::getRotationOffsetA()
+{
+    btQuaternion ro = static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetA().getRotation();
+    return Quaternion(ro.x(), ro.y(), ro.z(), ro.w());
+}
+
+inline Quaternion PhysicsGenericConstraint::getRotationOffsetB()
+{
+    btQuaternion ro = static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetB().getRotation();
+    return Quaternion(ro.x(), ro.y(), ro.z(), ro.w());
+}
+
+inline Vector3 PhysicsGenericConstraint::getTranslationOffsetA()
+{
+    btVector3 to = static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetA().getOrigin();
+    return Vector3(to.x(), to.y(), to.z());
+}
+
+inline Vector3 PhysicsGenericConstraint::getTranslationOffsetB()
+{
+    btVector3 to = static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetB().getOrigin();
+    return Vector3(to.x(), to.y(), to.z());
+}
+
+inline void PhysicsGenericConstraint::setAngularLowerLimit(const Vector3& limits)
+{
+    ((btGeneric6DofConstraint*)_constraint)->setAngularLowerLimit(btVector3(limits.x, limits.y, limits.z));
+}
+
+inline void PhysicsGenericConstraint::setAngularUpperLimit(const Vector3& limits)
+{
+    ((btGeneric6DofConstraint*)_constraint)->setAngularUpperLimit(btVector3(limits.x, limits.y, limits.z));
+}
+
+inline void PhysicsGenericConstraint::setLinearLowerLimit(const Vector3& limits)
+{
+    ((btGeneric6DofConstraint*)_constraint)->setLinearLowerLimit(btVector3(limits.x, limits.y, limits.z));
+}
+    
+inline void PhysicsGenericConstraint::setLinearUpperLimit(const Vector3& limits)
+{
+    ((btGeneric6DofConstraint*)_constraint)->setLinearUpperLimit(btVector3(limits.x, limits.y, limits.z));
+}
+
+inline void PhysicsGenericConstraint::setRotationOffsetA(const Quaternion& rotationOffset)
+{
+    static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetA().setRotation(btQuaternion(rotationOffset.x, rotationOffset.y, rotationOffset.z, rotationOffset.w));
+}
+
+inline void PhysicsGenericConstraint::setRotationOffsetB(const Quaternion& rotationOffset)
+{
+    static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetB().setRotation(btQuaternion(rotationOffset.x, rotationOffset.y, rotationOffset.z, rotationOffset.w));
+}
+
+inline void PhysicsGenericConstraint::setTranslationOffsetA(const Vector3& translationOffset)
+{
+    static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetA().setOrigin(btVector3(translationOffset.x, translationOffset.y, translationOffset.z));
+}
+
+inline void PhysicsGenericConstraint::setTranslationOffsetB(const Vector3& translationOffset)
+{
+    static_cast<btGeneric6DofConstraint*>(_constraint)->getFrameOffsetB().setOrigin(btVector3(translationOffset.x, translationOffset.y, translationOffset.z));
+}
+
+}

+ 40 - 0
gameplay/src/PhysicsHingeConstraint.cpp

@@ -0,0 +1,40 @@
+/*
+ * PhysicsHingeConstraint.cpp
+ */
+
+#include "PhysicsHingeConstraint.h"
+
+namespace gameplay
+{
+
+void PhysicsHingeConstraint::setLimits(float minAngle, float maxAngle, float softness, float biasFactor, float relaxationFactor)
+{
+    ((btHingeConstraint*)_constraint)->setLimit(minAngle, maxAngle, softness, biasFactor, relaxationFactor);
+}
+
+PhysicsHingeConstraint::PhysicsHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
+    PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
+{
+    if (b)
+    {
+        btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
+            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
+        btTransform frameInB(btQuaternion(rotationOffsetB.x, rotationOffsetB.y, rotationOffsetB.z, rotationOffsetB.w), 
+            btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
+        _constraint = new btHingeConstraint(*a->_body, *b->_body, frameInA, frameInB);
+    }
+    else
+    {
+        btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
+            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
+        _constraint = new btHingeConstraint(*a->_body, frameInA);
+    }
+}
+
+    
+PhysicsHingeConstraint::~PhysicsHingeConstraint()
+{
+    // DUMMY FUNCTION
+}
+
+}

+ 7 - 33
gameplay/src/PhysicsHingeConstraint.h

@@ -23,18 +23,6 @@ class PhysicsHingeConstraint : public PhysicsConstraint
     friend class PhysicsController;
     friend class PhysicsController;
 
 
 public:
 public:
-    /**
-     * Destructor.
-     */
-    ~PhysicsHingeConstraint()
-    {
-        if (_constraint)
-        {
-            delete _constraint;
-            _constraint = NULL;
-        }
-    }
-
     /**
     /**
      * Sets the limits (and optionally, some properties) for the hinge.
      * Sets the limits (and optionally, some properties) for the hinge.
      * 
      * 
@@ -45,10 +33,7 @@ public:
      * @param relaxationFactor The relaxation factor for the hinge (defaults to 1.0).
      * @param relaxationFactor The relaxation factor for the hinge (defaults to 1.0).
      */
      */
     void setLimits(float minAngle, float maxAngle, float softness = 0.9f, 
     void setLimits(float minAngle, float maxAngle, float softness = 0.9f, 
-        float biasFactor = 0.3f, float relaxationFactor = 1.0f)
-    {
-        ((btHingeConstraint*)_constraint)->setLimit(minAngle, maxAngle, softness, biasFactor, relaxationFactor);
-    }
+        float biasFactor = 0.3f, float relaxationFactor = 1.0f);
 
 
 private:
 private:
     /**
     /**
@@ -67,23 +52,12 @@ private:
      *      (in its local space) with respect to the constraint joint (optional).
      *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
     PhysicsHingeConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
-        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
-    {
-        if (b)
-        {
-            btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
-                btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
-            btTransform frameInB(btQuaternion(rotationOffsetB.x, rotationOffsetB.y, rotationOffsetB.z, rotationOffsetB.w), 
-                btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
-            _constraint = new btHingeConstraint(*a->_body, *b->_body, frameInA, frameInB);
-        }
-        else
-        {
-            btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
-                btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
-            _constraint = new btHingeConstraint(*a->_body, frameInA);
-        }
-    }
+        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
+
+    /**
+     * Destructor.
+     */
+    ~PhysicsHingeConstraint();
 };
 };
 
 
 }
 }

+ 60 - 0
gameplay/src/PhysicsMotionState.cpp

@@ -0,0 +1,60 @@
+/**
+ * PhysicsMotionState.cpp
+ */
+
+#include "PhysicsMotionState.h"
+
+namespace gameplay
+{
+
+PhysicsMotionState::PhysicsMotionState(Node* node, const Vector3* centerOfMassOffset) : _node(node),
+    _needsUpdate(false), _centerOfMassOffset(btTransform::getIdentity())
+{
+    // Store the initial world transform (minus the scale) for use by Bullet later on.
+    Quaternion rotation;
+    const Matrix& m = _node->getWorldMatrix();
+    m.getRotation(&rotation);
+
+    if (centerOfMassOffset)
+    {
+        // Store the center of mass offset.
+        _centerOfMassOffset.setOrigin(btVector3(centerOfMassOffset->x, centerOfMassOffset->y, centerOfMassOffset->z));
+
+        // When there is a center of mass offset, we modify the initial world transformation
+        // so that when physics is initially applied, the object is in the correct location.
+        btQuaternion orientation(rotation.x, rotation.y, rotation.z, rotation.w);
+        btTransform offset = btTransform(orientation, btVector3(0.0f, 0.0f, 0.0f)) * _centerOfMassOffset.inverse();
+
+        btVector3 origin(m.m[12] + _centerOfMassOffset.getOrigin().getX() + offset.getOrigin().getX(),
+            m.m[13] + _centerOfMassOffset.getOrigin().getY() + offset.getOrigin().getY(), 
+            m.m[14] + _centerOfMassOffset.getOrigin().getZ() + offset.getOrigin().getZ());
+        _worldTransform = btTransform(orientation, origin);
+    }
+    else
+    {
+		_worldTransform = btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w), 
+			btVector3(m.m[12], m.m[13], m.m[14]));
+    }
+}
+
+PhysicsMotionState::~PhysicsMotionState()
+{
+}
+
+void PhysicsMotionState::getWorldTransform(btTransform &transform) const
+{
+	transform = _centerOfMassOffset.inverse() * _worldTransform;
+}
+
+void PhysicsMotionState::setWorldTransform(const btTransform &transform)
+{
+    _worldTransform = transform * _centerOfMassOffset;
+        
+    const btQuaternion& rot = _worldTransform.getRotation();
+	const btVector3& pos = _worldTransform.getOrigin();
+
+	_node->setRotation(rot.x(), rot.y(), rot.z(), rot.w());
+	_node->setTranslation(pos.x(), pos.y(), pos.z());
+}
+
+}

+ 28 - 81
gameplay/src/PhysicsMotionState.h

@@ -7,95 +7,42 @@
 
 
 #include "Node.h"
 #include "Node.h"
 #include "PhysicsRigidBody.h"
 #include "PhysicsRigidBody.h"
-#include "Transform.h"
 
 
 namespace gameplay
 namespace gameplay
 {
 {
 
 
+/**
+ * Interface between GamePlay and Bullet to keep object transforms synchronized properly.
+ * 
+ * @see btMotionState
+ */
 class PhysicsMotionState : public btMotionState
 class PhysicsMotionState : public btMotionState
 {
 {
 	friend class PhysicsRigidBody;
 	friend class PhysicsRigidBody;
 
 
-    PhysicsMotionState(Node* node, const Vector3* centerOfMassOffset = NULL) : _node(node),
-        _needsUpdate(false), _centerOfMassOffset(btTransform::getIdentity())
-	{
-        // Store the initial world transform (minus the scale) for use by Bullet later on.
-        Quaternion rotation;
-        const Matrix& m = _node->getWorldMatrix();
-        m.getRotation(&rotation);
-
-        if (centerOfMassOffset)
-        {
-            // Store the center of mass offset.
-            _centerOfMassOffset.setOrigin(btVector3(centerOfMassOffset->x, centerOfMassOffset->y, centerOfMassOffset->z));
-
-            // When there is a center of mass offset, we modify the initial world transformation
-            // so that when physics is initially applied, the object is in the correct location.
-            btQuaternion orientation(rotation.x, rotation.y, rotation.z, rotation.w);
-            btTransform offset = btTransform(orientation, btVector3(0.0f, 0.0f, 0.0f)) * _centerOfMassOffset.inverse();
-
-            btVector3 origin(m.m[12] + _centerOfMassOffset.getOrigin().getX() + offset.getOrigin().getX(),
-                m.m[13] + _centerOfMassOffset.getOrigin().getY() + offset.getOrigin().getY(), 
-                m.m[14] + _centerOfMassOffset.getOrigin().getZ() + offset.getOrigin().getZ());
-            _worldTransform = btTransform(orientation, origin);
-        }
-        else
-        {
-		    _worldTransform = btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w), 
-			    btVector3(m.m[12], m.m[13], m.m[14]));
-        }
-	}
-
-public:
-
-	virtual ~PhysicsMotionState()
-	{
-    }
-
-    virtual void getWorldTransform(btTransform &transform) const
-	{
-		transform = _centerOfMassOffset.inverse() * _worldTransform;
-    }
-
-    virtual void setWorldTransform(const btTransform &transform)
-	{
-        _worldTransform = transform * _centerOfMassOffset;
-        
-        const btQuaternion& rot = _worldTransform.getRotation();
-		const btVector3& pos = _worldTransform.getOrigin();
-
-		_node->setRotation(rot.x(), rot.y(), rot.z(), rot.w());
-		_node->setTranslation(pos.x(), pos.y(), pos.z());
-    }
-
-    /*
-    void update()
-    {
-        static Quaternion r;
-        static Vector3 t;
-
-        if (_needsUpdate)
-        {
-            if (_node->getParent()->getPhysicsRigidBody())
-                _node->getParent()->getPhysicsRigidBody()->update();
-
-            // Use the inverse of the parent's world matrix to
-            // calculate the local transform change due to physics.
-            const Matrix& m = _node->getParent()->getWorldMatrix();
-            m.getRotation(&r);
-            m.getTranslation(&t);
-            btTransform parentWorldInverse = (btTransform(btQuaternion(r.x, r.y, r.z, r.w), btVector3(t.x, t.y, t.z))).inverse();
-            _worldTransform = parentWorldInverse * _worldTransform;
-
-            _needsUpdate = false;
-        }
-    }
-
-    const btTransform& getCenterOfMassOffset()
-    {
-        return _centerOfMassOffset;
-    }
-    */
+protected:
+    /**
+     * Creates a physics motion state for a rigid body.
+     * 
+     * @param node The node that owns the rigid body that the motion state is being created for.
+     * @param centerOfMassOffset The translation offset to the center of mass of the rigid body.
+     */
+    PhysicsMotionState(Node* node, const Vector3* centerOfMassOffset = NULL);
+
+    /**
+     * Destructor.
+     */
+	virtual ~PhysicsMotionState();
+
+    /**
+     * @see btMotionState#getWorldTransform
+     */
+    virtual void getWorldTransform(btTransform &transform) const;
+
+    /**
+     * @see btMotionState#setWorldTransform
+     */
+    virtual void setWorldTransform(const btTransform &transform);
 
 
 private:
 private:
 	Node* _node;
 	Node* _node;

+ 26 - 21
gameplay/src/PhysicsRigidBody.cpp

@@ -13,7 +13,7 @@ namespace gameplay
 
 
 PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, float mass, 
 PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, float mass, 
 		float friction, float restitution, float linearDamping, float angularDamping)
 		float friction, float restitution, float linearDamping, float angularDamping)
-        : _node(node), _body(NULL)
+        : _shape(NULL), _body(NULL), _node(node)
 {
 {
 	switch (type)
 	switch (type)
 	{
 	{
@@ -22,7 +22,7 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, floa
 			const BoundingBox& box = node->getModel()->getMesh()->getBoundingBox();
 			const BoundingBox& box = node->getModel()->getMesh()->getBoundingBox();
 
 
             PhysicsController* physics = Game::getInstance()->getPhysicsController();
             PhysicsController* physics = Game::getInstance()->getPhysicsController();
-            btCollisionShape* shape = physics->getBox(box.min, box.max, btVector3(node->getScaleX(), node->getScaleY(), node->getScaleZ()));
+            _shape = physics->getBox(box.min, box.max, btVector3(node->getScaleX(), node->getScaleY(), node->getScaleZ()));
 			
 			
             // Use the center of the bounding box as the center of mass offset.
             // Use the center of the bounding box as the center of mass offset.
             Vector3 c(box.min, box.max);
             Vector3 c(box.min, box.max);
@@ -31,9 +31,9 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, floa
             c.negate();
             c.negate();
 
 
             if (c.lengthSquared() > MATH_EPSILON)
             if (c.lengthSquared() > MATH_EPSILON)
-			    _body = createBulletRigidBody(shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
+			    _body = createBulletRigidBody(_shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
             else
             else
-                _body = createBulletRigidBody(shape, mass, node, friction, restitution, linearDamping, angularDamping);
+                _body = createBulletRigidBody(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
 
 
 			break;
 			break;
 		}
 		}
@@ -42,32 +42,32 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, floa
 			const BoundingSphere& sphere = node->getModel()->getMesh()->getBoundingSphere();
 			const BoundingSphere& sphere = node->getModel()->getMesh()->getBoundingSphere();
 
 
 			PhysicsController* physics = Game::getInstance()->getPhysicsController();
 			PhysicsController* physics = Game::getInstance()->getPhysicsController();
-			btCollisionShape* shape = physics->getSphere(sphere.radius, btVector3(node->getScaleX(), node->getScaleY(), node->getScaleZ()));
+			_shape = physics->getSphere(sphere.radius, btVector3(node->getScaleX(), node->getScaleY(), node->getScaleZ()));
 
 
             // Use the center of the bounding sphere as the center of mass offset.
             // Use the center of the bounding sphere as the center of mass offset.
             Vector3 c(sphere.center);
             Vector3 c(sphere.center);
             c.negate();
             c.negate();
 
 
             if (c.lengthSquared() > MATH_EPSILON)
             if (c.lengthSquared() > MATH_EPSILON)
-                _body = createBulletRigidBody(shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
+                _body = createBulletRigidBody(_shape, mass, node, friction, restitution, linearDamping, angularDamping, &c);
             else
             else
-                _body = createBulletRigidBody(shape, mass, node, friction, restitution, linearDamping, angularDamping);
+                _body = createBulletRigidBody(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
 
 
 			break;
 			break;
 		}
 		}
 		case PhysicsRigidBody::PHYSICS_SHAPE_TRIANGLE_MESH:
 		case PhysicsRigidBody::PHYSICS_SHAPE_TRIANGLE_MESH:
 		{
 		{
 			//btTriangleIndexVertexArray meshShape(numTriangles, indexPointer, indexStride, numVertices, vertexPointer, vertexStride);
 			//btTriangleIndexVertexArray meshShape(numTriangles, indexPointer, indexStride, numVertices, vertexPointer, vertexStride);
-			//btCollisionShape* shape = btBvhTriangleMeshShape(meshShape, true);
+			//_shape = btBvhTriangleMeshShape(meshShape, true);
 
 
-			//_body = createBulletRigidBody(shape, mass, node, friction, restitution, linearDamping, angularDamping);
+			//_body = createBulletRigidBody(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
 			break;
 			break;
 		}
 		}
 		case PhysicsRigidBody::PHYSICS_SHAPE_HEIGHTFIELD:
 		case PhysicsRigidBody::PHYSICS_SHAPE_HEIGHTFIELD:
 		{
 		{
-			//btCollisionShape* shape = btHeightfieldTerrainShape(width, length, data, scale, minHeight, maxHeight, upAxis, dataType, false);
+			//_shape = btHeightfieldTerrainShape(width, length, data, scale, minHeight, maxHeight, upAxis, dataType, false);
 
 
-			//_body = createBulletRigidBody(shape, mass, node, friction, restitution, linearDamping, angularDamping);
+			//_body = createBulletRigidBody(_shape, mass, node, friction, restitution, linearDamping, angularDamping);
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -75,12 +75,24 @@ PhysicsRigidBody::PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, floa
 
 
 PhysicsRigidBody::~PhysicsRigidBody()
 PhysicsRigidBody::~PhysicsRigidBody()
 {
 {
+    // Clean up all constraints linked to this rigid body.
+    for (unsigned int i = 0; i < _constraints.size(); i++)
+    {
+        Game::getInstance()->getPhysicsController()->removeConstraint(_constraints[i]);
+        SAFE_RELEASE(_constraints[i]);
+    }
+
+    // Clean up the rigid body and its related objects.
     if (_body)
     if (_body)
     {
     {
         if (_body->getMotionState())
         if (_body->getMotionState())
             delete _body->getMotionState();
             delete _body->getMotionState();
 
 
-        delete _body;
+        if (_shape)
+            SAFE_DELETE(_shape);
+
+        Game::getInstance()->getPhysicsController()->removeRigidBody(this);
+        SAFE_DELETE(_body);
     }
     }
 }
 }
 
 
@@ -137,15 +149,6 @@ void PhysicsRigidBody::applyTorqueImpulse(const Vector3& torque)
     }
     }
 }
 }
 
 
-// TODO!!
-/*
-void PhysicsRigidBody::update()
-{
-    if (_body->getMotionState())
-        ((PhysicsMotionState*)_body->getMotionState())->update();
-}
-*/
-
 btRigidBody* PhysicsRigidBody::createBulletRigidBody(btCollisionShape* shape, float mass, Node* node,
 btRigidBody* PhysicsRigidBody::createBulletRigidBody(btCollisionShape* shape, float mass, Node* node,
     float friction, float restitution, float linearDamping, float angularDamping, const Vector3* centerOfMassOffset)
     float friction, float restitution, float linearDamping, float angularDamping, const Vector3* centerOfMassOffset)
 {
 {
@@ -171,4 +174,6 @@ btRigidBody* PhysicsRigidBody::createBulletRigidBody(btCollisionShape* shape, fl
 	return body;
 	return body;
 }
 }
 
 
+
+
 }
 }

+ 159 - 100
gameplay/src/PhysicsRigidBody.h

@@ -14,6 +14,7 @@ namespace gameplay
 {
 {
 
 
 class Node;
 class Node;
+class PhysicsConstraint;
 
 
 /**
 /**
  * Defines a class for physics rigid bodies.
  * Defines a class for physics rigid bodies.
@@ -21,14 +22,18 @@ class Node;
 class PhysicsRigidBody : public Ref
 class PhysicsRigidBody : public Ref
 {
 {
     friend class Node;
     friend class Node;
-	friend class PhysicsMotionState;
+	friend class PhysicsController;
     friend class PhysicsFixedConstraint;
     friend class PhysicsFixedConstraint;
     friend class PhysicsGenericConstraint;
     friend class PhysicsGenericConstraint;
     friend class PhysicsHingeConstraint;
     friend class PhysicsHingeConstraint;
+    friend class PhysicsMotionState;
     friend class PhysicsSocketConstraint;
     friend class PhysicsSocketConstraint;
     friend class PhysicsSpringConstraint;
     friend class PhysicsSpringConstraint;
 
 
 public:
 public:
+    /**
+     * Represents the different types of rigid bodies.
+     */
 	enum Type
 	enum Type
 	{
 	{
 		PHYSICS_SHAPE_BOX,
 		PHYSICS_SHAPE_BOX,
@@ -38,133 +43,187 @@ public:
         PHYSICS_SHAPE_NONE
         PHYSICS_SHAPE_NONE
 	};
 	};
 
 
+    /**
+     * Applies the given force to the rigid body (optionally, from the given relative position).
+     * 
+     * @param force The force to be applied.
+     * @param relativePosition The relative position from which to apply the force.
+     */
     void applyForce(const Vector3& force, const Vector3* relativePosition = NULL);
     void applyForce(const Vector3& force, const Vector3* relativePosition = NULL);
-	void applyImpulse(const Vector3& impulse, const Vector3* relativePosition = NULL);
-	void applyTorque(const Vector3& torque);
-    void applyTorqueImpulse(const Vector3& torque);
-    // TODO!!
-    //void update();
 
 
-    inline void setFriction(float friction);
-    inline void setRestitution(float restitution);
-    inline void setAnisotropicFriction(const Vector3& friction);
-    inline void setGravity(const Vector3& gravity);
-	inline float getFriction();
-    inline float getRestitution();
-    inline Vector3 getAnisotropicFriction();
-    inline Vector3 getGravity();
+    /**
+     * Applies the given force impulse to the rigid body (optionally, from the given relative position).
+     * 
+     * @param impulse The force impulse to be applied.
+     * @param relativePosition The relative position from which to apply the force.
+     */
+	void applyImpulse(const Vector3& impulse, const Vector3* relativePosition = NULL);
 
 
-    inline void setLinearVelocity(const Vector3& velocity);
-	inline void setAngularVelocity(const Vector3& velocity);
+    /**
+     * Applies the given torque to the rigid body.
+     * 
+     * @param torque The torque to be applied.
+     */
+	void applyTorque(const Vector3& torque);
 
 
-	inline Vector3 getLinearVelocity();
-	inline Vector3 getAngularVelocity();
+    /**
+     * Applies the given torque impulse to the rigid body.
+     * 
+     * @param torque The torque impulse to be applied.
+     */
+    void applyTorqueImpulse(const Vector3& torque);
+    
+    /**
+     * Gets the rigid body's angular damping.
+     * 
+     * @return The angular damping.
+     */
+    inline float getAngularDamping() const;
 
 
-	inline void setDamping(float linearDamping, float angularDamping);
-	inline float getLinearDamping();
-	inline float getAngularDamping();
+    /**
+     * Gets the rigid body's angular velocity.
+     * 
+     * @return The angular velocity.
+     */
+    inline Vector3 getAngularVelocity() const;
 
 
-private:
-    PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, float mass, float friction = 0.5,
-        float restitution = 0.0, float linearDamping = 0.0, float angularDamping = 0.0);
-    ~PhysicsRigidBody();
+    /**
+     * Gets the rigid body's anisotropic friction.
+     * 
+     * @return The anisotropic friction.
+     */
+    inline Vector3 getAnisotropicFriction() const;
 
 
     /**
     /**
-     * Private copy constructor to disallow copying.
+     * Gets the rigid body's friction.
+     * 
+     * @return The friction.
      */
      */
-    PhysicsRigidBody(const PhysicsRigidBody& body) {}
+    inline float getFriction() const;
 
 
-	static btRigidBody* createBulletRigidBody(btCollisionShape* shape, float mass, Node* node,
-        float friction, float restitution, float linearDamping, float angularDamping,
-        const Vector3* centerOfMassOffset = NULL);
+    /**
+     * Gets the gravity that affects the rigid body (this can
+     * be different from the global gravity; @see #setGravity).
+     * 
+     * @return The gravity.
+     */
+    inline Vector3 getGravity() const;
 
 
-	btRigidBody* _body;
-    Node* _node;
-};
+    /**
+     * Gets the rigid body's linear damping.
+     * 
+     * @return The linear damping.
+     */
+    inline float getLinearDamping() const;
 
 
-// Inline functions.
+    /**
+     * Gets the rigid body's linear velocity.
+     * 
+     * @return The linear velocity.
+     */
+    inline Vector3 getLinearVelocity() const;
 
 
-void PhysicsRigidBody::setFriction(float friction)
-{
-    _body->setFriction(friction);
-}
+    /**
+     * Gets the rigid body's restitution.
+     * 
+     * @return The restitution.
+     */
+    inline float getRestitution() const;
 
 
-void PhysicsRigidBody::setRestitution(float restitution)
-{
-    _body->setRestitution(restitution);
-}
+    /**
+     * Sets the rigid body's angular velocity.
+     * 
+     * @param velocity The angular velocity.
+     */
+    inline void setAngularVelocity(const Vector3& velocity);
 
 
-float PhysicsRigidBody::getFriction()
-{
-    return _body->getFriction();
-}
+    /**
+     * Sets the rigid body's anisotropic friction.
+     * 
+     * @param friction The anisotropic friction.
+     */
+    inline void setAnisotropicFriction(const Vector3& friction);
 
 
-float PhysicsRigidBody::getRestitution()
-{
-    return _body->getRestitution();
-}
+    /**
+     * Sets the rigid body's linear and angular damping.
+     * 
+     * @param linearDamping The linear damping; between 0.0 (minimum) and 1.0 (maximum).
+     * @param angularDamping The angular damping; between 0.0 (minimum) and 1.0 (maximum).
+     */
+	inline void setDamping(float linearDamping, float angularDamping);
 
 
-void PhysicsRigidBody::setLinearVelocity(const Vector3& velocity)
-{
-	_body->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
-}
+    /**
+     * Sets the rigid body's friction.
+     * 
+     * @param friction The friction.
+     */
+    inline void setFriction(float friction);
 
 
-void PhysicsRigidBody::setAngularVelocity(const Vector3& velocity)
-{
-	_body->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
-}
+    /**
+     * Sets the rigid body's gravity (this overrides the global gravity for this rigid body).
+     * 
+     * @param gravity The gravity.
+     */
+    inline void setGravity(const Vector3& gravity);
 
 
-// TODO: We can't cache these Vector3 values, but should we have member variables
-// that are set each time instead of creating a new Vector3 every time?
-Vector3 PhysicsRigidBody::getLinearVelocity()
-{
-	const btVector3& v = _body->getLinearVelocity();
-	return Vector3(v.x(), v.y(), v.z());
-}
+    /**
+     * Sets the rigid body's linear velocity.
+     * 
+     * @param velocity The linear velocity.
+     */
+    inline void setLinearVelocity(const Vector3& velocity);
 
 
-Vector3 PhysicsRigidBody::getAngularVelocity()
-{
-	const btVector3& v = _body->getAngularVelocity();
-	return Vector3(v.x(), v.y(), v.z());
-}
+    /**
+     * Sets the rigid body's restitution (or bounciness).
+     * 
+     * @param restitution The restitution.
+     */
+	inline void setRestitution(float restitution);
 
 
-Vector3 PhysicsRigidBody::getAnisotropicFriction()
-{
-    const btVector3& af = _body->getAnisotropicFriction();
-    return Vector3(af.x(), af.y(), af.z());
-}
+private:
+    /**
+     * Creates a rigid body.
+     * 
+     * @param node The node to create a rigid body for; note that the node must have
+     *      a model attached to it prior to creating a rigid body for it.
+     * @param type The type of rigid body to set.
+     * @param mass The mass of the rigid body, in kilograms.
+     * @param friction The friction of the rigid body (non-zero values give best simulation results).
+     * @param restitution The restitution of the rigid body (this controls the bounciness of
+     *      the rigid body; use zero for best simulation results).
+     * @param linearDamping The percentage of linear velocity lost per second (between 0.0 and 1.0).
+     * @param angularDamping The percentage of angular velocity lost per second (between 0.0 and 1.0).
+     */
+    PhysicsRigidBody(Node* node, PhysicsRigidBody::Type type, float mass, float friction = 0.5,
+        float restitution = 0.0, float linearDamping = 0.0, float angularDamping = 0.0);
 
 
-Vector3 PhysicsRigidBody::getGravity()
-{
-    const btVector3& g = _body->getGravity();
-    return Vector3(g.x(), g.y(), g.z());
-}
+    /**
+     * Destructor.
+     */
+    ~PhysicsRigidBody();
 
 
-void PhysicsRigidBody::setDamping(float linearDamping, float angularDamping)
-{
-    _body->setDamping(linearDamping, angularDamping);
-}
+    /**
+     * Private copy constructor to disallow copying.
+     */
+    PhysicsRigidBody(const PhysicsRigidBody& body);
 
 
-float PhysicsRigidBody::getLinearDamping()
-{
-	return _body->getLinearDamping();
-}
+    // Creates the underlying Bullet Physics rigid body object
+    // for a PhysicsRigidBody object using the given parameters.
+	static btRigidBody* createBulletRigidBody(btCollisionShape* shape, float mass, Node* node,
+        float friction, float restitution, float linearDamping, float angularDamping,
+        const Vector3* centerOfMassOffset = NULL);
 
 
-float PhysicsRigidBody::getAngularDamping()
-{
-	return _body->getAngularDamping();
-}
+    // Adds a constraint to this rigid body.
+    inline void addConstraint(PhysicsConstraint* constraint);
 
 
-void PhysicsRigidBody::setAnisotropicFriction(const Vector3& friction)
-{
-    _body->setAnisotropicFriction(btVector3(friction.x, friction.y, friction.z));
-}
+	btCollisionShape* _shape;
+    btRigidBody* _body;
+    Node* _node;
+    std::vector<PhysicsConstraint*> _constraints;
+};
 
 
-void PhysicsRigidBody::setGravity(const Vector3& gravity)
-{
-    _body->setGravity(btVector3(gravity.x, gravity.y, gravity.z));
 }
 }
 
 
-}
+#include "PhysicsRigidBody.inl"
 
 
 #endif
 #endif

+ 97 - 0
gameplay/src/PhysicsRigidBody.inl

@@ -0,0 +1,97 @@
+/**
+ * PhysicsRigidBody.inl
+ */
+
+#include "PhysicsRigidBody.h"
+
+namespace gameplay
+{
+
+// TODO: We can't cache these Vector3 values, but should we have member variables
+// that are set each time instead of creating a new Vector3 every time?
+
+inline float PhysicsRigidBody::getAngularDamping() const
+{
+	return _body->getAngularDamping();
+}
+
+inline Vector3 PhysicsRigidBody::getAngularVelocity() const
+{
+	const btVector3& v = _body->getAngularVelocity();
+	return Vector3(v.x(), v.y(), v.z());
+}
+
+inline Vector3 PhysicsRigidBody::getAnisotropicFriction() const
+{
+    const btVector3& af = _body->getAnisotropicFriction();
+    return Vector3(af.x(), af.y(), af.z());
+}
+
+inline float PhysicsRigidBody::getFriction() const
+{
+    return _body->getFriction();
+}
+
+inline Vector3 PhysicsRigidBody::getGravity() const
+{
+    const btVector3& g = _body->getGravity();
+    return Vector3(g.x(), g.y(), g.z());
+}
+
+inline float PhysicsRigidBody::getLinearDamping() const
+{
+	return _body->getLinearDamping();
+}
+
+inline Vector3 PhysicsRigidBody::getLinearVelocity() const
+{
+	const btVector3& v = _body->getLinearVelocity();
+	return Vector3(v.x(), v.y(), v.z());
+}
+
+inline float PhysicsRigidBody::getRestitution() const
+{
+    return _body->getRestitution();
+}
+
+inline void PhysicsRigidBody::setAngularVelocity(const Vector3& velocity)
+{
+	_body->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
+}
+
+inline void PhysicsRigidBody::setAnisotropicFriction(const Vector3& friction)
+{
+    _body->setAnisotropicFriction(btVector3(friction.x, friction.y, friction.z));
+}
+
+inline void PhysicsRigidBody::setDamping(float linearDamping, float angularDamping)
+{
+    _body->setDamping(linearDamping, angularDamping);
+}
+
+inline void PhysicsRigidBody::setFriction(float friction)
+{
+    _body->setFriction(friction);
+}
+
+inline void PhysicsRigidBody::setGravity(const Vector3& gravity)
+{
+    _body->setGravity(btVector3(gravity.x, gravity.y, gravity.z));
+}
+
+inline void PhysicsRigidBody::setLinearVelocity(const Vector3& velocity)
+{
+	_body->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
+}
+
+inline void PhysicsRigidBody::setRestitution(float restitution)
+{
+    _body->setRestitution(restitution);
+}
+
+inline void PhysicsRigidBody::addConstraint(PhysicsConstraint* constraint)
+{
+    _constraints.push_back(constraint);
+}
+
+}

+ 65 - 0
gameplay/src/PhysicsSocketConstraint.cpp

@@ -0,0 +1,65 @@
+/**
+ * PhysicsSocketConstraint.cpp
+ */
+
+#include "PhysicsSocketConstraint.h"
+
+#include "Node.h"
+
+namespace gameplay
+{
+
+PhysicsSocketConstraint::PhysicsSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    if (b)
+    {
+        // Create a translation matrix that translates to the midpoint
+        // between the two physics rigid bodies.
+        Matrix m;
+        Matrix::createTranslation(midpoint(a->_node, b->_node), &m);
+
+        // Calculate the translation offsets to the rigid bodies
+        // by transforming the translation matrix above into each rigid body's
+        // local space (multiply by the inverse world matrix and extract translation).
+        Matrix mAi;
+        a->_node->getWorldMatrix().invert(&mAi);
+        mAi.multiply(m);
+
+        Matrix mBi;
+        b->_node->getWorldMatrix().invert(&mBi);
+        mBi.multiply(m);
+    
+        Vector3 tA, tB;
+        mAi.getTranslation(&tA);
+        mBi.getTranslation(&tB);
+
+        _constraint = new btPoint2PointConstraint(*a->_body, *b->_body, btVector3(tA.x, tA.y, tA.z), btVector3(tB.x, tB.y, tB.z));
+    }
+    else
+    {
+        _constraint = new btPoint2PointConstraint(*a->_body, btVector3(0.0f, 0.0f, 0.0f));
+    }
+}
+
+PhysicsSocketConstraint::PhysicsSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA, 
+    PhysicsRigidBody* b, const Vector3& translationOffsetB)
+{
+    if (b)
+    {
+        _constraint = new btPoint2PointConstraint(*a->_body, *b->_body, 
+            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z),
+            btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
+    }
+    else
+    {
+        _constraint = new btPoint2PointConstraint(*a->_body, 
+            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
+    }
+}
+
+PhysicsSocketConstraint::~PhysicsSocketConstraint()
+{
+    // DUMMY FUNCTION
+}
+
+}

+ 15 - 25
gameplay/src/PhysicsSocketConstraint.h

@@ -21,20 +21,18 @@ class PhysicsSocketConstraint : public PhysicsConstraint
 {
 {
     friend class PhysicsController;
     friend class PhysicsController;
 
 
-public:
+private:
     /**
     /**
-     * Destructor.
+     * Creates a socket constraint so that the rigid body (or bodies) is
+     * (are) constrained using its (their) current world position(s) for
+     * the translation offset(s) to the constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
      */
      */
-    ~PhysicsSocketConstraint()
-    {
-        if (_constraint)
-        {
-            delete _constraint;
-            _constraint = NULL;
-        }
-    }
+    PhysicsSocketConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
 
 
-private:
     /**
     /**
      * Creates a socket constraint.
      * Creates a socket constraint.
      * 
      * 
@@ -47,20 +45,12 @@ private:
      *      (in its local space) with respect to the constraint joint (optional).
      *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA, 
     PhysicsSocketConstraint(PhysicsRigidBody* a, const Vector3& translationOffsetA, 
-        PhysicsRigidBody* b, const Vector3& translationOffsetB)
-    {
-        if (b)
-        {
-            _constraint = new btPoint2PointConstraint(*a->_body, *b->_body, 
-                btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z),
-                btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
-        }
-        else
-        {
-            _constraint = new btPoint2PointConstraint(*a->_body, 
-                btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
-        }
-    }
+        PhysicsRigidBody* b, const Vector3& translationOffsetB);
+
+    /**
+     * Destructor.
+     */
+    ~PhysicsSocketConstraint();
 };
 };
 
 
 }
 }

+ 73 - 0
gameplay/src/PhysicsSpringConstraint.cpp

@@ -0,0 +1,73 @@
+/**
+ * PhysicsSpringConstraint.cpp
+ */
+
+#include "PhysicsSpringConstraint.h"
+
+#include "Node.h"
+#include "PhysicsRigidBody.h"
+
+namespace gameplay
+{
+
+PhysicsSpringConstraint::PhysicsSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b)
+{
+    // Create a translation matrix that translates to the midpoint
+    // between the two physics rigid bodies.
+    Matrix m;
+    Matrix::createTranslation(midpoint(a->_node, b->_node), &m);
+
+    // Calculate the translation and rotation offsets to the rigid bodies
+    // by transforming the translation matrix above into each rigid body's
+    // local space (multiply by the inverse world matrix and extract components).
+    Matrix mAi;
+    a->_node->getWorldMatrix().invert(&mAi);
+    mAi.multiply(m);
+
+    Matrix mBi;
+    b->_node->getWorldMatrix().invert(&mBi);
+    mBi.multiply(m);
+
+    Quaternion rA, rB;
+    mAi.getRotation(&rA);
+    mBi.getRotation(&rB);
+    
+    Vector3 tA, tB;
+    mAi.getTranslation(&tA);
+    mBi.getTranslation(&tB);
+
+    btTransform frameInA(btQuaternion(rA.x, rA.y, rA.z, rA.w), btVector3(tA.x, tA.y, tA.z));
+    btTransform frameInB(btQuaternion(rB.x, rB.y, rB.z, rB.w), btVector3(tB.x, tB.y, tB.z));
+            
+    _constraint = new btGeneric6DofSpringConstraint(*a->_body, *b->_body, frameInA, frameInB, true);
+}
+
+PhysicsSpringConstraint::PhysicsSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
+    PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
+{
+    btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
+        btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
+    btTransform frameInB(btQuaternion(rotationOffsetB.x, rotationOffsetB.y, rotationOffsetB.z, rotationOffsetB.w), 
+        btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
+    _constraint = new btGeneric6DofSpringConstraint(*a->_body, *b->_body, frameInA, frameInB, true);
+}
+
+void PhysicsSpringConstraint::setStrength(SpringProperty property, float strength)
+{
+    if (strength < MATH_EPSILON)
+        ((btGeneric6DofSpringConstraint*)_constraint)->enableSpring(property, false);
+    else
+    {
+        ((btGeneric6DofSpringConstraint*)_constraint)->enableSpring(property, true);
+        ((btGeneric6DofSpringConstraint*)_constraint)->setStiffness(property, strength);
+        ((btGeneric6DofSpringConstraint*)_constraint)->setEquilibriumPoint(property);
+    }
+}
+
+void PhysicsSpringConstraint::setDamping(SpringProperty property, float damping)
+{
+    ((btGeneric6DofSpringConstraint*)_constraint)->setDamping(property, damping);
+    ((btGeneric6DofSpringConstraint*)_constraint)->setEquilibriumPoint(property);
+}
+
+}

+ 44 - 89
gameplay/src/PhysicsSpringConstraint.h

@@ -26,30 +26,21 @@ public:
      * 
      * 
      * @param damping The angular damping value.
      * @param damping The angular damping value.
      */
      */
-    inline void setAngularDampingX(float damping)
-    {
-        setDamping(ANGULAR_X, damping);
-    }
+    inline void setAngularDampingX(float damping);
 
 
     /**
     /**
      * Sets the angular damping along the constraint's local Y axis.
      * Sets the angular damping along the constraint's local Y axis.
      * 
      * 
      * @param damping The angular damping value.
      * @param damping The angular damping value.
      */
      */
-    inline void setAngularDampingY(float damping)
-    {
-        setDamping(ANGULAR_Y, damping);
-    }
+    inline void setAngularDampingY(float damping);
 
 
     /**
     /**
      * Sets the angular damping along the constraint's local Z axis.
      * Sets the angular damping along the constraint's local Z axis.
      * 
      * 
      * @param damping The angular damping value.
      * @param damping The angular damping value.
      */
      */
-    inline void setAngularDampingZ(float damping)
-    {
-        setDamping(ANGULAR_Z, damping);
-    }
+    inline void setAngularDampingZ(float damping);
 
 
     /**
     /**
      * Sets the angular strength along the constraint's local X axis.
      * Sets the angular strength along the constraint's local X axis.
@@ -59,10 +50,7 @@ public:
      * 
      * 
      * @param strength The angular strength value.
      * @param strength The angular strength value.
      */
      */
-    inline void setAngularStrengthX(float strength)
-    {
-        setStrength(ANGULAR_X, strength);
-    }
+    inline void setAngularStrengthX(float strength);
 
 
     /**
     /**
      * Sets the angular strength along the constraint's local Y axis.
      * Sets the angular strength along the constraint's local Y axis.
@@ -72,10 +60,7 @@ public:
      * 
      * 
      * @param strength The angular strength value.
      * @param strength The angular strength value.
      */
      */
-    inline void setAngularStrengthY(float strength)
-    {
-        setStrength(ANGULAR_Y, strength);
-    }
+    inline void setAngularStrengthY(float strength);
 
 
     /**
     /**
      * Sets the angular strength along the constraint's local Z axis.
      * Sets the angular strength along the constraint's local Z axis.
@@ -85,40 +70,28 @@ public:
      * 
      * 
      * @param strength The angular strength value.
      * @param strength The angular strength value.
      */
      */
-    inline void setAngularStrengthZ(float strength)
-    {
-        setStrength(ANGULAR_Z, strength);
-    }
+    inline void setAngularStrengthZ(float strength);
 
 
     /**
     /**
      * Sets the linear damping along the constraint's local X axis.
      * Sets the linear damping along the constraint's local X axis.
      * 
      * 
      * @param damping The linear damping value.
      * @param damping The linear damping value.
      */
      */
-    inline void setLinearDampingX(float damping)
-    {
-        setDamping(LINEAR_X, damping);
-    }
+    inline void setLinearDampingX(float damping);
 
 
     /**
     /**
      * Sets the linear damping along the constraint's local Y axis.
      * Sets the linear damping along the constraint's local Y axis.
      * 
      * 
      * @param damping The linear damping value.
      * @param damping The linear damping value.
      */
      */
-    inline void setLinearDampingY(float damping)
-    {
-        setDamping(LINEAR_Y, damping);
-    }
+    inline void setLinearDampingY(float damping);
 
 
     /**
     /**
      * Sets the linear damping along the constraint's local Z axis.
      * Sets the linear damping along the constraint's local Z axis.
      * 
      * 
      * @param damping The linear damping value.
      * @param damping The linear damping value.
      */
      */
-    inline void setLinearDampingZ(float damping)
-    {
-        setDamping(LINEAR_Z, damping);
-    }
+    inline void setLinearDampingZ(float damping);
 
 
     /**
     /**
      * Sets the linear strength along the constraint's local X axis.
      * Sets the linear strength along the constraint's local X axis.
@@ -128,10 +101,7 @@ public:
      * 
      * 
      * @param strength The linear strength value.
      * @param strength The linear strength value.
      */
      */
-    inline void setLinearStrengthX(float strength)
-    {
-        setStrength(LINEAR_X, strength);
-    }
+    inline void setLinearStrengthX(float strength);
 
 
     /**
     /**
      * Sets the linear strength along the constraint's local Y axis.
      * Sets the linear strength along the constraint's local Y axis.
@@ -141,10 +111,7 @@ public:
      * 
      * 
      * @param strength The linear strength value.
      * @param strength The linear strength value.
      */
      */
-    inline void setLinearStrengthY(float strength)
-    {
-        setStrength(LINEAR_Y, strength);
-    }
+    inline void setLinearStrengthY(float strength);
 
 
     /**
     /**
      * Sets the linear strength along the constraint's local Z axis.
      * Sets the linear strength along the constraint's local Z axis.
@@ -154,12 +121,36 @@ public:
      * 
      * 
      * @param strength The linear strength value.
      * @param strength The linear strength value.
      */
      */
-    inline void setLinearStrengthZ(float strength)
-    {
-        setStrength(LINEAR_Z, strength);
-    }
+    inline void setLinearStrengthZ(float strength);
 
 
 private:
 private:
+    // Represents the different properties that
+    // can be set on the spring constraint.
+    // 
+    // (Note: the values map to the index parameter
+    // used in the member functions of the Bullet
+    // class btGeneric6DofSpringConstraint.)
+    enum SpringProperty
+    {
+        LINEAR_X = 0,
+        LINEAR_Y,
+        LINEAR_Z,
+        ANGULAR_X,
+        ANGULAR_Y,
+        ANGULAR_Z
+    };
+
+    /**
+     * Creates a spring constraint so that the rigid body (or bodies) is
+     * (are) constrained using its (their) current world position(s) for
+     * the translation offset(s) to the constraint.
+     * 
+     * @param a The first (possibly only) rigid body to constrain. If this is the only rigid
+     *      body specified the constraint applies between it and the global physics world object.
+     * @param b The second rigid body to constrain (optional).
+     */
+    PhysicsSpringConstraint(PhysicsRigidBody* a, PhysicsRigidBody* b);
+
     /**
     /**
      * Creates a spring constraint.
      * Creates a spring constraint.
      * 
      * 
@@ -176,61 +167,25 @@ private:
      *      (in its local space) with respect to the constraint joint (optional).
      *      (in its local space) with respect to the constraint joint (optional).
      */
      */
     PhysicsSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
     PhysicsSpringConstraint(PhysicsRigidBody* a, const Quaternion& rotationOffsetA, const Vector3& translationOffsetA,
-        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB)
-        : PhysicsGenericConstraint(a, rotationOffsetA, translationOffsetA, b, rotationOffsetB, translationOffsetB)
-    {
-        btTransform frameInA(btQuaternion(rotationOffsetA.x, rotationOffsetA.y, rotationOffsetA.z, rotationOffsetA.w), 
-            btVector3(translationOffsetA.x, translationOffsetA.y, translationOffsetA.z));
-        btTransform frameInB(btQuaternion(rotationOffsetB.x, rotationOffsetB.y, rotationOffsetB.z, rotationOffsetB.w), 
-            btVector3(translationOffsetB.x, translationOffsetB.y, translationOffsetB.z));
-        _constraint = new btGeneric6DofSpringConstraint(*a->_body, *b->_body, frameInA, frameInB, true);
-    }
-
-    // Represents the different properties that
-    // can be set on the spring constraint.
-    // 
-    // (Note: the values map to the index parameter
-    // used in the member functions of the Bullet
-    // class btGeneric6DofSpringConstraint.)
-    enum SpringProperty
-    {
-        LINEAR_X = 0,
-        LINEAR_Y,
-        LINEAR_Z,
-        ANGULAR_X,
-        ANGULAR_Y,
-        ANGULAR_Z
-    };
+        PhysicsRigidBody* b, const Quaternion& rotationOffsetB, const Vector3& translationOffsetB);
 
 
     // Sets the strength for the given angular/linear 
     // Sets the strength for the given angular/linear 
     // X/Y/Z axis combination determined by the given index.
     // X/Y/Z axis combination determined by the given index.
     // 
     // 
     // See the Bullet class btGeneric6DofSpringConstraint
     // See the Bullet class btGeneric6DofSpringConstraint
     // for more information.
     // for more information.
-    void setStrength(SpringProperty property, float strength)
-    {
-        if (strength < MATH_EPSILON)
-            ((btGeneric6DofSpringConstraint*)_constraint)->enableSpring(property, false);
-        else
-        {
-            ((btGeneric6DofSpringConstraint*)_constraint)->enableSpring(property, true);
-            ((btGeneric6DofSpringConstraint*)_constraint)->setStiffness(property, strength);
-            ((btGeneric6DofSpringConstraint*)_constraint)->setEquilibriumPoint(property);
-        }
-    }
+    void setStrength(SpringProperty property, float strength);
 
 
     // Sets the damping for the given angular/linear 
     // Sets the damping for the given angular/linear 
     // X/Y/Z axis combination determined by the given index.
     // X/Y/Z axis combination determined by the given index.
     // 
     // 
     // See the Bullet class btGeneric6DofSpringConstraint
     // See the Bullet class btGeneric6DofSpringConstraint
     // for more information.
     // for more information.
-    void setDamping(SpringProperty property, float damping)
-    {
-        ((btGeneric6DofSpringConstraint*)_constraint)->setDamping(property, damping);
-        ((btGeneric6DofSpringConstraint*)_constraint)->setEquilibriumPoint(property);
-    }
+    void setDamping(SpringProperty property, float damping);
 };
 };
 
 
 }
 }
 
 
+#include "PhysicsSpringConstraint.inl"
+
 #endif
 #endif

+ 70 - 0
gameplay/src/PhysicsSpringConstraint.inl

@@ -0,0 +1,70 @@
+/**
+ * PhysicsSpringConstraint.inl
+ */
+
+#include "PhysicsSpringConstraint.h"
+
+namespace gameplay
+{
+
+inline void PhysicsSpringConstraint::setAngularDampingX(float damping)
+{
+    setDamping(ANGULAR_X, damping);
+}
+
+inline void PhysicsSpringConstraint::setAngularDampingY(float damping)
+{
+    setDamping(ANGULAR_Y, damping);
+}
+
+inline void PhysicsSpringConstraint::setAngularDampingZ(float damping)
+{
+    setDamping(ANGULAR_Z, damping);
+}
+
+inline void PhysicsSpringConstraint::setAngularStrengthX(float strength)
+{
+    setStrength(ANGULAR_X, strength);
+}
+
+inline void PhysicsSpringConstraint::setAngularStrengthY(float strength)
+{
+    setStrength(ANGULAR_Y, strength);
+}
+
+inline void PhysicsSpringConstraint::setAngularStrengthZ(float strength)
+{
+    setStrength(ANGULAR_Z, strength);
+}
+
+inline void PhysicsSpringConstraint::setLinearDampingX(float damping)
+{
+    setDamping(LINEAR_X, damping);
+}
+
+inline void PhysicsSpringConstraint::setLinearDampingY(float damping)
+{
+    setDamping(LINEAR_Y, damping);
+}
+
+inline void PhysicsSpringConstraint::setLinearDampingZ(float damping)
+{
+    setDamping(LINEAR_Z, damping);
+}
+
+inline void PhysicsSpringConstraint::setLinearStrengthX(float strength)
+{
+    setStrength(LINEAR_X, strength);
+}
+
+inline void PhysicsSpringConstraint::setLinearStrengthY(float strength)
+{
+    setStrength(LINEAR_Y, strength);
+}
+
+inline void PhysicsSpringConstraint::setLinearStrengthZ(float strength)
+{
+    setStrength(LINEAR_Z, strength);
+}
+
+}