diff --git a/engines/grim/emi/animationemi.cpp b/engines/grim/emi/animationemi.cpp index fd880521609..20ee77caf62 100644 --- a/engines/grim/emi/animationemi.cpp +++ b/engines/grim/emi/animationemi.cpp @@ -59,117 +59,6 @@ AnimationEmi::~AnimationEmi() { delete[] _bones; } -void AnimationEmi::computeWeights(const Skeleton *skel, float weight) { - if (weight <= 0.0f) - return; - - for (int bone = 0; bone < _numBones; ++bone) { - Bone &curBone = _bones[bone]; - Joint *target = skel->getJointNamed(curBone._boneName); - if (!target) { - continue; - } - - AnimationLayer *layer = skel->getLayer(curBone._priority); - int jointIndex = skel->getJointIndex(target); - JointAnimation &jointAnim = layer->_jointAnims[jointIndex]; - - if (curBone._rotations) { - jointAnim._rotWeight += weight; - } - if (curBone._translations) { - jointAnim._transWeight += weight; - } - } -} - -void AnimationEmi::animate(const Skeleton *skel, float time, bool loop, float weight) { - if (weight <= 0.0f) - return; - - for (int bone = 0; bone < _numBones; ++bone) { - Bone &curBone = _bones[bone]; - Joint *target = skel->getJointNamed(curBone._boneName); - if (!target) { - continue; - } - - AnimationLayer *layer = skel->getLayer(curBone._priority); - int jointIndex = skel->getJointIndex(target); - JointAnimation &jointAnim = layer->_jointAnims[jointIndex]; - - if (curBone._rotations) { - int keyfIdx = -1; - Math::Quaternion quat; - - // Normalize the weight so that the sum of applied weights will equal 1. - float normalizedRotWeight = weight; - if (jointAnim._rotWeight > 1.0f) { - // Note: Division by unnormalized sum of weights. - normalizedRotWeight = weight / jointAnim._rotWeight; - } - - for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) { - if (curBone._rotations[curKeyFrame]._time >= time) { - keyfIdx = curKeyFrame; - break; - } - } - - if (keyfIdx == 0) { - quat = curBone._rotations[0]._quat; - } else if (keyfIdx != -1) { - float timeDelta = curBone._rotations[keyfIdx]._time - curBone._rotations[keyfIdx - 1]._time; - float interpVal = (time - curBone._rotations[keyfIdx - 1]._time) / timeDelta; - - quat = curBone._rotations[keyfIdx - 1]._quat.slerpQuat(curBone._rotations[keyfIdx]._quat, interpVal); - } else { - quat = curBone._rotations[curBone._count - 1]._quat; - } - - Math::Quaternion &quatFinal = jointAnim._quat; - quat = target->_quat.inverse() * quat; - quat = quatFinal * quat; - quatFinal = quatFinal.slerpQuat(quat, normalizedRotWeight); - } - - if (curBone._translations) { - int keyfIdx = -1; - Math::Vector3d vec; - - // Normalize the weight so that the sum of applied weights will equal 1. - float normalizedTransWeight = weight; - if (jointAnim._rotWeight > 1.0f) { - // Note: Division by unnormalized sum of weights. - normalizedTransWeight = weight / jointAnim._transWeight; - } - - for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) { - if (curBone._translations[curKeyFrame]._time >= time) { - keyfIdx = curKeyFrame; - break; - } - } - - if (keyfIdx == 0) { - vec = curBone._translations[0]._vec; - } else if (keyfIdx != -1) { - float timeDelta = curBone._translations[keyfIdx]._time - curBone._translations[keyfIdx - 1]._time; - float interpVal = (time - curBone._translations[keyfIdx - 1]._time) / timeDelta; - - vec = curBone._translations[keyfIdx - 1]._vec + - (curBone._translations[keyfIdx]._vec - curBone._translations[keyfIdx - 1]._vec) * interpVal; - } else { - vec = curBone._translations[curBone._count - 1]._vec; - } - - Math::Vector3d &posFinal = jointAnim._pos; - vec = vec - target->_relMatrix.getPosition(); - posFinal = posFinal + vec * normalizedTransWeight; - } - } -} - void Bone::loadBinary(Common::SeekableReadStream *data) { uint32 len = data->readUint32LE(); char *inString = new char[len]; @@ -277,6 +166,121 @@ void AnimationStateEmi::update(uint time) { } } +void AnimationStateEmi::computeWeights() { + if (_fade <= 0.0f) + return; + + for (int bone = 0; bone < _anim->_numBones; ++bone) { + Bone &curBone = _anim->_bones[bone]; + Joint *target = _skel->getJointNamed(curBone._boneName); + if (!target) { + continue; + } + + AnimationLayer *layer = _skel->getLayer(curBone._priority); + int jointIndex = _skel->getJointIndex(target); + JointAnimation &jointAnim = layer->_jointAnims[jointIndex]; + + if (curBone._rotations) { + jointAnim._rotWeight += _fade; + } + if (curBone._translations) { + jointAnim._transWeight += _fade; + } + } +} + +void AnimationStateEmi::animate() { + if (_fade <= 0.0f) + return; + + for (int bone = 0; bone < _anim->_numBones; ++bone) { + Bone &curBone = _anim->_bones[bone]; + Joint *target = _skel->getJointNamed(curBone._boneName); + if (!target) { + continue; + } + + AnimationLayer *layer = _skel->getLayer(curBone._priority); + int jointIndex = _skel->getJointIndex(target); + JointAnimation &jointAnim = layer->_jointAnims[jointIndex]; + + if (curBone._rotations) { + int keyfIdx = -1; + Math::Quaternion quat; + + // Normalize the weight so that the sum of applied weights will equal 1. + float normalizedRotWeight = _fade; + if (jointAnim._rotWeight > 1.0f) { + // Note: Division by unnormalized sum of weights. + normalizedRotWeight = _fade / jointAnim._rotWeight; + } + + for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) { + if (curBone._rotations[curKeyFrame]._time >= _time) { + keyfIdx = curKeyFrame; + break; + } + } + + if (keyfIdx == 0) { + quat = curBone._rotations[0]._quat; + } + else if (keyfIdx != -1) { + float timeDelta = curBone._rotations[keyfIdx]._time - curBone._rotations[keyfIdx - 1]._time; + float interpVal = (_time - curBone._rotations[keyfIdx - 1]._time) / timeDelta; + + quat = curBone._rotations[keyfIdx - 1]._quat.slerpQuat(curBone._rotations[keyfIdx]._quat, interpVal); + } + else { + quat = curBone._rotations[curBone._count - 1]._quat; + } + + Math::Quaternion &quatFinal = jointAnim._quat; + quat = target->_quat.inverse() * quat; + quat = quatFinal * quat; + quatFinal = quatFinal.slerpQuat(quat, normalizedRotWeight); + } + + if (curBone._translations) { + int keyfIdx = -1; + Math::Vector3d vec; + + // Normalize the weight so that the sum of applied weights will equal 1. + float normalizedTransWeight = _fade; + if (jointAnim._rotWeight > 1.0f) { + // Note: Division by unnormalized sum of weights. + normalizedTransWeight = _fade / jointAnim._transWeight; + } + + for (int curKeyFrame = 0; curKeyFrame < curBone._count; curKeyFrame++) { + if (curBone._translations[curKeyFrame]._time >= _time) { + keyfIdx = curKeyFrame; + break; + } + } + + if (keyfIdx == 0) { + vec = curBone._translations[0]._vec; + } + else if (keyfIdx != -1) { + float timeDelta = curBone._translations[keyfIdx]._time - curBone._translations[keyfIdx - 1]._time; + float interpVal = (_time - curBone._translations[keyfIdx - 1]._time) / timeDelta; + + vec = curBone._translations[keyfIdx - 1]._vec + + (curBone._translations[keyfIdx]._vec - curBone._translations[keyfIdx - 1]._vec) * interpVal; + } + else { + vec = curBone._translations[curBone._count - 1]._vec; + } + + Math::Vector3d &posFinal = jointAnim._pos; + vec = vec - target->_relMatrix.getPosition(); + posFinal = posFinal + vec * normalizedTransWeight; + } + } +} + void AnimationStateEmi::play() { if (!_active) { _time = 0.f; diff --git a/engines/grim/emi/animationemi.h b/engines/grim/emi/animationemi.h index a3037d4413d..c39167a668f 100644 --- a/engines/grim/emi/animationemi.h +++ b/engines/grim/emi/animationemi.h @@ -67,8 +67,6 @@ public: AnimationEmi(const Common::String &filename, Common::SeekableReadStream *data); ~AnimationEmi(); - void computeWeights(const Skeleton *skel, float weight); - void animate(const Skeleton *skel, float delta, bool loop, float weight); const Common::String &getFilename() const { return _fname; } }; @@ -77,9 +75,9 @@ public: AnimationStateEmi(const Common::String &anim); ~AnimationStateEmi(); - void activate(); - void deactivate(); void update(uint time); + void computeWeights(); + void animate(); void play(); void stop(); void setPaused(bool paused); @@ -91,6 +89,9 @@ public: void restoreState(SaveGame *state); private: + void activate(); + void deactivate(); + friend class Skeleton; Skeleton *_skel; diff --git a/engines/grim/emi/skeleton.cpp b/engines/grim/emi/skeleton.cpp index 7bda662b1c8..04c194490dd 100644 --- a/engines/grim/emi/skeleton.cpp +++ b/engines/grim/emi/skeleton.cpp @@ -129,12 +129,12 @@ void Skeleton::commitAnim() { // animation layers. The sums must be pre-computed in order to be able to normalize the blend // weights properly in the next step. for (Common::List::iterator j = _activeAnims.begin(); j != _activeAnims.end(); ++j) { - (*j)->_anim->computeWeights(this, (*j)->_fade); + (*j)->computeWeights(); } // Now make a second pass over the animations to actually accumulate animation to layers. for (Common::List::iterator j = _activeAnims.begin(); j != _activeAnims.end(); ++j) { - (*j)->_anim->animate(this, (*j)->_time, (*j)->_looping, (*j)->_fade); + (*j)->animate(); } // Blend the layers together in priority order to produce the final result. Highest priority