Procházet zdrojové kódy

Fixes bug in animation blending of independent values.
Code cleanup.
Adds rotate(float qx, float qy, float qz, float qw) to Transform class.

Kieran Cunney před 14 roky
rodič
revize
651381eb67

+ 9 - 156
gameplay/src/AnimationClip.cpp

@@ -198,7 +198,7 @@ void AnimationClip::addEndListener(AnimationClip::Listener* listener)
     _endListeners->push_back(listener);
 }
 
-bool AnimationClip::update(unsigned long elapsedTime)
+bool AnimationClip::update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets)
 {
     float speed = _speed;
     if (!_isPlaying)
@@ -295,146 +295,16 @@ bool AnimationClip::update(unsigned long elapsedTime)
         target = channel->_target;
         value = _values[i];
 
-        // Get the current value.
-        target->getAnimationPropertyValue(channel->_propertyId, value);
+        // If the target's _bitFlag is clear, we can assume that this is the first
+        // animation channel to act on the target and we can add the target to the list of
+        // active targets stored by the AnimationController.
+        if (target->_bitFlag == 0x00)
+            activeTargets->push_front(target);
 
-        bool isHighest = false;
-        // My channel priority has changed if my priority is greater than the active animation count.
-        if (!target->_highestPriority)
-        {
-            target->_highestPriority = channel;
-            value->_isFirstActing = true;
-        }
-
-        if (_blendWeight != 0.0f)
-        {
-            // Evaluate point on Curve.
-            channel->_curve->evaluate(percentComplete, value->_interpolatedValue);
-
-            if (!channel->_curve->_quaternionOffset)
-            {
-                if (value->_isFirstActing)
-                {
-                    unsigned int componentCount = value->_componentCount;
-                    for (unsigned int j = 0; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] = value->_interpolatedValue[j];
-                    }
-                }
-                else
-                {
-                    unsigned int componentCount = value->_componentCount;
-                    for (unsigned int j = 0; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] += value->_interpolatedValue[j];
-                    }
-                }
-            }
-            else
-            {   //We have Quaternions!!!
-                unsigned int quaternionOffset = *(channel->_curve->_quaternionOffset);
-                
-                if (value->_isFirstActing)
-                {
-                    unsigned int j = 0;
-                    for (; j < quaternionOffset; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] = value->_interpolatedValue[j];
-                    }
-
-                    // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
-                    Quaternion* interpolatedQuaternion = (Quaternion*) (value->_interpolatedValue + j);
-                    Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
-
-                    // If we have a blend weight, we apply it by slerping from the identity to our interpolated value at the given weight.
-                    if (_blendWeight != 1.0f)
-                        Quaternion::slerp(Quaternion::identity(), *interpolatedQuaternion, _blendWeight, interpolatedQuaternion);
-                    
-                    // Add in contribution.
-                    currentQuaternion->set(*interpolatedQuaternion);
-                    
-                    unsigned int componentCount = value->_componentCount;
-                    for (j += 4; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] = value->_interpolatedValue[j];
-                    }
-                }
-                else
-                {
-                    unsigned int j = 0;
-                    for (; j < quaternionOffset; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] += value->_interpolatedValue[j];
-                    }
-                    // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
-
-                    Quaternion* interpolatedQuaternion = (Quaternion*) (value->_interpolatedValue + j);
-                    Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
-
-                    // If we have a blend weight, we apply it by slerping from the identity to our interpolated value at the given weight.
-                    if (_blendWeight != 1.0f)
-                        Quaternion::slerp(Quaternion::identity(), *interpolatedQuaternion, _blendWeight, interpolatedQuaternion);
-                    
-                    // Add in contribution.
-                    currentQuaternion->multiply(*interpolatedQuaternion);
-                    
-                    unsigned int componentCount = value->_componentCount;
-                    for (j += 4; j < componentCount; j++)
-                    {
-                        if (_blendWeight != 1.0f)
-                            value->_interpolatedValue[j] *= _blendWeight;
-
-                        value->_currentValue[j] += value->_interpolatedValue[j];
-                    }
-                }
-            }
-        }
-        else if (value->_isFirstActing)
-        {
-            if (!channel->_curve->_quaternionOffset)
-            {
-                memset(value->_currentValue, 0.0f, value->_componentCount);
-            }
-            else
-            {
-                unsigned int quaternionOffset = *(channel->_curve->_quaternionOffset);
-                unsigned int j = 0;
-                for (; j < quaternionOffset; j++)
-                {
-                    value->_currentValue[j] = 0.0f;
-                }
-
-                // We are at the index for a quaternion component. Handle the next for components as a whole quaternion.
-                Quaternion* currentQuaternion = (Quaternion*) (value->_currentValue + j);
-
-                // Set it to identity.
-                currentQuaternion->setIdentity();
-                
-                unsigned int componentCount = value->_componentCount;
-                for (j += 4; j < componentCount; j++)
-                {
-                    value->_currentValue[j] = 0.0f;
-                }
-            }
-        }
-        
+        // Evaluate the point on Curve
+        channel->_curve->evaluate(percentComplete, value->_value);
         // Set the animation value on the target property.
