Ver Fonte

Merge pull request #195 from blackberry-gaming/next-cculy

Adds support for ghost objects to the physics system.
Sean Paul Taylor há 13 anos atrás
pai
commit
354078547a

+ 2 - 0
gameplay/gameplay.vcxproj

@@ -67,6 +67,7 @@
     <ClCompile Include="src\PhysicsController.cpp" />
     <ClCompile Include="src\PhysicsController.cpp" />
     <ClCompile Include="src\PhysicsFixedConstraint.cpp" />
     <ClCompile Include="src\PhysicsFixedConstraint.cpp" />
     <ClCompile Include="src\PhysicsGenericConstraint.cpp" />
     <ClCompile Include="src\PhysicsGenericConstraint.cpp" />
+    <ClCompile Include="src\PhysicsGhostObject.cpp" />
     <ClCompile Include="src\PhysicsHingeConstraint.cpp" />
     <ClCompile Include="src\PhysicsHingeConstraint.cpp" />
     <ClCompile Include="src\PhysicsMotionState.cpp" />
     <ClCompile Include="src\PhysicsMotionState.cpp" />
     <ClCompile Include="src\PhysicsRigidBody.cpp" />
     <ClCompile Include="src\PhysicsRigidBody.cpp" />
@@ -156,6 +157,7 @@
     <ClInclude Include="src\PhysicsController.h" />
     <ClInclude Include="src\PhysicsController.h" />
     <ClInclude Include="src\PhysicsFixedConstraint.h" />
     <ClInclude Include="src\PhysicsFixedConstraint.h" />
     <ClInclude Include="src\PhysicsGenericConstraint.h" />
     <ClInclude Include="src\PhysicsGenericConstraint.h" />
+    <ClInclude Include="src\PhysicsGhostObject.h" />
     <ClInclude Include="src\PhysicsHingeConstraint.h" />
     <ClInclude Include="src\PhysicsHingeConstraint.h" />
     <ClInclude Include="src\PhysicsMotionState.h" />
     <ClInclude Include="src\PhysicsMotionState.h" />
     <ClInclude Include="src\PhysicsRigidBody.h" />
     <ClInclude Include="src\PhysicsRigidBody.h" />

+ 7 - 1
gameplay/gameplay.vcxproj.filters

@@ -270,6 +270,9 @@
     <ClCompile Include="src\PhysicsCollisionObject.cpp">
     <ClCompile Include="src\PhysicsCollisionObject.cpp">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="src\PhysicsGhostObject.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
     <ClInclude Include="src\Animation.h">
@@ -533,6 +536,9 @@
     <ClInclude Include="src\TimeListener.h">
     <ClInclude Include="src\TimeListener.h">
       <Filter>src</Filter>
       <Filter>src</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="src\PhysicsGhostObject.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <None Include="res\shaders\bumped-specular.vsh">
     <None Include="res\shaders\bumped-specular.vsh">
@@ -667,4 +673,4 @@
       <Filter>src</Filter>
       <Filter>src</Filter>
     </None>
     </None>
   </ItemGroup>
   </ItemGroup>
-</Project>
+</Project>

+ 15 - 1
gameplay/src/Node.cpp

@@ -13,7 +13,7 @@ namespace gameplay
 Node::Node(const char* id)
 Node::Node(const char* id)
     : _scene(NULL), _firstChild(NULL), _nextSibling(NULL), _prevSibling(NULL), _parent(NULL), _childCount(NULL),
     : _scene(NULL), _firstChild(NULL), _nextSibling(NULL), _prevSibling(NULL), _parent(NULL), _childCount(NULL),
     _camera(NULL), _light(NULL), _model(NULL), _form(NULL), _audioSource(NULL), _particleEmitter(NULL), _physicsRigidBody(NULL), 
     _camera(NULL), _light(NULL), _model(NULL), _form(NULL), _audioSource(NULL), _particleEmitter(NULL), _physicsRigidBody(NULL), 
