mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 12:12:39 +02:00
AnimUtil: prevent accumulateTime from looping forever
This might happen with large dts, large timeScales.
This commit is contained in:
parent
091e34e792
commit
df5afffc77
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,
|
||||
const QString& id, AnimNode::Triggers& triggersOut) {
|
||||
|
||||
const float EPSILON = 0.0001f;
|
||||
float frame = currentFrame;
|
||||
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;
|
||||
} else if (timeScale > 0.0f) {
|
||||
} else if (timeScale > EPSILON && dt > EPSILON) {
|
||||
// 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) {
|
||||
|
||||
// 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;
|
||||
// when looping, add one frame between start and end.
|
||||
if (loopFlag) {
|
||||
|
@ -62,6 +69,7 @@ float accumulateTime(float startFrame, float endFrame, float timeScale, float cu
|
|||
frame = endFrame;
|
||||
framesRemaining = 0.0f;
|
||||
}
|
||||
triggerCount++;
|
||||
} else {
|
||||
frame += framesRemaining;
|
||||
framesRemaining = 0.0f;
|
||||
|
|
|
@ -257,6 +257,29 @@ void AnimTests::testAccumulateTime() {
|
|||
endFrame = 15.0f;
|
||||
timeScale = 2.0f;
|
||||
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 {
|
||||
|
|
Loading…
Reference in a new issue