mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-29 08:52:12 +02:00
Merge pull request #7410 from hyperlogic/tony/limit-accumulate-time-loops
AnimUtil: prevent accumulateTime from looping forever
This commit is contained in:
commit
277f49ef64
2 changed files with 34 additions and 3 deletions
|
@ -36,15 +36,22 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A
|
||||||
float accumulateTime(float startFrame, float endFrame, float timeScale, float currentFrame, float dt, bool loopFlag,
|
float accumulateTime(float startFrame, float endFrame, float timeScale, float currentFrame, float dt, bool loopFlag,
|
||||||
const QString& id, AnimNode::Triggers& triggersOut) {
|
const QString& id, AnimNode::Triggers& triggersOut) {
|
||||||
|
|
||||||
|
const float EPSILON = 0.0001f;
|
||||||
float frame = currentFrame;
|
float frame = currentFrame;
|
||||||
const float clampedStartFrame = std::min(startFrame, endFrame);
|
const float clampedStartFrame = std::min(startFrame, endFrame);
|
||||||
if (fabsf(clampedStartFrame - endFrame) < 1.0f) {
|
if (fabsf(clampedStartFrame - endFrame) <= 1.0f) {
|
||||||
|
// An animation of a single frame should not send loop or done triggers.
|
||||||
frame = endFrame;
|
frame = endFrame;
|
||||||
} else if (timeScale > 0.0f) {
|
} else if (timeScale > EPSILON && dt > EPSILON) {
|
||||||
// accumulate time, keeping track of loops and end of animation events.
|
// accumulate time, keeping track of loops and end of animation events.
|
||||||
const float FRAMES_PER_SECOND = 30.0f;
|
const float FRAMES_PER_SECOND = 30.0f;
|
||||||
float framesRemaining = (dt * timeScale) * FRAMES_PER_SECOND;
|
float framesRemaining = (dt * timeScale) * FRAMES_PER_SECOND;
|
||||||
while (framesRemaining > 0.0f) {
|
|
||||||
|
// prevent huge dt or timeScales values from causing many trigger events.
|
||||||
|
uint32_t triggerCount = 0;
|
||||||
|
const uint32_t MAX_TRIGGER_COUNT = 3;
|
||||||
|
|
||||||
|
while (framesRemaining > EPSILON && triggerCount < MAX_TRIGGER_COUNT) {
|
||||||
float framesTillEnd = endFrame - frame;
|
float framesTillEnd = endFrame - frame;
|
||||||
// when looping, add one frame between start and end.
|
// when looping, add one frame between start and end.
|
||||||
if (loopFlag) {
|
if (loopFlag) {
|
||||||
|
@ -62,6 +69,7 @@ float accumulateTime(float startFrame, float endFrame, float timeScale, float cu
|
||||||
frame = endFrame;
|
frame = endFrame;
|
||||||
framesRemaining = 0.0f;
|
framesRemaining = 0.0f;
|
||||||
}
|
}
|
||||||
|
triggerCount++;
|
||||||
} else {
|
} else {
|
||||||
frame += framesRemaining;
|
frame += framesRemaining;
|
||||||
framesRemaining = 0.0f;
|
framesRemaining = 0.0f;
|
||||||
|
|
|
@ -257,6 +257,29 @@ void AnimTests::testAccumulateTime() {
|
||||||
endFrame = 15.0f;
|
endFrame = 15.0f;
|
||||||
timeScale = 2.0f;
|
timeScale = 2.0f;
|
||||||
testAccumulateTimeWithParameters(startFrame, endFrame, timeScale);
|
testAccumulateTimeWithParameters(startFrame, endFrame, timeScale);
|
||||||
|
|
||||||
|
startFrame = 0.0f;
|
||||||
|
endFrame = 1.0f;
|
||||||
|
timeScale = 1.0f;
|
||||||
|
float dt = 1.0f;
|
||||||
|
QString id = "testNode";
|
||||||
|
AnimNode::Triggers triggers;
|
||||||
|
float loopFlag = true;
|
||||||
|
float resultFrame = accumulateTime(startFrame, endFrame, timeScale, startFrame, dt, loopFlag, id, triggers);
|
||||||
|
// a one frame looping animation should NOT trigger onLoop events
|
||||||
|
QVERIFY(triggers.empty());
|
||||||
|
|
||||||
|
const uint32_t MAX_TRIGGER_COUNT = 3;
|
||||||
|
|
||||||
|
startFrame = 0.0f;
|
||||||
|
endFrame = 1.1f;
|
||||||
|
timeScale = 10.0f;
|
||||||
|
dt = 10.0f;
|
||||||
|
triggers.clear();
|
||||||
|
loopFlag = true;
|
||||||
|
resultFrame = accumulateTime(startFrame, endFrame, timeScale, startFrame, dt, loopFlag, id, triggers);
|
||||||
|
// a short animation with a large dt & a large timescale, should only create a MAXIMUM of 3 loop events.
|
||||||
|
QVERIFY(triggers.size() <= MAX_TRIGGER_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimTests::testAccumulateTimeWithParameters(float startFrame, float endFrame, float timeScale) const {
|
void AnimTests::testAccumulateTimeWithParameters(float startFrame, float endFrame, float timeScale) const {
|
||||||
|
|
Loading…
Reference in a new issue