-        target->setAnimationPropertyValue(channel->_propertyId, value);
+        target->setAnimationPropertyValue(channel->_propertyId, value, _blendWeight);
     }
 
     // When ended. Probably should move to it's own method so we can call it when the clip is ended early.
@@ -485,23 +355,6 @@ void AnimationClip::onBegin()
 
 void AnimationClip::onEnd()
 {
-    AnimationValue* value;
-    Animation::Channel* channel = NULL;
-    AnimationTarget* target = NULL;
-    unsigned int channelCount = _animation->_channels.size();
-    for (unsigned int i = 0; i < channelCount; i++)
-    {
-        value = _values[i];
-
-        if (value->_isFirstActing)
-        {
-            channel = _animation->_channels[i];
-            target = channel->_target;
-            target->_highestPriority = NULL;
-            value->_isFirstActing = false;
-        }
-    }
-
     _blendWeight = 1.0f;
     _timeStarted = 0;
 }

+ 1 - 1
gameplay/src/AnimationClip.h

@@ -215,7 +215,7 @@ private:
     /**
      * Updates the animation with the elapsed time.
      */
-    bool update(unsigned long elapsedTime);
+    bool update(unsigned long elapsedTime, std::list<AnimationTarget*>* activeTargets);
 
     /**
      * Handles when the AnimationClip begins.

+ 12 - 1
gameplay/src/AnimationController.cpp

@@ -333,11 +333,12 @@ void AnimationController::update(long elapsedTime)
     if (_state != RUNNING)
         return;
 
+    // Loop through running clips and call update() on them.
     std::list<AnimationClip*>::iterator clipIter = _runningClips.begin();
     while (clipIter != _runningClips.end())
     {
         AnimationClip* clip = (*clipIter);
-        if (clip->update(elapsedTime))
+        if (clip->update(elapsedTime, &_activeTargets))
         {
             SAFE_RELEASE(clip);
             clipIter = _runningClips.erase(clipIter);
@@ -347,6 +348,16 @@ void AnimationController::update(long elapsedTime)
             clipIter++;
         }
     }
+
+    // Loop through active AnimationTarget's and reset their _bitFlag for the next frame.
+    std::list<AnimationTarget*>::iterator targetItr = _activeTargets.begin();
+    while (targetItr != _activeTargets.end())
+    {
+        AnimationTarget* target = (*targetItr);
+        target->_bitFlag = 0x00;
+        targetItr++;
+    }
+    _activeTargets.clear();
     
     if (_runningClips.empty())
         _state = IDLE;

+ 2 - 1
gameplay/src/AnimationController.h

@@ -205,7 +205,8 @@ private:
     void destroyAllAnimations();
     
     State _state;                               // The current state of the AnimationController.
-    std::list<AnimationClip*> _runningClips;    // A list of currently running AnimationClips.
+    std::list<AnimationClip*> _runningClips;    // A list of running AnimationClips.
+    std::list<AnimationTarget*> _activeTargets;   // A list of animating AnimationTargets.
     std::vector<Animation*> _animations;        // A list of animations registered with the AnimationController
 };
 

+ 1 - 1
gameplay/src/AnimationTarget.cpp

@@ -8,7 +8,7 @@ namespace gameplay
 {
 
 AnimationTarget::AnimationTarget()
-    : _targetType(SCALAR), _highestPriority(NULL), _animationChannels(NULL)
+    : _targetType(SCALAR), _bitFlag(0x00), _animationChannels(NULL)
 {
 }
 

+ 4 - 3
gameplay/src/AnimationTarget.h

@@ -45,7 +45,7 @@ public:
      * @param propertyId The ID of the property on the AnimationTarget to set the animation property value on.
      * @param value The container to set the animation property value in.
      */