-    _dirtyBits(NODE_DIRTY_ALL), _notifyHierarchyChanged(true)
+    _ghostObject(NULL), _dirtyBits(NODE_DIRTY_ALL), _notifyHierarchyChanged(true)
 {
 {
     if (id)
     if (id)
     {
     {
@@ -46,6 +46,7 @@ Node::~Node()
     SAFE_RELEASE(_particleEmitter);
     SAFE_RELEASE(_particleEmitter);
     SAFE_RELEASE(_form);
     SAFE_RELEASE(_form);
     SAFE_DELETE(_physicsRigidBody);
     SAFE_DELETE(_physicsRigidBody);
+    SAFE_DELETE(_ghostObject);
 }
 }
 
 
 Node* Node::create(const char* id)
 Node* Node::create(const char* id)
@@ -780,4 +781,17 @@ void Node::setRigidBody(Properties* properties)
     _physicsRigidBody = PhysicsRigidBody::create(this, properties);
     _physicsRigidBody = PhysicsRigidBody::create(this, properties);
 }
 }
 
 
+PhysicsGhostObject* Node::getGhostObject()
+{
+    return _ghostObject;
+}
+
+void Node::setGhostObject(PhysicsRigidBody::ShapeType type)
+{
+    SAFE_DELETE(_ghostObject);
+    
+    if (type != PhysicsRigidBody::SHAPE_NONE)
+        _ghostObject = new PhysicsGhostObject(this, type);
+}
+
 }
 }

+ 19 - 0
gameplay/src/Node.h

@@ -8,6 +8,7 @@
 #include "Form.h"
 #include "Form.h"
 #include "AudioSource.h"
 #include "AudioSource.h"
 #include "ParticleEmitter.h"
 #include "ParticleEmitter.h"
+#include "PhysicsGhostObject.h"
 #include "PhysicsRigidBody.h"
 #include "PhysicsRigidBody.h"
 #include "BoundingBox.h"
 #include "BoundingBox.h"
 
 
@@ -390,6 +391,23 @@ public:
     void setRigidBody(PhysicsRigidBody::ShapeType type, float mass = 0.0f, float friction = 0.5f,
     void setRigidBody(PhysicsRigidBody::ShapeType type, float mass = 0.0f, float friction = 0.5f,
         float restitution = 0.0f, float linearDamping = 0.0f, float angularDamping = 0.0f);
         float restitution = 0.0f, float linearDamping = 0.0f, float angularDamping = 0.0f);
 
 
+    /**
+     * Returns the pointer to this node's physics ghost object or NULL.
+     * 
+     * @return The pointer to this node's physics ghost object or NULL.
+     */
+    PhysicsGhostObject* getGhostObject();
+
+    /**
+     * Sets (or disables) the physics ghost object for this node.
+     * 
+     * Note: This is only allowed for nodes that have a model attached to them.
+     *
+     * @param type The type of physics ghost object to set; to disable the physics ghost
+     *      object, pass PhysicsRigidBody#SHAPE_NONE.
+     */
+    void setGhostObject(PhysicsRigidBody::ShapeType type);
+
     /**
     /**
      * Sets the physics rigid body for this node using the rigid body definition in the given file.
      * Sets the physics rigid body for this node using the rigid body definition in the given file.
      * 
      * 
@@ -473,6 +491,7 @@ protected:
     AudioSource* _audioSource;
     AudioSource* _audioSource;
     ParticleEmitter* _particleEmitter;
     ParticleEmitter* _particleEmitter;
     PhysicsRigidBody* _physicsRigidBody;
     PhysicsRigidBody* _physicsRigidBody;
+    PhysicsGhostObject* _ghostObject;
     mutable Matrix _world;
     mutable Matrix _world;
     mutable int _dirtyBits;
     mutable int _dirtyBits;
     bool _notifyHierarchyChanged;
     bool _notifyHierarchyChanged;

+ 6 - 1
gameplay/src/PhysicsCollisionObject.h

@@ -30,7 +30,12 @@ public:
         /**
         /**
          * PhysicsCharacter type.
          * PhysicsCharacter type.
          */
          */
