float AnimClip::accumulateTime(float frame, float dt, Triggers& triggersOut) const { const float startFrame = std::min(_startFrame, _endFrame); if (startFrame == _endFrame) { // when startFrame >= endFrame frame = _endFrame; } else if (_timeScale > 0.0f) { // accumulate time, keeping track of loops and end of animation events. const float FRAMES_PER_SECOND = 30.0f; float framesRemaining = (dt * _timeScale) * FRAMES_PER_SECOND; while (framesRemaining > 0.0f) { float framesTillEnd = _endFrame - _frame; if (framesRemaining >= framesTillEnd) { if (_loopFlag) { // anim loop triggersOut.push_back(_id + "OnLoop"); framesRemaining -= framesTillEnd; frame = startFrame; } else { // anim end triggersOut.push_back(_id + "OnDone"); frame = _endFrame; framesRemaining = 0.0f; } } else { frame += framesRemaining; framesRemaining = 0.0f; } } } return frame; }
void AnimBlendLinearMove::setFrameAndPhase(float dt, float alpha, int prevPoseIndex, int nextPoseIndex, float* prevDeltaTimeOut, float* nextDeltaTimeOut, Triggers& triggersOut) { const float FRAMES_PER_SECOND = 30.0f; auto prevClipNode = std::dynamic_pointer_cast<AnimClip>(_children[prevPoseIndex]); assert(prevClipNode); auto nextClipNode = std::dynamic_pointer_cast<AnimClip>(_children[nextPoseIndex]); assert(nextClipNode); float v0 = _characteristicSpeeds[prevPoseIndex]; float n0 = (prevClipNode->getEndFrame() - prevClipNode->getStartFrame()) + 1.0f; float v1 = _characteristicSpeeds[nextPoseIndex]; float n1 = (nextClipNode->getEndFrame() - nextClipNode->getStartFrame()) + 1.0f; // rate of change in phase space, necessary to achive desired speed. float omega = (_desiredSpeed * FRAMES_PER_SECOND) / ((1.0f - alpha) * v0 * n0 + alpha * v1 * n1); float f0 = prevClipNode->getStartFrame() + _phase * n0; prevClipNode->setCurrentFrame(f0); float f1 = nextClipNode->getStartFrame() + _phase * n1; nextClipNode->setCurrentFrame(f1); // integrate phase forward in time. _phase += omega * dt; // detect loop trigger events if (_phase >= 1.0f) { triggersOut.push_back(_id + "Loop"); _phase = glm::fract(_phase); } *prevDeltaTimeOut = omega * dt * (n0 / FRAMES_PER_SECOND); *nextDeltaTimeOut = omega * dt * (n1 / FRAMES_PER_SECOND); }