-    virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value) = 0;
+    virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f) = 0;
 
 protected:
     
@@ -69,6 +69,8 @@ protected:
 
     TargetType _targetType;             // The type of target this is.
 
+    char _bitFlag;
+
 private:
 
     /**
@@ -86,9 +88,8 @@ private:
      */
     static int getPropertyId(TargetType type, const char* propertyIdStr);
 
-    Animation::Channel* _highestPriority;
     std::vector<Animation::Channel*>* _animationChannels;   // Collection of all animation channels that target the AnimationTarget
-
+    
 };
 }
 

+ 7 - 9
gameplay/src/AnimationValue.cpp

@@ -5,44 +5,42 @@ namespace gameplay
 {
 
 AnimationValue::AnimationValue(unsigned int componentCount)
-  : _isFirstActing(false), _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
+  : _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
 {
-    _currentValue = new float[_componentCount];
-    _interpolatedValue = new float[_componentCount];
+    _value = new float[_componentCount];
 }
 
 AnimationValue::~AnimationValue()
 {
-    SAFE_DELETE_ARRAY(_currentValue);
-    SAFE_DELETE_ARRAY(_interpolatedValue);
+    SAFE_DELETE_ARRAY(_value);
 }
 
 float AnimationValue::getFloat(unsigned int index) const
 {
     assert(index < _componentCount);
 
-    return _currentValue[index];
+    return _value[index];
 }
 
 void AnimationValue::setFloat(unsigned int index, float value)
 {
     assert(index < _componentCount);
 
-    _currentValue[index] = value;
+    _value[index] = value;
 }
 
 void AnimationValue::getFloat(float* value, unsigned int offset, unsigned int length) const
 {
     assert(value && offset < _componentCount && (offset + length) <= _componentCount);
 
-    memcpy(value + offset, _currentValue, length * sizeof(float));
+    memcpy(value + offset, _value, length * sizeof(float));
 }
 
 void AnimationValue::setFloat(float* value, unsigned int offset, unsigned int length)
 {
     assert(value && offset < _componentCount && (offset + length) <= _componentCount);
 
-    memcpy(_currentValue, value + offset, length * sizeof(float));
+    memcpy(_value, value + offset, length * sizeof(float));
 }
 
 }

+ 2 - 3
gameplay/src/AnimationValue.h

@@ -72,11 +72,10 @@ private:
      */
     ~AnimationValue();
 
-    bool _isFirstActing;            // Flag indicating if this value's channel is the first to act on the target.
     unsigned int _componentCount;   // The number of float values for the property.
     unsigned int _componentSize;    // The number of bytes of memory the property is.
-    float* _currentValue;           // The current value of the property.
-    float* _interpolatedValue;      // The last interpolated value of the property.
+    float* _value;                  // The current value of the property.
+
 };
 
 }

+ 183 - 12
gameplay/src/MaterialParameter.cpp

@@ -304,7 +304,7 @@ unsigned int MaterialParameter::getAnimationPropertyComponentCount(int propertyI
                     return 0;
                 case FLOAT:
                 case INT:
-                    return 1;
+                    return _count;
                 case VECTOR2:
                     return 2 * _count;
                 case VECTOR3:
@@ -329,10 +329,30 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
             switch (_type)
             {
                 case FLOAT:
-                    value->setFloat(0, _value.floatValue);
+                    if (_count == 1)
+                    {
+                        value->setFloat(0, _value.floatValue);
+                    }
+                    else
+                    {
+                        for (unsigned int i = 0; i < _count; i++)
+                        {
+                            value->setFloat(i, _value.floatPtrValue[i]);
+                        }
+                    }
                     break;
                 case INT:
-                    value->setFloat(0, _value.intValue);
+                    if (_count == 1)
+                    {
+                        value->setFloat(0, _value.intValue);
+                    }
+                    else
+                    {
+                        for (unsigned int i = 0; i < _count; i++)
+                        {
+                            value->setFloat(i, _value.intPtrValue[i]);
+                        }
+                    }
                     break;
                 case VECTOR2:
                     for (unsigned int i = 0; i < _count; i++)
@@ -359,8 +379,12 @@ void MaterialParameter::getAnimationPropertyValue(int propertyId, AnimationValue
     }
 }
 
-void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue* value)
+void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
 {
+    assert(blendWeight >= 0.0f && blendWeight <= 1.0f);
+    if (blendWeight == 0.0f)
+        return;
+
     switch (propertyId)
     {
         case ANIMATE_UNIFORM:
@@ -368,29 +392,176 @@ void MaterialParameter::setAnimationPropertyValue(int propertyId, AnimationValue
             switch (_type)
             {
                 case FLOAT:
-                    _value.floatValue = value->getFloat(0);
+                {
+                    float value1 = value->getFloat(0);
+                    if (blendWeight != 1.0f)
+                        value1 *= blendWeight;
+
+                    if ((_bitFlag & UNIFORM_BIT) != UNIFORM_BIT)
+                    {
+                        if (_count == 1)
+                        {
+                            _value.floatValue = value1;
+                        }
+                        else
+                        {
+                            for (unsigned int i = 0; i < _count; i++)
+                                _value.floatPtrValue[i] = value1;
+                        }
+                        _bitFlag |= UNIFORM_BIT;
+                    }
+                    else
+                    {
+                        if (_count == 1)
+                        {
+                            _value.floatValue += value1;
+                        }
+                        else
+                        {
+                            for (unsigned int i = 0; i < _count; i++)
+                                _value.floatPtrValue[i] += value1;
+                        }
+                    }
                     break;
+                }
                 case INT:
-                    _value.intValue = value->getFloat(0);
+                {
+                    float value1 = value->getFloat(0);
+                    if (blendWeight != 1.0f)
+                        value1 *= blendWeight;
+
+                    if ((_bitFlag & UNIFORM_BIT) != UNIFORM_BIT)
+                    {
+                        if (_count == 1)
+                        {
+                            _value.intValue = value1;
+                        }
+                        else
+                        {
+                            for (unsigned int i = 0; i < _count; i++)
+                                _value.intPtrValue[i] = value1;
+                        }
+                        _bitFlag |= UNIFORM_BIT;
+                    }
+                    else
+                    {
+                        if (_count == 1)
+                        {
+                            _value.intValue += value1;
+                        }
+                        else
+                        {
+                            for (unsigned int i = 0; i < _count; i++)
+                                _value.intPtrValue[i] += value1;
+                        }
+                    }
                     break;
+                }
                 case VECTOR2:
-                    for (unsigned int i = 0; i < _count; i++)
+                {
+                    float value1 = value->getFloat(0);
+                    float value2 = value->getFloat(1);
+                    if (blendWeight != 1.0f)
                     {
-                        value->getFloat(_value.floatPtrValue, i * 2, 2);
+                        value1 *= blendWeight;
+                        value2 *= blendWeight;
+                    }
+
+                    if ((_bitFlag & UNIFORM_BIT) != UNIFORM_BIT)
+                    {
+                        unsigned int count = _count * 2;
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            _value.floatPtrValue[i] = value1;
+                            _value.floatPtrValue[++i] = value2;
+                        }
+                        _bitFlag |= UNIFORM_BIT;
+                    }
+                    else
+                    {
+                        unsigned int count = _count * 2;
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            _value.floatPtrValue[i] += value1;
+                            _value.floatPtrValue[++i] += value2;
+                        }
                     }
                     break;
+                }
                 case VECTOR3:
-                    for (unsigned int i = 0; i < _count; i++)
+                {
+                    float value1 = value->getFloat(0);
+                    float value2 = value->getFloat(1);
+                    float value3 = value->getFloat(2);
+                    if (blendWeight != 1.0f)
+                    {
+                        value1 *= blendWeight;
+                        value2 *= blendWeight;
+                        value3 *= blendWeight;
+                    }
+
+                    if ((_bitFlag & UNIFORM_BIT) != UNIFORM_BIT)
+                    {
+                        unsigned int count = _count * 3;
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            _value.floatPtrValue[i] = value1;
+                            _value.floatPtrValue[++i] = value2;
+                            _value.floatPtrValue[++i] = value3;
+                        }
+                        _bitFlag |= UNIFORM_BIT;
+                    }
+                    else
                     {
-                        value->getFloat(_value.floatPtrValue, i * 3, 3);
+                        unsigned int count = _count * 3;
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            _value.floatPtrValue[i] += value1;
+                            _value.floatPtrValue[++i] += value2;
+                            _value.floatPtrValue[++i] += value3;
+                        }
                     }
                     break;
+                }
                 case VECTOR4:
-                    for (unsigned int i = 0; i < _count; i++)
+                {
+                    float value1 = value->getFloat(0);
+                    float value2 = value->getFloat(1);
+                    float value3 = value->getFloat(2);
+                    float value4 = value->getFloat(3);
+                    if (blendWeight != 1.0f)
+                    {
+                        value1 *= blendWeight;
+                        value2 *= blendWeight;
+                        value3 *= blendWeight;
+                        value4 *= blendWeight;
+                    }
+
+                    if ((_bitFlag & UNIFORM_BIT) != UNIFORM_BIT)
+                    {
+                        unsigned int count = _count * 4;
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            _value.floatPtrValue[i] = value1;
+                            _value.floatPtrValue[++i] = value2;
+                            _value.floatPtrValue[++i] = value3;
+                            _value.floatPtrValue[++i] = value4;
+                        }
+                        _bitFlag |= UNIFORM_BIT;
+                    }
+                    else
                     {
-                        value->getFloat(_value.floatPtrValue, i * 4, 4);
+                        unsigned int count = _count * 4;
+                        for (unsigned int i = 0; i < count; i++)
+                        {
+                            _value.floatPtrValue[i] += value1;
+                            _value.floatPtrValue[++i] += value2;
+                            _value.floatPtrValue[++i] += value3;
+                            _value.floatPtrValue[++i] += value4;;
+                        }
                     }
                     break;
+                }
 
                 // UNSUPPORTED: NONE, MATRIX, METHOD, SAMPLER 
             }

+ 3 - 1
gameplay/src/MaterialParameter.h

@@ -164,7 +164,7 @@ public:
     /**
      * @see AnimationTarget#setAnimationProperty
      */
-    void setAnimationPropertyValue(int propertyId, AnimationValue* value);
+    void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f);
 
 private:
 
@@ -253,6 +253,8 @@ private:
         METHOD
     } _type;
 
+    static const char UNIFORM_BIT = 0x01;
+
     unsigned int _count;
     bool _dynamic;
     std::string _name;

+ 265 - 16
gameplay/src/Transform.cpp

@@ -226,6 +226,13 @@ void Transform::getRightVector(Vector3* dst) const
     getMatrix().getRightVector(dst);
 }
 
+void Transform::rotate(float qx, float qy, float qz, float qw)
+{
+    Quaternion q(qx, qy, qz, qw);
+    _rotation.multiply(q);
+    dirty();
+}
+
 void Transform::rotate(const Quaternion& rotation)
 {
     _rotation.multiply(rotation);
@@ -640,49 +647,194 @@ void Transform::getAnimationPropertyValue(int propertyId, AnimationValue* value)
     }
 }
 
-void Transform::setAnimationPropertyValue(int propertyId, AnimationValue* value)
+void Transform::setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight)
 {
+    assert(blendWeight >= 0.0f && blendWeight <= 1.0f);
+    if (blendWeight == 0.0f)
+        return;
+
     switch (propertyId)
     {
         case ANIMATE_SCALE_UNIT:
-            setScale(value->getFloat(0));
+        {
+            float scale = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                scale *= blendWeight;
+
+            animateScaleX(scale);
+            animateScaleY(scale);
+            animateScaleZ(scale);
+            
             break;
+        }   
         case ANIMATE_SCALE:
-            setScale(value->getFloat(0), value->getFloat(1), value->getFloat(2));
+        {
+            float sx = value->getFloat(0);
+            float sy = value->getFloat(1);
+            float sz = value->getFloat(2);
+            if (blendWeight != 1.0f)
+            {
+                sx *= blendWeight;
+                sy *= blendWeight;
+                sz *= blendWeight;
+            }
+
+            animateScaleX(sx);
+            animateScaleY(sy);
+            animateScaleZ(sz);
+
             break;
+        }
         case ANIMATE_SCALE_X:
-            setScaleX(value->getFloat(0));
+        {
+            float sx = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                sx *= blendWeight;
+
+            animateScaleX(sx);
+
             break;
+        }
         case ANIMATE_SCALE_Y:
-            setScaleY(value->getFloat(0));
+        {
+            float sy = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                sy *= blendWeight;
+
+            animateScaleY(sy);
+
             break;
+        }
         case ANIMATE_SCALE_Z:
-            setScaleZ(value->getFloat(0));
+        {
+            float sz = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                sz *= blendWeight;
+
+            animateScaleZ(sz);
+
             break;
+        }
         case ANIMATE_ROTATE:
-            setRotation(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
+        {
+            Quaternion q(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
+
+            if (blendWeight != 1.0f)
+                Quaternion::slerp(Quaternion::identity(), q, blendWeight, &q);
+
+            animateRotate(&q);
+            
             break;
+        }
         case ANIMATE_TRANSLATE:
-            setTranslation(value->getFloat(0), value->getFloat(1), value->getFloat(2));
+        {
+            float tx = value->getFloat(0);
+            float ty = value->getFloat(1);
+            float tz = value->getFloat(2);
+
+            if (blendWeight != 1.0f)
+            {
+                tx *= blendWeight;
+                ty *= blendWeight;
+                tz *= blendWeight;
+            }
+
+            animateTranslateX(tx);
+            animateTranslateY(ty);
+            animateTranslateZ(tz);
+            
             break;
+        }
         case ANIMATE_TRANSLATE_X:
-            setTranslationX(value->getFloat(0));
+        {
+            float tx = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                tx *= blendWeight;
+
+            animateTranslateX(tx);
+
             break;
+        }
         case ANIMATE_TRANSLATE_Y:
-            setTranslationY(value->getFloat(0));
+        {
+            float ty = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                ty *= blendWeight;
+            
+            animateTranslateY(ty);
+
             break;
+        }
         case ANIMATE_TRANSLATE_Z:
-            setTranslationZ(value->getFloat(0));
+        {
+            float tz = value->getFloat(0);
+
+            if (blendWeight != 1.0f)
+                tz *= blendWeight;
+
+            animateTranslateZ(tz);
+
             break;
+        }
         case ANIMATE_ROTATE_TRANSLATE:
-            setRotation(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
-            setTranslation(value->getFloat(4), value->getFloat(5), value->getFloat(6));
+        {
+            Quaternion q(value->getFloat(0), value->getFloat(1), value->getFloat(2), value->getFloat(3));
+            float tx = value->getFloat(4);
+            float ty = value->getFloat(5);
+            float tz = value->getFloat(6);
+
+            if (blendWeight != 1.0f)
+            {
+                Quaternion::slerp(Quaternion::identity(), q, blendWeight, &q);
+                tx *= blendWeight;
+                ty *= blendWeight;
+                tz *= blendWeight;
+            }
+
+            animateRotate(&q);
+            animateTranslateX(tx);
+            animateTranslateY(ty);
+            animateTranslateZ(tz);
+            
             break;
+        }
         case ANIMATE_SCALE_ROTATE_TRANSLATE:
-            setScale(value->getFloat(0), value->getFloat(1), value->getFloat(2));
-            setRotation(value->getFloat(3), value->getFloat(4), value->getFloat(5), value->getFloat(6));
-            setTranslation(value->getFloat(7), value->getFloat(8), value->getFloat(9));
+        {
+            float sx = value->getFloat(0);
+            float sy = value->getFloat(1);
+            float sz = value->getFloat(2);
+            Quaternion q(value->getFloat(3), value->getFloat(4), value->getFloat(5), value->getFloat(6));
+            float tx = value->getFloat(7);
+            float ty = value->getFloat(8);
+            float tz = value->getFloat(9);
+
+            if (blendWeight != 1.0f)
+            {
+                sx *= blendWeight;
+                sy *= blendWeight;
+                sz *= blendWeight;
+                Quaternion::slerp(Quaternion::identity(), q, blendWeight, &q);
+                tx *= blendWeight;
+                ty *= blendWeight;
+                tz *= blendWeight;
+            }
+
+            animateScaleX(sx);
+            animateScaleY(sy);
+            animateScaleZ(sz);
+            animateRotate(&q);
+            animateTranslateX(tx);
+            animateTranslateY(ty);
+            animateTranslateZ(tz);
+            
             break;
+        }
         default:
             break;
     }
@@ -732,4 +884,101 @@ void Transform::transformChanged()
     }
 }
 
+
+void Transform::animateScaleX(float sx)
+{
+    if ((_bitFlag & SCALE_X_BIT) != SCALE_X_BIT)
+    {
+        _bitFlag |= SCALE_X_BIT;
+        setScaleX(sx);
+    }
+    else
+    {
+        _scale.x += sx;
+        dirty();
+    }
+}
+
+void Transform::animateScaleY(float sy)
+{
+    if ((_bitFlag & SCALE_Y_BIT) != SCALE_Y_BIT)
+    {
+        _bitFlag |= SCALE_Y_BIT;
+        setScaleY(sy);
+    }
+    else
+    {
+        _scale.y += sy;
+        dirty();
+    }
+}
+
+void Transform::animateScaleZ(float sz)
+{
+    if ((_bitFlag & SCALE_Z_BIT) != SCALE_Z_BIT)
+    {
+        _bitFlag |= SCALE_Z_BIT;
+        setScaleZ(sz);
+    }
+    else
+    {
+        _scale.z += sz;
+        dirty();
+    }
+}
+
+void Transform::animateRotate(Quaternion* q)
+{
+    if ((_bitFlag & ROTATE_BIT) != ROTATE_BIT)
+    {
+        _bitFlag |= ROTATE_BIT;
+        setRotation(*q);
+    }
+    else
+    {
+        rotate(*q);
+    }
+}
+
+void Transform::animateTranslateX(float tx)
+{
+    if ((_bitFlag & TRANSLATE_X_BIT) != TRANSLATE_X_BIT)
+    {
+        _bitFlag |= TRANSLATE_X_BIT;
+        setTranslationX(tx);
+    }
+    else
+    {
+        translateX(tx);
+    }
+}
+
+void Transform::animateTranslateY(float ty)
+{
+    if ((_bitFlag & TRANSLATE_Y_BIT) != TRANSLATE_Y_BIT)
+    {
+        _bitFlag |= TRANSLATE_Y_BIT;
+        setTranslationY(ty);
+    }
+    else
+    {
+        translateY(ty);
+    }
+}
+
+void Transform::animateTranslateZ(float tz)
+{
+    if ((_bitFlag & TRANSLATE_Z_BIT) != TRANSLATE_Z_BIT)
+    {
+        _bitFlag |= TRANSLATE_Z_BIT;
+        setTranslationZ(tz);
+    }
+    else
+    {
+        translateZ(tz);
+    }
+}
+
+
+
 }

+ 31 - 3
gameplay/src/Transform.h

@@ -31,12 +31,12 @@ class Transform : public AnimationTarget
 public:
 
     /**
-     * Scale animation property. Data=sx,sy,sz
+     * Scale animation property. Data=scale
      */
     static const int ANIMATE_SCALE_UNIT = 0;
 
     /**
-     * Scale animation property. Data=scale
+     * Scale animation property. Data=sx,sy,sz
      */
     static const int ANIMATE_SCALE = 1;
 
@@ -324,6 +324,16 @@ public:
      */
     void getRightVector(Vector3* dst) const;
 
+    /**
+     * Rotates this transform's rotation component by the given rotation.
+     *
+     * @param qx The quaternion x value.
+     * @param qy The quaternion y value.
+     * @param qz The quaternion z value.
+     * @param qw The quaternion w value.
+     */
+    void rotate(float qx, float qy, float qz, float qw);
+
     /**
      * Rotates this transform's rotation component by the given rotation.
      *
@@ -715,7 +725,7 @@ public:
     /**
      * @see AnimationTarget#setAnimationProperty
      */
-    void setAnimationPropertyValue(int propertyId, AnimationValue* value);
+    void setAnimationPropertyValue(int propertyId, AnimationValue* value, float blendWeight = 1.0f);
 
 protected:
 
@@ -735,6 +745,24 @@ protected:
     mutable bool _matrixDirty;
     std::list<TransformListener>* _listeners;
 
+private:
+    static const char SCALE_X_BIT = 0x01; 
+    static const char SCALE_Y_BIT = 0x02; 
+    static const char SCALE_Z_BIT = 0x04; 
+    static const char ROTATE_BIT = 0x08;  
+    static const char TRANSLATE_X_BIT = 0x10; 
+    static const char TRANSLATE_Y_BIT = 0x20; 
+    static const char TRANSLATE_Z_BIT = 0x40; 
+
+    void animateScaleX(float sx);
+    void animateScaleY(float sy);
+    void animateScaleZ(float sz);
+    void animateRotate(Quaternion* q);
+    void animateTranslateX(float tx);
+    void animateTranslateY(float ty);
+    void animateTranslateZ(float tz);
+
+
 };
 
 }