-        CHARACTER
+        CHARACTER,
+
+        /** 
+         * PhysicsGhostObject type.
+         */
+        GHOST_OBJECT
     };
     };
 
 
     /** 
     /** 

+ 5 - 0
gameplay/src/PhysicsController.cpp

@@ -417,6 +417,10 @@ void PhysicsController::addCollisionObject(PhysicsCollisionObject* object)
         _world->addCollisionObject(object->getCollisionObject(), btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter);
         _world->addCollisionObject(object->getCollisionObject(), btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::CharacterFilter | btBroadphaseProxy::DefaultFilter);
         break;
         break;
 
 
+    case PhysicsCollisionObject::GHOST_OBJECT:
+        _world->addCollisionObject(object->getCollisionObject(), btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::AllFilter);
+        break;
+
     default:
     default:
         assert(0); // unexpected (new type?)
         assert(0); // unexpected (new type?)
         break;
         break;
@@ -435,6 +439,7 @@ void PhysicsController::removeCollisionObject(PhysicsCollisionObject* object)
             break;
             break;
 
 
         case PhysicsCollisionObject::CHARACTER:
         case PhysicsCollisionObject::CHARACTER:
+        case PhysicsCollisionObject::GHOST_OBJECT:
             _world->removeCollisionObject(object->getCollisionObject());
             _world->removeCollisionObject(object->getCollisionObject());
             break;
             break;
 
 

+ 1 - 0
gameplay/src/PhysicsController.h

@@ -23,6 +23,7 @@ class PhysicsController : public btCollisionWorld::ContactResultCallback
     friend class PhysicsRigidBody;
     friend class PhysicsRigidBody;
     friend class PhysicsCharacter;
     friend class PhysicsCharacter;
     friend class PhysicsCollisionObject;
     friend class PhysicsCollisionObject;
+    friend class PhysicsGhostObject;
 
 
 public:
 public:
 
 

+ 93 - 0
gameplay/src/PhysicsGhostObject.cpp

@@ -0,0 +1,93 @@
+#include "Base.h"
+#include "Game.h"
+#include "PhysicsGhostObject.h"
+#include "Vector3.h"
+
+namespace gameplay
+{
+
+PhysicsGhostObject::PhysicsGhostObject(Node* node, PhysicsRigidBody::ShapeType type)
+    : _node(node), _motionState(NULL), _shape(NULL), _ghostObject(NULL)
+{
+    _node->addListener(this);
+
+    // Create the ghost object.
+    _ghostObject = bullet_new<btPairCachingGhostObject>();
+
+    // Get the node's world scale (we need to apply this during creation since ghost objects don't scale dynamically).
+    Vector3 scale;
+    _node->getWorldMatrix().getScale(&scale);
+
+    // Use the center of the bounding sphere as the center of mass offset.
+    Vector3 c(_node->getModel()->getMesh()->getBoundingSphere().center);
+    c.x *= scale.x;
+    c.y *= scale.y;
+    c.z *= scale.z;
+        
+    // Initialize a physics motion state object for syncing the transform.
+    Vector3 centerOfMassOffset(-c);
+    _motionState = new PhysicsMotionState(_node, &centerOfMassOffset);
+    _motionState->getWorldTransform(_ghostObject->getWorldTransform());
+
+    // Create and set the collision shape for the ghost object.
+    PhysicsController* physicsController = Game::getInstance()->getPhysicsController();
+    switch (type)
+    {
+        case PhysicsRigidBody::SHAPE_BOX:
+        {
+            const BoundingBox& box = node->getModel()->getMesh()->getBoundingBox();
+            _shape = physicsController->createBox(box.min, box.max, scale);
+            break;
+        }
+        case PhysicsRigidBody::SHAPE_SPHERE:
+        {
+            const BoundingSphere& sphere = node->getModel()->getMesh()->getBoundingSphere();
+            _shape = physicsController->createSphere(sphere.radius, scale);
+            break;
+        }
+    }
+    _ghostObject->setCollisionShape(_shape);
+
+    // Add the ghost object to the physics world.
+    physicsController->addCollisionObject(this);
+}
+
+PhysicsGhostObject::~PhysicsGhostObject()
+{
+    Game::getInstance()->getPhysicsController()->removeCollisionObject(this);
+
+    _shape = NULL;
+    SAFE_DELETE(_ghostObject);
+    SAFE_DELETE(_motionState);
+}
+
+PhysicsCollisionObject::Type PhysicsGhostObject::getType() const
+{
+    return GHOST_OBJECT;
+}
+
+Node* PhysicsGhostObject::getNode() const
+{
+    return _node;
+}
+
+btCollisionObject* PhysicsGhostObject::getCollisionObject() const
+{
+    return _ghostObject;
+}
+
+btCollisionShape* PhysicsGhostObject::getCollisionShape() const
+{
+    return _shape;
+}
+
+void PhysicsGhostObject::transformChanged(Transform* transform, long cookie)
+{
+    // Update the motion state with the transform from the node.
+    _motionState->updateTransformFromNode();
+
+    // Update the transform on the ghost object.
+    _motionState->getWorldTransform(_ghostObject->getWorldTransform());
+}
+
+}

+ 73 - 0
gameplay/src/PhysicsGhostObject.h

@@ -0,0 +1,73 @@
+#ifndef PHYSICSGHOSTOBJECT_H_
+#define PHYSICSGHOSTOBJECT_H_
+
+#include "PhysicsCollisionObject.h"
+#include "PhysicsRigidBody.h"
+#include "Transform.h"
+
+namespace gameplay
+{
+
+class PhysicsMotionState;
+
+/**
+ * Defines a class for physics ghost objects.
+ */
+class PhysicsGhostObject : public PhysicsCollisionObject, public Transform::Listener
+{
+    friend class Node;
+    friend class PhysicsController;
+
+public:
+
+    /**
+     * @see PhysicsCollisionObject#getType
+     */
+    PhysicsCollisionObject::Type getType() const;
+
+    /**
+     * @see PhysicsCollisionObject#getNode
+     */
+    Node* getNode() const;
+
+protected:
+
+    /**
+     * @see PhysicsCollisionObject::getCollisionObject
+     */
+    btCollisionObject* getCollisionObject() const;
+
+    /**
+     * @see PhysicsCollisionObject::getCollisionShape
+     */
+    btCollisionShape* getCollisionShape() const;
+
+private:
+
+    /**
+     * Constructor.
+     * 
+     * @param node The node to attach the ghost object to.
+     * @param type The type of ghost object (collision shape type).
+     */
+    PhysicsGhostObject(Node* node, PhysicsRigidBody::ShapeType type);
+    
+    /**
+     * Destructor.
+     */
+    ~PhysicsGhostObject();
+
+    /**
+     * Used to synchronize the transform between GamePlay and Bullet.
+     */
+    void transformChanged(Transform* transform, long cookie);
+
+    Node* _node;
+    PhysicsMotionState* _motionState;
+    btCollisionShape* _shape;
+    btGhostObject* _ghostObject;
+};
+
+}
+
+#endif

+ 1 - 0
gameplay/src/PhysicsMotionState.h

@@ -17,6 +17,7 @@ class PhysicsMotionState : public btMotionState
     friend class PhysicsRigidBody;
     friend class PhysicsRigidBody;
     friend class PhysicsCharacter;
     friend class PhysicsCharacter;
     friend class PhysicsConstraint;
     friend class PhysicsConstraint;
+    friend class PhysicsGhostObject;
 
 
 protected:
 protected: