diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1e296c1066..15bde7fe2c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -170,7 +170,7 @@ void MyAvatar::update(float deltaTime) { blend->setAlpha(0.5f * sin(t) + 0.5f); */ t += deltaTime; - _animNode->evaluate(deltaTime); + _animNode->evaluate(_animVars, deltaTime); } if (_referential) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c1812a5e96..0adc901398 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -17,6 +17,7 @@ #include #include "Avatar.h" +#include "AnimVariant.h" class ModelItemID; class AnimNode; @@ -315,6 +316,7 @@ private: bool _prevShouldDrawHead; std::shared_ptr _animNode; + AnimVariantMap _animVars; }; #endif // hifi_MyAvatar_h diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index 76d92cd264..8ce6845e6f 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -22,22 +22,24 @@ AnimBlendLinear::~AnimBlendLinear() { } -const std::vector& AnimBlendLinear::evaluate(float dt) { +const std::vector& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, float dt) { + + // TODO: update _alpha from animVars if (_children.size() == 0) { for (auto&& pose : _poses) { pose = AnimPose::identity; } } else if (_children.size() == 1) { - _poses = _children[0]->evaluate(dt); + _poses = _children[0]->evaluate(animVars, dt); } else { float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); size_t prevPoseIndex = glm::floor(clampedAlpha); size_t nextPoseIndex = glm::ceil(clampedAlpha); float alpha = glm::fract(clampedAlpha); if (prevPoseIndex != nextPoseIndex) { - auto prevPoses = _children[prevPoseIndex]->evaluate(dt); - auto nextPoses = _children[nextPoseIndex]->evaluate(dt); + auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, dt); + auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, dt); if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) { _poses.resize(prevPoses.size()); diff --git a/libraries/animation/src/AnimBlendLinear.h b/libraries/animation/src/AnimBlendLinear.h index c1c1c928e5..784d89b04c 100644 --- a/libraries/animation/src/AnimBlendLinear.h +++ b/libraries/animation/src/AnimBlendLinear.h @@ -28,7 +28,7 @@ public: AnimBlendLinear(const std::string& id, float alpha); virtual ~AnimBlendLinear() override; - virtual const std::vector& evaluate(float dt) override; + virtual const std::vector& evaluate(const AnimVariantMap& animVars, float dt) override; void setAlpha(float alpha) { _alpha = alpha; } float getAlpha() const { return _alpha; } diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index dca43cb735..7653aabde8 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -45,7 +45,10 @@ void AnimClip::setLoopFlag(bool loopFlag) { _loopFlag = loopFlag; } -const std::vector& AnimClip::evaluate(float dt) { +const std::vector& AnimClip::evaluate(const AnimVariantMap& animVars, float dt) { + + // TODO: update _frame, _startFrame, _endFrame, _timeScale, _loopFlag from animVars. + _frame = accumulateTime(_frame, dt); if (_networkAnim && _networkAnim->isLoaded() && _skeleton) { diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 2cce40d98a..0d4f104678 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -42,7 +42,7 @@ public: void setLoopFlag(bool loopFlag); bool getLoopFlag() const { return _loopFlag; } - virtual const std::vector& evaluate(float dt) override; + virtual const std::vector& evaluate(const AnimVariantMap& animVars, float dt) override; protected: virtual void setCurrentFrameInternal(float frame) override; diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 9063488e9b..c4edd9bb06 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -18,6 +18,7 @@ #include #include "AnimSkeleton.h" +#include "AnimVariant.h" class QJsonObject; @@ -78,9 +79,9 @@ public: } } - virtual const std::vector& evaluate(float dt) = 0; - virtual const std::vector& overlay(float dt, const std::vector& underPoses) { - return evaluate(dt); + virtual const std::vector& evaluate(const AnimVariantMap& animVars, float dt) = 0; + virtual const std::vector& overlay(const AnimVariantMap& animVars, float dt, const std::vector& underPoses) { + return evaluate(animVars, dt); } protected: diff --git a/libraries/animation/src/AnimOverlay.cpp b/libraries/animation/src/AnimOverlay.cpp index c02c83d69f..3a76903d0f 100644 --- a/libraries/animation/src/AnimOverlay.cpp +++ b/libraries/animation/src/AnimOverlay.cpp @@ -37,17 +37,18 @@ void AnimOverlay::setBoneSet(BoneSet boneSet) { } } -const std::vector& AnimOverlay::evaluate(float dt) { +const std::vector& AnimOverlay::evaluate(const AnimVariantMap& animVars, float dt) { + if (_children.size() >= 2) { - auto underPoses = _children[1]->evaluate(dt); - auto overPoses = _children[0]->overlay(dt, underPoses); + auto underPoses = _children[1]->evaluate(animVars, dt); + auto overPoses = _children[0]->overlay(animVars, dt, underPoses); if (underPoses.size() > 0 && underPoses.size() == overPoses.size()) { _poses.resize(underPoses.size()); assert(_boneSetVec.size() == _poses.size()); for (size_t i = 0; i < _poses.size(); i++) { - float alpha = _boneSetVec[i]; // TODO: PULL from boneSet + float alpha = _boneSetVec[i]; blend(1, &underPoses[i], &overPoses[i], alpha, &_poses[i]); } } diff --git a/libraries/animation/src/AnimOverlay.h b/libraries/animation/src/AnimOverlay.h index 82990514af..87d05e2b96 100644 --- a/libraries/animation/src/AnimOverlay.h +++ b/libraries/animation/src/AnimOverlay.h @@ -41,7 +41,7 @@ public: void setBoneSet(BoneSet boneSet); BoneSet getBoneSet() const { return _boneSet; } - virtual const std::vector& evaluate(float dt) override; + virtual const std::vector& evaluate(const AnimVariantMap& animVars, float dt) override; protected: // for AnimDebugDraw rendering diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index 13e364045b..627e3210f4 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -18,6 +18,7 @@ class AnimVariant { public: enum Type { BoolType = 0, + IntType, FloatType, Vec3Type, QuatType, @@ -27,24 +28,28 @@ public: AnimVariant() : _type(BoolType) { memset(&_val, 0, sizeof(_val)); } AnimVariant(bool value) : _type(BoolType) { _val.boolVal = value; } + AnimVariant(int value) : _type(IntType) { _val.intVal = value; } AnimVariant(float value) : _type(FloatType) { _val.floats[0] = value; } AnimVariant(const glm::vec3& value) : _type(Vec3Type) { *reinterpret_cast(&_val) = value; } AnimVariant(const glm::quat& value) : _type(QuatType) { *reinterpret_cast(&_val) = value; } AnimVariant(const glm::mat4& value) : _type(Mat4Type) { *reinterpret_cast(&_val) = value; } bool isBool() const { return _type == BoolType; } + bool isInt() const { return _type == IntType; } bool isFloat() const { return _type == FloatType; } bool isVec3() const { return _type == Vec3Type; } bool isQuat() const { return _type == QuatType; } bool isMat4() const { return _type == Mat4Type; } void setBool(bool value) { assert(_type == BoolType); _val.boolVal = value; } + void setInt(int value) { assert(_type == IntType); _val.intVal = value; } void setFloat(float value) { assert(_type == FloatType); _val.floats[0] = value; } void setVec3(const glm::vec3& value) { assert(_type == Vec3Type); *reinterpret_cast(&_val) = value; } void setQuat(const glm::quat& value) { assert(_type == QuatType); *reinterpret_cast(&_val) = value; } void setMat4(const glm::mat4& value) { assert(_type == Mat4Type); *reinterpret_cast(&_val) = value; } bool getBool() { assert(_type == BoolType); return _val.boolVal; } + int getInt() { assert(_type == IntType); return _val.intVal; } float getFloat() { assert(_type == FloatType); return _val.floats[0]; } const glm::vec3& getVec3() { assert(_type == Vec3Type); return *reinterpret_cast(&_val); } const glm::quat& getQuat() { assert(_type == QuatType); return *reinterpret_cast(&_val); } @@ -54,10 +59,11 @@ protected: Type _type; union { bool boolVal; + int intVal; float floats[16]; } _val; }; -typedef std::map AnimVarantMap; +typedef std::map AnimVariantMap; #endif // hifi_AnimVariant_h diff --git a/tests/animation/src/AnimTests.cpp b/tests/animation/src/AnimTests.cpp index 82d805d515..a25ce4bc0a 100644 --- a/tests/animation/src/AnimTests.cpp +++ b/tests/animation/src/AnimTests.cpp @@ -80,18 +80,20 @@ void AnimTests::testEvaulate() { float timeScale = 1.0f; float loopFlag = true; + auto vars = AnimVariantMap(); + AnimClip clip(id, url, startFrame, endFrame, timeScale, loopFlag); - clip.evaluate(framesToSec(10.0f)); + clip.evaluate(vars, framesToSec(10.0f)); QCOMPARE_WITH_ABS_ERROR(clip._frame, 12.0f, EPSILON); // does it loop? - clip.evaluate(framesToSec(11.0f)); + clip.evaluate(vars, 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)); + clip.evaluate(vars, framesToSec(20.0f)); QCOMPARE_WITH_ABS_ERROR(clip._frame, 22.0f, EPSILON); } @@ -155,6 +157,7 @@ void AnimTests::testLoader() { void AnimTests::testVariant() { auto defaultVar = AnimVariant(); auto boolVar = AnimVariant(true); + auto intVar = AnimVariant(1); auto floatVar = AnimVariant(1.0f); auto vec3Var = AnimVariant(glm::vec3(1.0f, 2.0f, 3.0f)); auto quatVar = AnimVariant(glm::quat(1.0f, 2.0f, 3.0f, 4.0f)); @@ -168,6 +171,9 @@ void AnimTests::testVariant() { QVERIFY(boolVar.isBool()); QVERIFY(boolVar.getBool() == true); + QVERIFY(intVar.isInt()); + QVERIFY(intVar.getInt() == 1); + QVERIFY(floatVar.isFloat()); QVERIFY(floatVar.getFloat() == 1.0f);