Przeglądaj źródła

Adds support for kinematic rigid bodies.

Chris Culy 14 lat temu
rodzic
commit
f03f480731

+ 31 - 20
gameplay/src/PhysicsMotionState.cpp

@@ -10,31 +10,13 @@ namespace gameplay
 PhysicsMotionState::PhysicsMotionState(Node* node, const Vector3* centerOfMassOffset) : _node(node),
     _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]));
     }
+
+    updateTransformFromNode();
 }
 
 PhysicsMotionState::~PhysicsMotionState()
@@ -43,6 +25,9 @@ PhysicsMotionState::~PhysicsMotionState()
 
 void PhysicsMotionState::getWorldTransform(btTransform &transform) const
 {
+    if (_node->getPhysicsRigidBody() && _node->getPhysicsRigidBody()->isKinematic())
+        updateTransformFromNode();
+
     transform = _centerOfMassOffset.inverse() * _worldTransform;
 }
 
@@ -57,4 +42,30 @@ void PhysicsMotionState::setWorldTransform(const btTransform &transform)
     _node->setTranslation(pos.x(), pos.y(), pos.z());
 }
 
+void PhysicsMotionState::updateTransformFromNode() const
+{
+    // 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.getOrigin().isZero())
+    {
+        // 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]));
+    }
+}
+
 }

+ 4 - 1
gameplay/src/PhysicsMotionState.h

@@ -46,9 +46,12 @@ protected:
     virtual void setWorldTransform(const btTransform &transform);
 
 private:
+    // Updates the motion state's world transform from the GamePlay Node object's world transform.
+    void updateTransformFromNode() const;
+
     Node* _node;
     btTransform _centerOfMassOffset;
-    btTransform _worldTransform;
+    mutable btTransform _worldTransform;
 };
 
 }

+ 14 - 0
gameplay/src/PhysicsRigidBody.h

@@ -131,6 +131,13 @@ public:
      */
     inline float getRestitution() const;
 
+    /**
+     * Gets whether the rigid body is a kinematic rigid body or not.
+     * 
+     * @return Whether the rigid body is kinematic or not.
+     */
+    inline bool isKinematic() const;
+
     /**
      * Sets the rigid body's angular velocity.
      * 
@@ -167,6 +174,13 @@ public:
      */
     inline void setGravity(const Vector3& gravity);
 
+    /**
+     * Sets whether the rigid body is a kinematic rigid body or not.
+     * 
+     * @param kinematic Whether the rigid body is kinematic or not.
+     */
+    inline void setKinematic(bool kinematic);
+
     /**
      * Sets the rigid body's linear velocity.
      * 

+ 19 - 0
gameplay/src/PhysicsRigidBody.inl

@@ -54,6 +54,11 @@ inline float PhysicsRigidBody::getRestitution() const
     return _body->getRestitution();
 }
 
+inline bool PhysicsRigidBody::isKinematic() const
+{
+    return (_body->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT) != 0;
+}
+
 inline void PhysicsRigidBody::setAngularVelocity(const Vector3& velocity)
 {
     _body->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
@@ -79,6 +84,20 @@ inline void PhysicsRigidBody::setGravity(const Vector3& gravity)
     _body->setGravity(btVector3(gravity.x, gravity.y, gravity.z));
 }
 
+inline void PhysicsRigidBody::setKinematic(bool kinematic)
+{
+    if (kinematic)
+    {
+        _body->setCollisionFlags(_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
+        _body->setActivationState(DISABLE_DEACTIVATION);
+    }
+    else
+    {
+        _body->setCollisionFlags(_body->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT);
+        _body->setActivationState(ACTIVE_TAG);
+    }
+}
+
 inline void PhysicsRigidBody::setLinearVelocity(const Vector3& velocity)
 {
     _body->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));