소스 검색

Merge pull request #309 from blackberry-gaming/next-sgrenier

Next sgrenier
Steve Grenier 13 년 전
부모
커밋
da04297a07

+ 13 - 0
gameplay/src/Animation.cpp

@@ -146,6 +146,19 @@ AnimationClip* Animation::getClip(const char* id)
     }
     }
 }
 }
 
 
+AnimationClip* Animation::getClip(unsigned int index) const
+{
+    if (_clips)
+        return _clips->at(index);
+
+    return NULL;
+}
+
+unsigned int Animation::getClipCount() const
+{
+    return _clips ? _clips->size() : 0;
+}
+
 void Animation::play(const char* clipId)
 void Animation::play(const char* clipId)
 {
 {
     // If id is NULL, play the default clip.
     // If id is NULL, play the default clip.

+ 12 - 0
gameplay/src/Animation.h

@@ -66,6 +66,18 @@ public:
      * @return The AnimationClip with the specified ID; NULL if an AnimationClip with the given ID is not found.
      * @return The AnimationClip with the specified ID; NULL if an AnimationClip with the given ID is not found.
      */
      */
     AnimationClip* getClip(const char* clipId = NULL);
     AnimationClip* getClip(const char* clipId = NULL);
+
+    /**
+     * Returns the AnimationClip at the given index.
+     *
+     * @param index Index of the clip to return.
+     */
+    AnimationClip* getClip(unsigned int index) const;
+
+    /**
+     * Returns the number of animation clips in this animation.
+     */
+    unsigned int getClipCount() const;
     
     
     /**
     /**
      * Plays the AnimationClip with the specified name. 
      * Plays the AnimationClip with the specified name. 

+ 6 - 6
gameplay/src/Matrix.cpp

@@ -554,18 +554,18 @@ void Matrix::getLeftVector(Vector3* dst) const
 {
 {
     assert(dst);
     assert(dst);
 
 
-    dst->x = -m[0];
-    dst->y = -m[1];
-    dst->z = -m[2];
+    dst->x = m[0];
+    dst->y = m[1];
+    dst->z = m[2];
 }
 }
 
 
 void Matrix::getRightVector(Vector3* dst) const
 void Matrix::getRightVector(Vector3* dst) const
 {
 {
     assert(dst);
     assert(dst);
 
 
-    dst->x = m[0];
-    dst->y = m[1];
-    dst->z = m[2];
+    dst->x = -m[0];
+    dst->y = -m[1];
+    dst->z = -m[2];
 }
 }
 
 
 void Matrix::getForwardVector(Vector3* dst) const
 void Matrix::getForwardVector(Vector3* dst) const

+ 18 - 4
gameplay/src/Node.cpp

@@ -15,6 +15,7 @@
 // Node property flags
 // Node property flags
 #define NODE_FLAG_VISIBLE 1
 #define NODE_FLAG_VISIBLE 1
 #define NODE_FLAG_TRANSPARENT 2
 #define NODE_FLAG_TRANSPARENT 2
+#define NODE_FLAG_DYNAMIC 4
 
 
 namespace gameplay
 namespace gameplay
 {
 {
@@ -235,6 +236,19 @@ void Node::setTransparent(bool transparent)
         _nodeFlags &= ~NODE_FLAG_TRANSPARENT;
         _nodeFlags &= ~NODE_FLAG_TRANSPARENT;
 }
 }
 
 
+bool Node::isDynamic() const
+{
+    return ((_nodeFlags & NODE_FLAG_DYNAMIC) == NODE_FLAG_DYNAMIC);
+}
+
+void Node::setDynamic(bool dynamic)
+{
+    if (dynamic)
+        _nodeFlags |= NODE_FLAG_DYNAMIC;
+    else
+        _nodeFlags &= ~NODE_FLAG_DYNAMIC;
+}
+
 void* Node::getUserPointer() const
 void* Node::getUserPointer() const
 {
 {
     return (_userData ? _userData->pointer : NULL);
     return (_userData ? _userData->pointer : NULL);
@@ -1004,8 +1018,8 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
     // Check if the properties is valid.
     // Check if the properties is valid.
     if (!properties || 
     if (!properties || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
-        strcmp(properties->getNamespace(), "ghost") == 0 || 
-        strcmp(properties->getNamespace(), "rigidbody") == 0))
+        strcmp(properties->getNamespace(), "ghostObject") == 0 || 
+        strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
     {
         WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
         WARN("Failed to load collision object from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
         return NULL;
         return NULL;
@@ -1015,11 +1029,11 @@ PhysicsCollisionObject* Node::setCollisionObject(Properties* properties)
     {
     {
         _collisionObject = PhysicsCharacter::create(this, properties);
         _collisionObject = PhysicsCharacter::create(this, properties);
     }
     }
-    else if (strcmp(properties->getNamespace(), "ghost") == 0)
+    else if (strcmp(properties->getNamespace(), "ghostObject") == 0)
     {
     {
         _collisionObject = PhysicsGhostObject::create(this, properties);
         _collisionObject = PhysicsGhostObject::create(this, properties);
     }
     }
-    else if (strcmp(properties->getNamespace(), "rigidbody") == 0)
+    else if (strcmp(properties->getNamespace(), "rigidBody") == 0)
     {
     {
         _collisionObject = PhysicsRigidBody::create(this, properties);
         _collisionObject = PhysicsRigidBody::create(this, properties);
     }
     }

+ 20 - 0
gameplay/src/Node.h

@@ -148,6 +148,26 @@ public:
      */
      */
     void setTransparent(bool transparent);
     void setTransparent(bool transparent);
 
 
+    /**
+     * Returns whether this node is dynamic.
+     *
+     * The dynamic propery can be used to flag nodes as being non-static.
+     * This can be useful for modifying behavior or rendering/material
+     * logic at runtime for static vs dynamic (moving) objects. An
+     * example would be determing whether to use static or  dyanmic
+     * lighting materials for node models during loading.
+     *
+     * @return Whether this node is dynamic (false by default).
+     */
+    bool isDynamic() const;
+
+    /**
+     * Sets whether this node is dynamic.
+     *
+     * @param dynamic Whether the node is dynamic.
+     */
+    void setDynamic(bool dynamic);
+
     /**
     /**
      * Returns the user pointer for this node.
      * Returns the user pointer for this node.
      *
      *

+ 45 - 165
gameplay/src/PhysicsCharacter.cpp

@@ -59,9 +59,9 @@ protected:
 
 
 PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Definition& shape, float mass)
 PhysicsCharacter::PhysicsCharacter(Node* node, const PhysicsCollisionShape::Definition& shape, float mass)
     : PhysicsGhostObject(node, shape), _moveVelocity(0,0,0), _forwardVelocity(0.0f), _rightVelocity(0.0f),
     : PhysicsGhostObject(node, shape), _moveVelocity(0,0,0), _forwardVelocity(0.0f), _rightVelocity(0.0f),
-    _fallVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
-    _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0),
-    _stepHeight(0.1f), _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
+    _verticalVelocity(0, 0, 0), _currentVelocity(0,0,0), _normalizedVelocity(0,0,0),
+    _colliding(false), _collisionNormal(0,0,0), _currentPosition(0,0,0), _stepHeight(0.1f),
+    _slopeAngle(0.0f), _cosSlopeAngle(0.0f), _physicsEnabled(true), _mass(mass)
 {
 {
     setMaxSlopeAngle(45.0f);
     setMaxSlopeAngle(45.0f);
 
 
@@ -99,6 +99,8 @@ PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
     // Load the character's parameters.
     // Load the character's parameters.
     properties->rewind();
     properties->rewind();
     float mass = 1.0f;
     float mass = 1.0f;
+    float maxStepHeight = 0.1f;
+    float maxSlopeAngle = 0.0f;
     const char* name = NULL;
     const char* name = NULL;
     while ((name = properties->getNextProperty()) != NULL)
     while ((name = properties->getNextProperty()) != NULL)
     {
     {
@@ -106,10 +108,20 @@ PhysicsCharacter* PhysicsCharacter::create(Node* node, Properties* properties)
         {
         {
             mass = properties->getFloat();
             mass = properties->getFloat();
         }
         }
+        else if (strcmp(name, "maxStepHeight") == 0)
+        {
+            maxStepHeight = properties->getFloat();
+        }
+        else if (strcmp(name, "maxSlopeAngle") == 0)
+        {
+            maxSlopeAngle = properties->getFloat();
+        }
     }
     }
 
 
     // Create the physics character.
     // Create the physics character.
     PhysicsCharacter* character = new PhysicsCharacter(node, *shape, mass);
     PhysicsCharacter* character = new PhysicsCharacter(node, *shape, mass);
+    character->setMaxStepHeight(maxStepHeight);
+    character->setMaxSlopeAngle(maxSlopeAngle);
     SAFE_DELETE(shape);
     SAFE_DELETE(shape);
 
 
     return character;
     return character;
@@ -156,120 +168,6 @@ void PhysicsCharacter::setMaxSlopeAngle(float angle)
     _cosSlopeAngle = std::cos(MATH_DEG_TO_RAD(angle));
     _cosSlopeAngle = std::cos(MATH_DEG_TO_RAD(angle));
 }
 }
 
 
-void PhysicsCharacter::addAnimation(const char* name, AnimationClip* clip, float moveSpeed)
-{
-    CharacterAnimation a;
-    a.name = name;
-    a.clip = clip;
-    a.moveSpeed = moveSpeed;
-    a.layer = 0;
-    a.playing = false;
-    a.animationFlags = ANIMATION_STOP;
-    a.prev = NULL;
-    _animations[name] = a;
-}
-
-AnimationClip* PhysicsCharacter::getAnimation(const char* name)
-{
-    if (name)
-    {
-        // Lookup the specified animation
-        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
-        if (aitr != _animations.end())
-        {
-            return aitr->second.clip;
-        }
-    }
-    return NULL;
-}
-
-void PhysicsCharacter::play(const char* name, AnimationFlags flags, float speed, unsigned int blendDuration, unsigned int layer)
-{
-    CharacterAnimation* animation = NULL;
-    if (name)
-    {
-        // Lookup the specified animation
-        std::map<const char*, CharacterAnimation>::iterator aitr = _animations.find(name);
-        if (aitr == _animations.end())
-            return; // invalid animation name
-
-        animation = &(aitr->second);
-
-        // Set animation flags
-        animation->clip->setRepeatCount(flags & ANIMATION_REPEAT ? AnimationClip::REPEAT_INDEFINITE : 1);
-        animation->clip->setSpeed(speed);
-        animation->animationFlags = flags;
-        animation->layer = layer;
-        animation->blendDuration = blendDuration;
-        animation->prev = NULL;
-
-        // If the animation is already marked playing, do nothing more
-        if (animation->playing)
-            return;
-    }
-
-    play(animation, layer);
-}
-
-void PhysicsCharacter::play(CharacterAnimation* animation, unsigned int layer)
-{
-    // Is there already an animation playing on this layer?
-    std::map<unsigned int, CharacterAnimation*>::iterator litr = _layers.find(layer);
-    CharacterAnimation* prevAnimation = (litr == _layers.end() ? NULL : litr->second);
-    if (prevAnimation && prevAnimation->playing)
-    {
-        // An animation is already playing on this layer
-        if (animation)
-        {
-            if (animation->animationFlags == ANIMATION_RESUME)
-                animation->prev = prevAnimation;
-
-            if (animation->blendDuration > 0L)
-            {
-                // Crossfade from current animation into the new one
-                prevAnimation->clip->crossFade(animation->clip, animation->blendDuration);
-            }
-            else
-            {
-                // Stop the previous animation (no blending)
-                prevAnimation->clip->stop();
-
-                // Play the new animation
-                animation->clip->play();
-            }
-        }
-        else
-        {
-            // No new animaton specified - stop current animation on this layer
-            prevAnimation->clip->stop();
-        }
-
-        prevAnimation->playing = false;
-    }
-    else if (animation)
-    {
-        // No animations currently playing - just play the new one
-        animation->clip->play();
-    }
-
-    // Update animaton and layers
-    if (animation)
-    {
-        animation->playing = true;
-
-        // Update layer to point to the new animation
-        if (litr != _layers.end())
-            litr->second = animation;
-        else
-            _layers[layer] = animation;
-    }
-    else if (litr != _layers.end())
-    {
-        // Remove layer sine we stopped the animation previously on it
-        _layers.erase(litr);
-    }
-}
-
 void PhysicsCharacter::setVelocity(const Vector3& velocity)
 void PhysicsCharacter::setVelocity(const Vector3& velocity)
 {
 {
     _moveVelocity.setValue(velocity.x, velocity.y, velocity.z);
     _moveVelocity.setValue(velocity.x, velocity.y, velocity.z);
@@ -307,7 +205,20 @@ void PhysicsCharacter::setRightVelocity(float velocity)
 
 
 void PhysicsCharacter::jump(float height)
 void PhysicsCharacter::jump(float height)
 {
 {
-    // TODO
+    // TODO: Add support for different jump modes (i.e. double jump, changing direction in air, holding down jump button for extra height, etc)
+    if (!_verticalVelocity.isZero())
+        return;
+
+    // v = sqrt(v0^2 + 2 a s)
+    //  v0 == initial velocity (zero for jumping)
+    //  a == acceleration (inverse gravity)
+    //  s == linear displacement (height)
+    Vector3 jumpVelocity = -Game::getInstance()->getPhysicsController()->getGravity() * height * 2.0f;
+    jumpVelocity.set(
+        jumpVelocity.x == 0 ? 0 : std::sqrt(jumpVelocity.x),
+        jumpVelocity.y == 0 ? 0 : std::sqrt(jumpVelocity.y),
+        jumpVelocity.z == 0 ? 0 : std::sqrt(jumpVelocity.z));
+    _verticalVelocity += BV(jumpVelocity);
 }
 }
 
 
 void PhysicsCharacter::updateCurrentVelocity()
 void PhysicsCharacter::updateCurrentVelocity()
@@ -403,58 +314,26 @@ void PhysicsCharacter::updateAction(btCollisionWorld* collisionWorld, btScalar d
 
 
 void PhysicsCharacter::stepUp(btCollisionWorld* collisionWorld, btScalar time)
 void PhysicsCharacter::stepUp(btCollisionWorld* collisionWorld, btScalar time)
 {
 {
-    // Note: btKinematicCharacterController implements this by always just setting
-    // target position to currentPosition.y + stepHeight, and then checking for collisions.
-    // Don't let the character move up if it hits the ceiling (or something above).
-    // Do this WITHOUT using time in the calculation - this way you are always guarnateed
-    // to step over a step that is stepHeight high.
-    // 
-    // Note that stepDown() will be called right after this, so the character will move back
-    // down to collide with the ground so that he smoothly steps up stairs.
-    _currentPosition += btVector3(0, _stepHeight, 0);
-}
+    btVector3 targetPosition(_currentPosition);
 
 
-void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
-{
-    // Process currently playing movements+animations and determine final move location
-    float animationMoveSpeed = 0.0f;
-    unsigned int animationCount = 0;
-    for (std::map<unsigned int, CharacterAnimation*>::iterator itr = _layers.begin(); itr != _layers.end(); ++itr)
+    if (_verticalVelocity.isZero())
     {
     {
-        CharacterAnimation* animation = itr->second;
-
-        // If the animation is not playing, ignore it
-        if (!animation->playing)
-            continue;
-
-        AnimationClip* clip = animation->clip;
-
-        // Did the clip finish playing (but we still have it marked playing)?
-        if (!clip->isPlaying())
-        {
-            // If the animaton was flaged the ANIMATION_RESUME bit, start the previously playing animation
-            if ((animation->animationFlags == ANIMATION_RESUME) && animation->prev)
-            {
-                play(animation->prev, animation->prev->layer);
-            }
-
-            animation->playing = false;
+        // Simply increase our poisiton by step height to enable us
+        // to smoothly move over steps.
+        targetPosition += btVector3(0, _stepHeight, 0);
+    }
 
 
-            continue;
-        }
+    // TODO: Convex sweep test to ensure we didn't hit anything during the step up.
 
 
-        animationMoveSpeed += animation->moveSpeed;
-        ++animationCount;
-    }
+    _currentPosition = targetPosition;
+}
 
 
+void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, float time)
+{
     updateCurrentVelocity();
     updateCurrentVelocity();
 
 
     // Calculate final velocity
     // Calculate final velocity
     btVector3 velocity(_currentVelocity);
     btVector3 velocity(_currentVelocity);
-    if (animationCount > 0)
-    {
-        velocity *= animationMoveSpeed;
-    }
     velocity *= time; // since velocity is in meters per second
     velocity *= time; // since velocity is in meters per second
 
 
     if (velocity.isZero())
     if (velocity.isZero())
@@ -542,11 +421,12 @@ void PhysicsCharacter::stepForwardAndStrafe(btCollisionWorld* collisionWorld, fl
 
 
 void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
 void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
 {
 {
-    // Contribute basic gravity to fall velocity.
+    // Contribute gravity to vertical velocity.
     btVector3 gravity = Game::getInstance()->getPhysicsController()->_world->getGravity();
     btVector3 gravity = Game::getInstance()->getPhysicsController()->_world->getGravity();
-    _fallVelocity += (gravity * time);
+    _verticalVelocity += (gravity * time);
 
 
-    btVector3 targetPosition = _currentPosition + (_fallVelocity * time);
+    // Compute new position from vertical velocity.
+    btVector3 targetPosition = _currentPosition + (_verticalVelocity * time);
     targetPosition -= btVector3(0, _stepHeight, 0);
     targetPosition -= btVector3(0, _stepHeight, 0);
 
 
     // Perform a convex sweep test between current and target position
     // Perform a convex sweep test between current and target position
@@ -569,7 +449,7 @@ void PhysicsCharacter::stepDown(btCollisionWorld* collisionWorld, btScalar time)
         _currentPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
         _currentPosition.setInterpolate3(_currentPosition, targetPosition, callback.m_closestHitFraction);
 
 
         // Zero out fall velocity when we hit an object
         // Zero out fall velocity when we hit an object
-        _fallVelocity.setZero();
+        _verticalVelocity.setZero();
     }
     }
     else
     else
     {
     {

+ 3 - 111
gameplay/src/PhysicsCharacter.h

@@ -18,10 +18,6 @@ namespace gameplay
  * PhysicsCharacter class. This results in a more responsive and typical game
  * PhysicsCharacter class. This results in a more responsive and typical game
  * character than would be possible if trying to move a character by applying
  * character than would be possible if trying to move a character by applying
  * physical simulation with forces.
  * physical simulation with forces.
- *
- * This class can also be used to control animations for a character. Animation
- * clips can be setup for typical character animations, such as walk, run, jump,
- * etc; and the controller will handle blending between these animations as needed.
  */
  */
 class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 {
 {
@@ -29,27 +25,6 @@ class PhysicsCharacter : public PhysicsGhostObject, public btActionInterface
 
 
 public:
 public:
 
 
-    /**
-     * Flags for controlling how a character animation is played back.
-     */
-    enum AnimationFlags
-    {
-        /**
-         * Plays an animation once and then stops.
-         */
-        ANIMATION_STOP,
-
-        /**
-         * Play an animation once and then resumes the previous playing animation.
-         */
-        ANIMATION_RESUME,
-
-        /**
-         * Plays an animation and repeats it indefinitely.
-         */
-         ANIMATION_REPEAT
-    };
-
     /**
     /**
      * @see PhysicsCollisionObject#getType
      * @see PhysicsCollisionObject#getType
      */
      */
@@ -110,74 +85,13 @@ public:
      */
      */
     void setMaxSlopeAngle(float angle);
     void setMaxSlopeAngle(float angle);
 
 
-    /**
-     * Configures a new animation for this character.
-     *
-     * This method registers an animation for the character, with an associated movement speed.
-     * The moveSpeed specifies how fast the character moves while the animation is playing.
-     * The final velocity of the character is the product of the current move velocity and
-     * the currently playing animation(s) moveSpeed.
-     *
-     * @param name Name of the animation.
-     * @param animationClip Animation clip associated with the new character animation.
-     * @param moveSpeed Base movement speed (meters per second) associated with the animation.
-     */
-    void addAnimation(const char* name, AnimationClip* animationClip, float moveSpeed);
-
-    /**
-     * Returns the animation with the specified name.
-     *
-     * @return The specified animation clip.
-     */
-    AnimationClip* getAnimation(const char* name);
-
-    /**
-     * Plays the specified animation.
-     *
-     * There are some limiations and considerations that should be ponited out when
-     * playing animations:
-     * <li>You should avoid playing multiple animations concurrently that have the same target.
-     * For example, two animations targetting the character's joints should not be played 
-     * concurrently, but it is fine to play one animation that targets the joints and another
-     * that targets the character's Node.
-     * <li>When playing an animation that targets the transform of the character's Node
-     * (such as a motion path animation), the character's velocity vector should be set to
-     * Vector3::zero() so that the PhysicsCharacter stops applying motion directly
-     * and instead relies on the motion animation to control the character.
-     *
-     * The optional animation layer can be used to group animations on separate layers.
-     * Each animation layer can have at most one active animation. Playing multiple
-     * animations concurrently can be achieved by putting the different animations
-     * on separate layers. For example, a motion path animation that targets the
-     * character's Node can be put on one layer, while a running animation that targets
-     * a character's Joints can be put on a separate layer. This allows a character's
-     * movement to be animated at the same time as the run animation is playing.
-     *
-     * @param name Animation name, or NULL to stop all character animations on the given layer.
-     * @param flags Animation flags from the AnimationFlags enumeration.
-     * @param animationSpeed Optional animation speed (default is 1.0).
-     * @param blendDuration Optional number of milliseconds to crossfade between the
-     *      currently playing animation on the given layer and the new animation.
-     * @param layer Optional animation layer.
-     */
-    void play(const char* name, AnimationFlags flags, float animationSpeed = 1.0f, unsigned int blendDuration = 0, unsigned int layer = 0);
-
     /**
     /**
      * Sets the velocity of the character.
      * Sets the velocity of the character.
      *
      *
      * Calling this function sets the velocity (speed and direction) for the character.
      * Calling this function sets the velocity (speed and direction) for the character.
      * The velocity is maintained until this method is called again. The final velocity
      * The velocity is maintained until this method is called again. The final velocity
-     * of the character is determined by product of the current velocity vector(s)
-     * and the current character animation's move speed. Therefore, specifying a
-     * normalized (unit-length) velocity vector results in the character speed being
-     * controled entirely by the current animation's velocity; whereas the speed of
-     * the character can be augmented by modifying the magnitude of the velocity vector.
-
-     * Note that a zero velocity vector and/or a zero animation move speed will
-     * result in no character movement (the character will be stationary). A zero
-     * velocity vector should be used when playing an animation that targets the
-     * character's transform directly (such as a motion path animation), since these
-     * animations will overwrite any transformations on the character's node.
+     * of the character is determined by product of the current velocity, right and
+     * forward vectors.
      *
      *
      * @param velocity Movement velocity.
      * @param velocity Movement velocity.
      */
      */
@@ -219,9 +133,6 @@ public:
      * The forward velocity is defined by the character's current orientation
      * The forward velocity is defined by the character's current orientation
      * (it is the forward vector from the character's current world transform).
      * (it is the forward vector from the character's current world transform).
      *
      *
-     * The specified velocity acts as a multiplier on the currently playing animation's
-     * velocity (or, if there is no animation playing, it directly impacts velocity).
-     *
      * Note that a negative velocity (i.e. -1.0f) will move the character backwards.
      * Note that a negative velocity (i.e. -1.0f) will move the character backwards.
      *
      *
      * @param velocity Optional velocity modifier.
      * @param velocity Optional velocity modifier.
@@ -234,9 +145,6 @@ public:
      * The right velocity is defined by the character's current orientation
      * The right velocity is defined by the character's current orientation
      * (it is the right vector from the character's current world transform).
      * (it is the right vector from the character's current world transform).
      *
      *
-     * The specified velocity acts as a multiplier on the currently playing animation's
-     * velocity (or, if there is no animation playing, it directly impacts velocity).
-     *
      * Note that a negative velocity (i.e. -1.0f) will move the character left.
      * Note that a negative velocity (i.e. -1.0f) will move the character left.
      *
      *
      * @param velocity Optional velocity modifier.
      * @param velocity Optional velocity modifier.
@@ -269,18 +177,6 @@ protected:
 
 
 private:
 private:
 
 
-    struct CharacterAnimation
-    {
-        const char* name;
-        AnimationClip* clip;
-        float moveSpeed;
-        unsigned int layer;
-        bool playing;
-        AnimationFlags animationFlags;
-        unsigned int blendDuration;
-        CharacterAnimation* prev;
-    };
-
     /**
     /**
      * Creates a new PhysicsCharacter.
      * Creates a new PhysicsCharacter.
      *
      *
@@ -311,8 +207,6 @@ private:
 
 
     void updateCurrentVelocity();
     void updateCurrentVelocity();
 
 
-    void play(CharacterAnimation* animation, unsigned int layer);
-
     void stepUp(btCollisionWorld* collisionWorld, btScalar time);
     void stepUp(btCollisionWorld* collisionWorld, btScalar time);
 
 
     void stepDown(btCollisionWorld* collisionWorld, btScalar time);
     void stepDown(btCollisionWorld* collisionWorld, btScalar time);
@@ -326,14 +220,12 @@ private:
     btVector3 _moveVelocity;
     btVector3 _moveVelocity;
     float _forwardVelocity;
     float _forwardVelocity;
     float _rightVelocity;
     float _rightVelocity;
-    btVector3 _fallVelocity;
+    btVector3 _verticalVelocity;
     btVector3 _currentVelocity;
     btVector3 _currentVelocity;
     btVector3 _normalizedVelocity;
     btVector3 _normalizedVelocity;
     bool _colliding;
     bool _colliding;
     btVector3 _collisionNormal;
     btVector3 _collisionNormal;
     btVector3 _currentPosition;
     btVector3 _currentPosition;
-    std::map<const char*, CharacterAnimation> _animations;
-    std::map<unsigned int, CharacterAnimation*> _layers;
     btManifoldArray _manifoldArray;
     btManifoldArray _manifoldArray;
     float _stepHeight;
     float _stepHeight;
     float _slopeAngle;
     float _slopeAngle;

+ 2 - 2
gameplay/src/PhysicsCollisionShape.cpp

@@ -121,8 +121,8 @@ PhysicsCollisionShape::Definition* PhysicsCollisionShape::Definition::create(Nod
     assert(properties);
     assert(properties);
     if (!properties || 
     if (!properties || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
         !(strcmp(properties->getNamespace(), "character") == 0 || 
-        strcmp(properties->getNamespace(), "ghost") == 0 || 
-        strcmp(properties->getNamespace(), "rigidbody") == 0))
+        strcmp(properties->getNamespace(), "ghostObject") == 0 || 
+        strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
     {
         WARN("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
         WARN("Failed to load physics collision shape from properties object: must be non-null object and have namespace equal to \'character\', \'ghost\', or \'rigidbody\'.");
         return NULL;
         return NULL;

+ 1 - 1
gameplay/src/PhysicsGhostObject.cpp

@@ -43,7 +43,7 @@ PhysicsGhostObject* PhysicsGhostObject::create(Node* node, Properties* propertie
 {
 {
     // Check if the properties is valid and has a valid namespace.
     // Check if the properties is valid and has a valid namespace.
     assert(properties);
     assert(properties);
-    if (!properties || !(strcmp(properties->getNamespace(), "ghost") == 0))
+    if (!properties || !(strcmp(properties->getNamespace(), "ghostObject") == 0))
     {
     {
         WARN("Failed to load ghost object from properties object: must be non-null object and have namespace equal to \'ghost\'.");
         WARN("Failed to load ghost object from properties object: must be non-null object and have namespace equal to \'ghost\'.");
         return NULL;
         return NULL;

+ 2 - 2
gameplay/src/PhysicsRigidBody.cpp

@@ -145,9 +145,9 @@ PhysicsRigidBody* PhysicsRigidBody::create(Node* node, Properties* properties)
 {
 {
     // Check if the properties is valid and has a valid namespace.
     // Check if the properties is valid and has a valid namespace.
     assert(properties);
     assert(properties);
-    if (!properties || !(strcmp(properties->getNamespace(), "rigidbody") == 0))
+    if (!properties || !(strcmp(properties->getNamespace(), "rigidBody") == 0))
     {
     {
-        WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidbody\'.");
+        WARN("Failed to load rigid body from properties object: must be non-null object and have namespace equal to \'rigidBody\'.");
         return NULL;
         return NULL;
     }
     }
 
 

+ 25 - 15
gameplay/src/SceneLoader.cpp

@@ -61,8 +61,9 @@ Scene* SceneLoader::load(const char* filePath)
         SceneNodeProperty::ROTATE |
         SceneNodeProperty::ROTATE |
         SceneNodeProperty::SCALE |
         SceneNodeProperty::SCALE |
         SceneNodeProperty::TRANSLATE | 
         SceneNodeProperty::TRANSLATE | 
-        SceneNodeProperty::TRANSPARENT);
-    applyNodeProperties(scene, sceneProperties, SceneNodeProperty::CHARACTER | SceneNodeProperty::GHOST | SceneNodeProperty::RIGIDBODY);
+        SceneNodeProperty::TRANSPARENT |
+        SceneNodeProperty::DYNAMIC);
+    applyNodeProperties(scene, sceneProperties, SceneNodeProperty::CHARACTER | SceneNodeProperty::GHOSTOBJECT | SceneNodeProperty::RIGIDBODY);
     createAnimations(scene);
     createAnimations(scene);
 
 
     // Find the physics properties object.
     // Find the physics properties object.
@@ -195,7 +196,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
         snp._type == SceneNodeProperty::MATERIAL ||
         snp._type == SceneNodeProperty::MATERIAL ||
         snp._type == SceneNodeProperty::PARTICLE ||
         snp._type == SceneNodeProperty::PARTICLE ||
         snp._type == SceneNodeProperty::CHARACTER ||
         snp._type == SceneNodeProperty::CHARACTER ||
-        snp._type == SceneNodeProperty::GHOST ||
+        snp._type == SceneNodeProperty::GHOSTOBJECT ||
         snp._type == SceneNodeProperty::RIGIDBODY)
         snp._type == SceneNodeProperty::RIGIDBODY)
     {
     {
         // Check to make sure the referenced properties object was loaded properly.
         // Check to make sure the referenced properties object was loaded properly.
@@ -250,7 +251,7 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             break;
             break;
         }
         }
         case SceneNodeProperty::CHARACTER:
         case SceneNodeProperty::CHARACTER:
-        case SceneNodeProperty::GHOST:
+        case SceneNodeProperty::GHOSTOBJECT:
         case SceneNodeProperty::RIGIDBODY:
         case SceneNodeProperty::RIGIDBODY:
         {
         {
             // Check to make sure the referenced properties object was loaded properly.
             // Check to make sure the referenced properties object was loaded properly.
@@ -283,20 +284,20 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             {
             {
                 WARN_VARG("Attempting to set a 'character' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
                 WARN_VARG("Attempting to set a 'character' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
             }
-            else if (snp._type == SceneNodeProperty::GHOST && strcmp(p->getNamespace(), "ghost") != 0)
+            else if (snp._type == SceneNodeProperty::GHOSTOBJECT && strcmp(p->getNamespace(), "ghostObject") != 0)
             {
             {
-                WARN_VARG("Attempting to set a 'ghost' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
+                WARN_VARG("Attempting to set a 'ghostObject' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
             }
-            else if (snp._type == SceneNodeProperty::RIGIDBODY && strcmp(p->getNamespace(), "rigidbody") != 0)
+            else if (snp._type == SceneNodeProperty::RIGIDBODY && strcmp(p->getNamespace(), "rigidBody") != 0)
             {
             {
-                WARN_VARG("Attempting to set a 'rigidbody' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
+                WARN_VARG("Attempting to set a 'rigidBody' (physics collision object attribute) on a node using a '%s' definition.", p->getNamespace());
             }
             }
             else
             else
             {
             {
                 // If the scene file specifies a rigid body model, use it for creating the collision object.
                 // If the scene file specifies a rigid body model, use it for creating the collision object.
                 Properties* np = sceneProperties->getNamespace(sceneNode._nodeID);
                 Properties* np = sceneProperties->getNamespace(sceneNode._nodeID);
                 const char* name = NULL;
                 const char* name = NULL;
-                if (np && (name = np->getString("rigidbodymodel")))
+                if (np && (name = np->getString("rigidBodyModel")))
                 {
                 {
                     Node* modelNode = node->getScene()->findNode(name);
                     Node* modelNode = node->getScene()->findNode(name);
                     if (!modelNode)
                     if (!modelNode)
@@ -307,14 +308,14 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
                             WARN_VARG("Node '%s' does not have a model; attempting to use its model for collision object creation.", name);
                             WARN_VARG("Node '%s' does not have a model; attempting to use its model for collision object creation.", name);
                         else
                         else
                         {
                         {
-                            // Temporarily set rigidbody model on model so it's used during collision object creation.
+                            // Temporarily set rigidBody model on model so it's used during collision object creation.
                             Model* model = node->getModel();
                             Model* model = node->getModel();
                             assert(model);
                             assert(model);
                         
                         
                             // Up ref count to prevent node from releasing the model when we swap it.
                             // Up ref count to prevent node from releasing the model when we swap it.
                             model->addRef(); 
                             model->addRef(); 
                         
                         
-                            // Create collision object with new rigidbodymodel set.
+                            // Create collision object with new rigidBodyModel set.
                             node->setModel(modelNode->getModel());
                             node->setModel(modelNode->getModel());
                             node->setCollisionObject(p);
                             node->setCollisionObject(p);
 
 
@@ -370,6 +371,11 @@ void SceneLoader::applyNodeProperty(SceneNode& sceneNode, Node* node, const Prop
             node->setTransparent(true);
             node->setTransparent(true);
             break;
             break;
         }
         }
+        case SceneNodeProperty::DYNAMIC:
+        {
+            node->setDynamic(true);
+            break;
+        }
         default:
         default:
             WARN_VARG("Unsupported node property type: %d.", snp._type);
             WARN_VARG("Unsupported node property type: %d.", snp._type);
             break;
             break;
@@ -554,15 +560,15 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::CHARACTER, ns->getString());
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::CHARACTER, ns->getString());
                 }
                 }
-                else if (strcmp(name, "ghost") == 0)
+                else if (strcmp(name, "ghostObject") == 0)
                 {
                 {
-                    addSceneNodeProperty(sceneNode, SceneNodeProperty::GHOST, ns->getString());
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::GHOSTOBJECT, ns->getString());
                 }
                 }
-                else if (strcmp(name, "rigidbody") == 0)
+                else if (strcmp(name, "rigidBody") == 0)
                 {
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::RIGIDBODY, ns->getString());
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::RIGIDBODY, ns->getString());
                 }
                 }
-                else if (strcmp(name, "rigidbodymodel") == 0)
+                else if (strcmp(name, "rigidBodyModel") == 0)
                 {
                 {
                     // Ignore this for now. We process this when we do rigid body creation.
                     // Ignore this for now. We process this when we do rigid body creation.
                 }
                 }
@@ -582,6 +588,10 @@ void SceneLoader::buildReferenceTables(Properties* sceneProperties)
                 {
                 {
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSPARENT);
                     addSceneNodeProperty(sceneNode, SceneNodeProperty::TRANSPARENT);
                 }
                 }
+                else if (strcmp(name, "dynamic") == 0)
+                {
+                    addSceneNodeProperty(sceneNode, SceneNodeProperty::DYNAMIC);
+                }
                 else
                 else
                 {
                 {
                     WARN_VARG("Unsupported node property: %s = %s", name, ns->getString());
                     WARN_VARG("Unsupported node property: %s = %s", name, ns->getString());

+ 3 - 2
gameplay/src/SceneLoader.h

@@ -46,13 +46,14 @@ private:
             MATERIAL = 2,
             MATERIAL = 2,
             PARTICLE = 4,
             PARTICLE = 4,
             CHARACTER = 8,
             CHARACTER = 8,
-            GHOST = 16,
+            GHOSTOBJECT = 16,
             RIGIDBODY = 32,
             RIGIDBODY = 32,
             TRANSLATE = 64,
             TRANSLATE = 64,
             ROTATE = 128,
             ROTATE = 128,
             SCALE = 256,
             SCALE = 256,
             URL = 512,
             URL = 512,
-            TRANSPARENT = 1024
+            TRANSPARENT = 1024,
+            DYNAMIC = 2048
         };
         };
 
 
         SceneNodeProperty(Type type, std::string file, std::string id, int index) : _type(type), _file(file), _id(id), _index(index) { }
         SceneNodeProperty(Type type, std::string file, std::string id, int index) : _type(type), _file(file), _id(id), _index(index) { }