mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-09 15:52:27 +02:00
bare-bones AnimClip implementation with tests!
It accumulates time and handles looping, and should handle onDone and onLoop events in the future.
This commit is contained in:
parent
836cdeb103
commit
35196a0059
6 changed files with 226 additions and 10 deletions
77
libraries/animation/src/AnimClip.cpp
Normal file
77
libraries/animation/src/AnimClip.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// AnimClip.cpp
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AnimClip.h"
|
||||
#include "AnimationLogging.h"
|
||||
|
||||
AnimClip::AnimClip(const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag) :
|
||||
_url(url),
|
||||
_startFrame(startFrame),
|
||||
_endFrame(endFrame),
|
||||
_timeScale(timeScale),
|
||||
_frame(startFrame),
|
||||
_loopFlag(loopFlag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AnimClip::~AnimClip() {
|
||||
|
||||
}
|
||||
|
||||
void AnimClip::setURL(const std::string& url) {
|
||||
// TODO:
|
||||
_url = url;
|
||||
}
|
||||
|
||||
void AnimClip::setStartFrame(float startFrame) {
|
||||
_startFrame = startFrame;
|
||||
}
|
||||
|
||||
void AnimClip::setEndFrame(float endFrame) {
|
||||
_endFrame = endFrame;
|
||||
}
|
||||
|
||||
void AnimClip::setLoopFlag(bool loopFlag) {
|
||||
_loopFlag = loopFlag;
|
||||
}
|
||||
|
||||
const AnimPose& AnimClip::evaluate(float dt) {
|
||||
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
|
||||
// TODO: trigger onLoop event
|
||||
framesRemaining -= framesTillEnd;
|
||||
_frame = startFrame;
|
||||
} else {
|
||||
// anim end
|
||||
// TODO: trigger onDone event
|
||||
_frame = _endFrame;
|
||||
framesRemaining = 0.0f;
|
||||
}
|
||||
} else {
|
||||
_frame += framesRemaining;
|
||||
framesRemaining = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: eval animation
|
||||
|
||||
return _frame;
|
||||
}
|
|
@ -10,17 +10,41 @@
|
|||
#ifndef hifi_AnimClip_h
|
||||
#define hifi_AnimClip_h
|
||||
|
||||
#include <string>
|
||||
#include "AnimationCache.h"
|
||||
#include "AnimNode.h"
|
||||
|
||||
class AnimClip : public AnimNode {
|
||||
public:
|
||||
friend class AnimClipTests;
|
||||
|
||||
AnimClip(const std::string& url, float startFrame, float endFrame, float timeScale, bool loopFlag);
|
||||
virtual ~AnimClip();
|
||||
|
||||
void setURL(const std::string& url);
|
||||
void setStartFrame(AnimFrame startFrame);
|
||||
void setEndFrame(AnimFrame startFrame);
|
||||
void setLoopFlag(bool loopFlag);
|
||||
void setTimeScale(float timeScale);
|
||||
const std::string& getURL() const { return _url; }
|
||||
|
||||
public:
|
||||
virtual const float getEnd() const;
|
||||
virtual const AnimPose& evaluate(float t);
|
||||
void setStartFrame(float startFrame);
|
||||
float getStartFrame() const { return _startFrame; }
|
||||
|
||||
void setEndFrame(float endFrame);
|
||||
float getEndFrame() const { return _endFrame; }
|
||||
|
||||
void setTimeScale(float timeScale) { _timeScale = timeScale; }
|
||||
float getTimeScale() const { return _timeScale; }
|
||||
|
||||
void setLoopFlag(bool loopFlag);
|
||||
bool getLoopFlag() const { return _loopFlag; }
|
||||
|
||||
virtual const AnimPose& evaluate(float dt);
|
||||
protected:
|
||||
AnimationPointer _anim;
|
||||
std::string _url;
|
||||
float _startFrame;
|
||||
float _endFrame;
|
||||
float _timeScale;
|
||||
float _frame;
|
||||
bool _loopFlag;
|
||||
};
|
||||
|
||||
#endif // hifi_AnimClip_h
|
||||
|
|
|
@ -10,10 +10,13 @@
|
|||
#ifndef hifi_AnimNode_h
|
||||
#define hifi_AnimNode_h
|
||||
|
||||
typedef float AnimPose;
|
||||
|
||||
class AnimNode {
|
||||
public:
|
||||
virtual float getEnd() const = 0;
|
||||
virtual const AnimPose& evaluate(float t) = 0;
|
||||
virtual ~AnimNode() {}
|
||||
|
||||
virtual const AnimPose& evaluate(float dt) = 0;
|
||||
};
|
||||
|
||||
#endif // hifi_AnimNode_h
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Declare dependencies
|
||||
macro (setup_testcase_dependencies)
|
||||
# link in the shared libraries
|
||||
link_hifi_libraries(shared animation gpu fbx model)
|
||||
link_hifi_libraries(shared animation gpu fbx model networking)
|
||||
|
||||
copy_dlls_beside_windows_executable()
|
||||
endmacro ()
|
||||
|
|
85
tests/animation/src/AnimClipTests.cpp
Normal file
85
tests/animation/src/AnimClipTests.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
//
|
||||
// AnimClipTests.cpp
|
||||
// tests/rig/src
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "AnimClipTests.h"
|
||||
#include "AnimClip.h"
|
||||
#include "AnimationLogging.h"
|
||||
|
||||
#include <../QTestExtensions.h>
|
||||
|
||||
QTEST_MAIN(AnimClipTests)
|
||||
|
||||
const float EPSILON = 0.001f;
|
||||
|
||||
void AnimClipTests::testAccessors() {
|
||||
std::string url = "foo";
|
||||
float startFrame = 2.0f;
|
||||
float endFrame = 20.0f;
|
||||
float timeScale = 1.1f;
|
||||
float loopFlag = true;
|
||||
|
||||
AnimClip clip(url, startFrame, endFrame, timeScale, loopFlag);
|
||||
QVERIFY(clip.getURL() == url);
|
||||
QVERIFY(clip.getStartFrame() == startFrame);
|
||||
QVERIFY(clip.getEndFrame() == endFrame);
|
||||
QVERIFY(clip.getTimeScale() == timeScale);
|
||||
QVERIFY(clip.getLoopFlag() == loopFlag);
|
||||
|
||||
std::string url2 = "bar";
|
||||
float startFrame2 = 22.0f;
|
||||
float endFrame2 = 100.0f;
|
||||
float timeScale2 = 1.2f;
|
||||
float loopFlag2 = false;
|
||||
|
||||
clip.setURL(url2);
|
||||
clip.setStartFrame(startFrame2);
|
||||
clip.setEndFrame(endFrame2);
|
||||
clip.setTimeScale(timeScale2);
|
||||
clip.setLoopFlag(loopFlag2);
|
||||
|
||||
QVERIFY(clip.getURL() == url2);
|
||||
QVERIFY(clip.getStartFrame() == startFrame2);
|
||||
QVERIFY(clip.getEndFrame() == endFrame2);
|
||||
QVERIFY(clip.getTimeScale() == timeScale2);
|
||||
QVERIFY(clip.getLoopFlag() == loopFlag2);
|
||||
}
|
||||
|
||||
static float secsToFrames(float secs) {
|
||||
const float FRAMES_PER_SECOND = 30.0f;
|
||||
return secs * FRAMES_PER_SECOND;
|
||||
}
|
||||
|
||||
static float framesToSec(float secs) {
|
||||
const float FRAMES_PER_SECOND = 30.0f;
|
||||
return secs / FRAMES_PER_SECOND;
|
||||
}
|
||||
|
||||
void AnimClipTests::testEvaulate() {
|
||||
std::string url = "foo";
|
||||
float startFrame = 2.0f;
|
||||
float endFrame = 22.0f;
|
||||
float timeScale = 1.0f;
|
||||
float loopFlag = true;
|
||||
|
||||
AnimClip clip(url, startFrame, endFrame, timeScale, loopFlag);
|
||||
|
||||
clip.evaluate(framesToSec(10.0f));
|
||||
QCOMPARE_WITH_ABS_ERROR(clip._frame, 12.0f, EPSILON);
|
||||
|
||||
// does it loop?
|
||||
clip.evaluate(framesToSec(11.0f));
|
||||
QCOMPARE_WITH_ABS_ERROR(clip._frame, 3.0f, EPSILON);
|
||||
|
||||
// does it pause at end?
|
||||
clip.setLoopFlag(false);
|
||||
clip.evaluate(framesToSec(20.0f));
|
||||
QCOMPARE_WITH_ABS_ERROR(clip._frame, 22.0f, EPSILON);
|
||||
}
|
||||
|
27
tests/animation/src/AnimClipTests.h
Normal file
27
tests/animation/src/AnimClipTests.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// AnimClipTests.h
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_AnimClipTests_h
|
||||
#define hifi_AnimClipTests_h
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
inline float getErrorDifference(float a, float b) {
|
||||
return fabs(a - b);
|
||||
}
|
||||
|
||||
class AnimClipTests : public QObject {
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void testAccessors();
|
||||
void testEvaulate();
|
||||
};
|
||||
|
||||
#endif // hifi_TransformTests_h
|
Loading…
Reference in a new issue