Remove hacks for debug rendering of IK targets

A AnimContext class was introduced.  This context is passed into every node during evaluation/overlay.
It holds non-animVar "global" data passed from the application.
This commit is contained in:
Anthony J. Thibault 2016-09-19 14:58:55 -07:00
parent c77f6a7c16
commit a028d3ba58
20 changed files with 120 additions and 63 deletions

View file

@ -82,9 +82,6 @@ const float MyAvatar::ZOOM_MIN = 0.5f;
const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_MAX = 25.0f;
const float MyAvatar::ZOOM_DEFAULT = 1.5f; const float MyAvatar::ZOOM_DEFAULT = 1.5f;
// OUTOFBODY_HACK defined in Rig.cpp
extern bool OUTOFBODY_HACK_ENABLE_DEBUG_DRAW_IK_TARGETS;
// OUTOFBODY_HACK defined in SkeletonModel.cpp // OUTOFBODY_HACK defined in SkeletonModel.cpp
extern glm::vec3 TRUNCATE_IK_CAPSULE_POSITION; extern glm::vec3 TRUNCATE_IK_CAPSULE_POSITION;
extern float TRUNCATE_IK_CAPSULE_LENGTH; extern float TRUNCATE_IK_CAPSULE_LENGTH;
@ -429,6 +426,11 @@ void MyAvatar::simulate(float deltaTime) {
{ {
PerformanceTimer perfTimer("skeleton"); PerformanceTimer perfTimer("skeleton");
if (_rig) {
_rig->setEnableDebugDrawIKTargets(_enableDebugDrawIKTargets);
}
_skeletonModel->simulate(deltaTime); _skeletonModel->simulate(deltaTime);
} }
@ -859,8 +861,6 @@ void MyAvatar::setEnableDebugDrawSensorToWorldMatrix(bool isEnabled) {
void MyAvatar::setEnableDebugDrawIKTargets(bool isEnabled) { void MyAvatar::setEnableDebugDrawIKTargets(bool isEnabled) {
_enableDebugDrawIKTargets = isEnabled; _enableDebugDrawIKTargets = isEnabled;
OUTOFBODY_HACK_ENABLE_DEBUG_DRAW_IK_TARGETS = isEnabled;
} }

View file

@ -24,7 +24,7 @@ AnimBlendLinear::~AnimBlendLinear() {
} }
const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
_alpha = animVars.lookup(_alphaVar, _alpha); _alpha = animVars.lookup(_alphaVar, _alpha);
@ -33,7 +33,7 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, flo
pose = AnimPose::identity; pose = AnimPose::identity;
} }
} else if (_children.size() == 1) { } else if (_children.size() == 1) {
_poses = _children[0]->evaluate(animVars, dt, triggersOut); _poses = _children[0]->evaluate(animVars, context, dt, triggersOut);
} else { } else {
float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1));
@ -41,7 +41,7 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, flo
size_t nextPoseIndex = glm::ceil(clampedAlpha); size_t nextPoseIndex = glm::ceil(clampedAlpha);
float alpha = glm::fract(clampedAlpha); float alpha = glm::fract(clampedAlpha);
evaluateAndBlendChildren(animVars, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt);
} }
return _poses; return _poses;
} }
@ -51,15 +51,15 @@ const AnimPoseVec& AnimBlendLinear::getPosesInternal() const {
return _poses; return _poses;
} }
void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, Triggers& triggersOut, float alpha, void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, const AnimContext& context, Triggers& triggersOut, float alpha,
size_t prevPoseIndex, size_t nextPoseIndex, float dt) { size_t prevPoseIndex, size_t nextPoseIndex, float dt) {
if (prevPoseIndex == nextPoseIndex) { if (prevPoseIndex == nextPoseIndex) {
// this can happen if alpha is on an integer boundary // this can happen if alpha is on an integer boundary
_poses = _children[prevPoseIndex]->evaluate(animVars, dt, triggersOut); _poses = _children[prevPoseIndex]->evaluate(animVars, context, dt, triggersOut);
} else { } else {
// need to eval and blend between two children. // need to eval and blend between two children.
auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, dt, triggersOut); auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, context, dt, triggersOut);
auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, dt, triggersOut); auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, context, dt, triggersOut);
if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) { if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) {
_poses.resize(prevPoses.size()); _poses.resize(prevPoses.size());

View file

@ -30,7 +30,7 @@ public:
AnimBlendLinear(const QString& id, float alpha); AnimBlendLinear(const QString& id, float alpha);
virtual ~AnimBlendLinear() override; virtual ~AnimBlendLinear() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; }
@ -38,7 +38,7 @@ protected:
// for AnimDebugDraw rendering // for AnimDebugDraw rendering
virtual const AnimPoseVec& getPosesInternal() const override; virtual const AnimPoseVec& getPosesInternal() const override;
void evaluateAndBlendChildren(const AnimVariantMap& animVars, Triggers& triggersOut, float alpha, void evaluateAndBlendChildren(const AnimVariantMap& animVars, const AnimContext& context, Triggers& triggersOut, float alpha,
size_t prevPoseIndex, size_t nextPoseIndex, float dt); size_t prevPoseIndex, size_t nextPoseIndex, float dt);
AnimPoseVec _poses; AnimPoseVec _poses;

View file

@ -26,7 +26,7 @@ AnimBlendLinearMove::~AnimBlendLinearMove() {
} }
const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
assert(_children.size() == _characteristicSpeeds.size()); assert(_children.size() == _characteristicSpeeds.size());
@ -43,7 +43,7 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars,
const int nextPoseIndex = 0; const int nextPoseIndex = 0;
float prevDeltaTime, nextDeltaTime; float prevDeltaTime, nextDeltaTime;
setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut); setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut);
evaluateAndBlendChildren(animVars, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime);
} else { } else {
auto clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); auto clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1));
@ -52,7 +52,7 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars,
auto alpha = glm::fract(clampedAlpha); auto alpha = glm::fract(clampedAlpha);
float prevDeltaTime, nextDeltaTime; float prevDeltaTime, nextDeltaTime;
setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut); setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut);
evaluateAndBlendChildren(animVars, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime); evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime);
} }
return _poses; return _poses;
} }
@ -62,16 +62,16 @@ const AnimPoseVec& AnimBlendLinearMove::getPosesInternal() const {
return _poses; return _poses;
} }
void AnimBlendLinearMove::evaluateAndBlendChildren(const AnimVariantMap& animVars, Triggers& triggersOut, float alpha, void AnimBlendLinearMove::evaluateAndBlendChildren(const AnimVariantMap& animVars, const AnimContext& context, Triggers& triggersOut, float alpha,
size_t prevPoseIndex, size_t nextPoseIndex, size_t prevPoseIndex, size_t nextPoseIndex,
float prevDeltaTime, float nextDeltaTime) { float prevDeltaTime, float nextDeltaTime) {
if (prevPoseIndex == nextPoseIndex) { if (prevPoseIndex == nextPoseIndex) {
// this can happen if alpha is on an integer boundary // this can happen if alpha is on an integer boundary
_poses = _children[prevPoseIndex]->evaluate(animVars, prevDeltaTime, triggersOut); _poses = _children[prevPoseIndex]->evaluate(animVars, context, prevDeltaTime, triggersOut);
} else { } else {
// need to eval and blend between two children. // need to eval and blend between two children.
auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, prevDeltaTime, triggersOut); auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, context, prevDeltaTime, triggersOut);
auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, nextDeltaTime, triggersOut); auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, context, nextDeltaTime, triggersOut);
if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) { if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) {
_poses.resize(prevPoses.size()); _poses.resize(prevPoses.size());

View file

@ -39,7 +39,7 @@ public:
AnimBlendLinearMove(const QString& id, float alpha, float desiredSpeed, const std::vector<float>& characteristicSpeeds); AnimBlendLinearMove(const QString& id, float alpha, float desiredSpeed, const std::vector<float>& characteristicSpeeds);
virtual ~AnimBlendLinearMove() override; virtual ~AnimBlendLinearMove() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; }
void setDesiredSpeedVar(const QString& desiredSpeedVar) { _desiredSpeedVar = desiredSpeedVar; } void setDesiredSpeedVar(const QString& desiredSpeedVar) { _desiredSpeedVar = desiredSpeedVar; }
@ -48,7 +48,7 @@ protected:
// for AnimDebugDraw rendering // for AnimDebugDraw rendering
virtual const AnimPoseVec& getPosesInternal() const override; virtual const AnimPoseVec& getPosesInternal() const override;
void evaluateAndBlendChildren(const AnimVariantMap& animVars, Triggers& triggersOut, float alpha, void evaluateAndBlendChildren(const AnimVariantMap& animVars, const AnimContext& context, Triggers& triggersOut, float alpha,
size_t prevPoseIndex, size_t nextPoseIndex, size_t prevPoseIndex, size_t nextPoseIndex,
float prevDeltaTime, float nextDeltaTime); float prevDeltaTime, float nextDeltaTime);

View file

@ -31,7 +31,7 @@ AnimClip::~AnimClip() {
} }
const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
// lookup parameters from animVars, using current instance variables as defaults. // lookup parameters from animVars, using current instance variables as defaults.
_startFrame = animVars.lookup(_startFrameVar, _startFrame); _startFrame = animVars.lookup(_startFrameVar, _startFrame);

View file

@ -30,7 +30,7 @@ public:
AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag); AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag);
virtual ~AnimClip() override; virtual ~AnimClip() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
void setStartFrameVar(const QString& startFrameVar) { _startFrameVar = startFrameVar; } void setStartFrameVar(const QString& startFrameVar) { _startFrameVar = startFrameVar; }
void setEndFrameVar(const QString& endFrameVar) { _endFrameVar = endFrameVar; } void setEndFrameVar(const QString& endFrameVar) { _endFrameVar = endFrameVar; }

View file

@ -0,0 +1,16 @@
//
// AnimContext.cpp
//
// Created by Anthony J. Thibault on 9/19/16.
// Copyright (c) 2016 High Fidelity, Inc. All rights reserved.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "AnimContext.h"
AnimContext::AnimContext(bool enableDebugDrawIKTargets, const glm::mat4& geometryToRigMatrix) :
_enableDebugDrawIKTargets(enableDebugDrawIKTargets),
_geometryToRigMatrix(geometryToRigMatrix) {
}

View file

@ -0,0 +1,30 @@
//
// AnimContext.h
//
// Created by Anthony J. Thibault on 9/19/16.
// Copyright (c) 2016 High Fidelity, Inc. All rights reserved.
//
// 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_AnimContext_h
#define hifi_AnimContext_h
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
class AnimContext {
public:
AnimContext(bool enableDebugDrawIKTargets, const glm::mat4& geometryToRigMatrix);
bool getEnableDebugDrawIKTargets() const { return _enableDebugDrawIKTargets; }
const glm::mat4& getGeometryToRigMatrix() const { return _geometryToRigMatrix; }
protected:
bool _enableDebugDrawIKTargets { false };
glm::mat4 _geometryToRigMatrix;
};
#endif // hifi_AnimContext_h

View file

@ -21,9 +21,6 @@
#include "SwingTwistConstraint.h" #include "SwingTwistConstraint.h"
#include "AnimationLogging.h" #include "AnimationLogging.h"
bool OUTOFBODY_HACK_ENABLE_DEBUG_DRAW_IK_TARGETS = false;
Rig* OUTOFBODY_HACK_RIG_POINTER = nullptr;
AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) { AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) {
} }
@ -381,14 +378,14 @@ int AnimInverseKinematics::solveTargetWithCCD(const IKTarget& target, AnimPoseVe
} }
//virtual //virtual
const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) { const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimNode::Triggers& triggersOut) {
// don't call this function, call overlay() instead // don't call this function, call overlay() instead
assert(false); assert(false);
return _relativePoses; return _relativePoses;
} }
//virtual //virtual
const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
const float MAX_OVERLAY_DT = 1.0f / 30.0f; // what to clamp delta-time to in AnimInverseKinematics::overlay const float MAX_OVERLAY_DT = 1.0f / 30.0f; // what to clamp delta-time to in AnimInverseKinematics::overlay
if (dt > MAX_OVERLAY_DT) { if (dt > MAX_OVERLAY_DT) {
@ -442,19 +439,27 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
computeTargets(animVars, targets, underPoses); computeTargets(animVars, targets, underPoses);
} }
if (OUTOFBODY_HACK_ENABLE_DEBUG_DRAW_IK_TARGETS && OUTOFBODY_HACK_RIG_POINTER) { // debug render ik targets
if (context.getEnableDebugDrawIKTargets()) {
const vec4 WHITE(1.0f); const vec4 WHITE(1.0f);
glm::mat4 geomToRigMat = OUTOFBODY_HACK_RIG_POINTER->getGeometryToRigTransform();
glm::mat4 rigToAvatarMat = createMatFromQuatAndPos(Quaternions::Y_180, glm::vec3()); glm::mat4 rigToAvatarMat = createMatFromQuatAndPos(Quaternions::Y_180, glm::vec3());
for (auto& target : targets) { for (auto& target : targets) {
glm::mat4 geomTargetMat = createMatFromQuatAndPos(target.getRotation(), target.getTranslation()); glm::mat4 geomTargetMat = createMatFromQuatAndPos(target.getRotation(), target.getTranslation());
glm::mat4 avatarTargetMat = rigToAvatarMat * geomToRigMat * geomTargetMat; glm::mat4 avatarTargetMat = rigToAvatarMat * context.getGeometryToRigMatrix() * geomTargetMat;
std::string name = "ikTarget" + std::to_string(target.getIndex()); std::string name = "ikTarget" + std::to_string(target.getIndex());
DebugDraw::getInstance().addMyAvatarMarker(name, glmExtractRotation(avatarTargetMat), extractTranslation(avatarTargetMat), WHITE); DebugDraw::getInstance().addMyAvatarMarker(name, glmExtractRotation(avatarTargetMat), extractTranslation(avatarTargetMat), WHITE);
} }
} else if (context.getEnableDebugDrawIKTargets() != _previousEnableDebugIKTargets) {
// remove markers if they were added last frame.
for (auto& target : targets) {
std::string name = "ikTarget" + std::to_string(target.getIndex());
DebugDraw::getInstance().removeMyAvatarMarker(name);
} }
}
_previousEnableDebugIKTargets = context.getEnableDebugDrawIKTargets();
if (targets.empty()) { if (targets.empty()) {
// no IK targets but still need to enforce constraints // no IK targets but still need to enforce constraints

View file

@ -34,8 +34,8 @@ public:
void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, const QString& typeVar); void setTargetVars(const QString& jointName, const QString& positionVar, const QString& rotationVar, const QString& typeVar);
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, AnimNode::Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimNode::Triggers& triggersOut) override;
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override;
void clearIKJointLimitHistory(); void clearIKJointLimitHistory();
@ -93,6 +93,8 @@ protected:
// _maxTargetIndex is tracked to help optimize the recalculation of absolute poses // _maxTargetIndex is tracked to help optimize the recalculation of absolute poses
// during the the cyclic coordinate descent algorithm // during the the cyclic coordinate descent algorithm
int _maxTargetIndex { 0 }; int _maxTargetIndex { 0 };
bool _previousEnableDebugIKTargets { false };
}; };
#endif // hifi_AnimInverseKinematics_h #endif // hifi_AnimInverseKinematics_h

View file

@ -22,11 +22,11 @@ AnimManipulator::~AnimManipulator() {
} }
const AnimPoseVec& AnimManipulator::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { const AnimPoseVec& AnimManipulator::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
return overlay(animVars, dt, triggersOut, _skeleton->getRelativeBindPoses()); return overlay(animVars, context, dt, triggersOut, _skeleton->getRelativeBindPoses());
} }
const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { const AnimPoseVec& AnimManipulator::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
_alpha = animVars.lookup(_alphaVar, _alpha); _alpha = animVars.lookup(_alphaVar, _alpha);
_poses = underPoses; _poses = underPoses;

View file

@ -22,8 +22,8 @@ public:
AnimManipulator(const QString& id, float alpha); AnimManipulator(const QString& id, float alpha);
virtual ~AnimManipulator() override; virtual ~AnimManipulator() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override; virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) override;
void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; }

View file

@ -20,6 +20,7 @@
#include "AnimSkeleton.h" #include "AnimSkeleton.h"
#include "AnimVariant.h" #include "AnimVariant.h"
#include "AnimContext.h"
class QJsonObject; class QJsonObject;
@ -72,9 +73,10 @@ public:
AnimSkeleton::ConstPointer getSkeleton() const { return _skeleton; } AnimSkeleton::ConstPointer getSkeleton() const { return _skeleton; }
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) = 0; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) = 0;
virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) { virtual const AnimPoseVec& overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut,
return evaluate(animVars, dt, triggersOut); const AnimPoseVec& underPoses) {
return evaluate(animVars, context, dt, triggersOut);
} }
void setCurrentFrame(float frame); void setCurrentFrame(float frame);

View file

@ -39,7 +39,7 @@ void AnimOverlay::buildBoneSet(BoneSet boneSet) {
} }
} }
const AnimPoseVec& AnimOverlay::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { const AnimPoseVec& AnimOverlay::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
// lookup parameters from animVars, using current instance variables as defaults. // lookup parameters from animVars, using current instance variables as defaults.
// NOTE: switching bonesets can be an expensive operation, let's try to avoid it. // NOTE: switching bonesets can be an expensive operation, let's try to avoid it.
@ -51,8 +51,8 @@ const AnimPoseVec& AnimOverlay::evaluate(const AnimVariantMap& animVars, float d
_alpha = animVars.lookup(_alphaVar, _alpha); _alpha = animVars.lookup(_alphaVar, _alpha);
if (_children.size() >= 2) { if (_children.size() >= 2) {
auto& underPoses = _children[1]->evaluate(animVars, dt, triggersOut); auto& underPoses = _children[1]->evaluate(animVars, context, dt, triggersOut);
auto& overPoses = _children[0]->overlay(animVars, dt, triggersOut, underPoses); auto& overPoses = _children[0]->overlay(animVars, context, dt, triggersOut, underPoses);
if (underPoses.size() > 0 && underPoses.size() == overPoses.size()) { if (underPoses.size() > 0 && underPoses.size() == overPoses.size()) {
_poses.resize(underPoses.size()); _poses.resize(underPoses.size());

View file

@ -43,7 +43,7 @@ public:
AnimOverlay(const QString& id, BoneSet boneSet, float alpha); AnimOverlay(const QString& id, BoneSet boneSet, float alpha);
virtual ~AnimOverlay() override; virtual ~AnimOverlay() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
void setBoneSetVar(const QString& boneSetVar) { _boneSetVar = boneSetVar; } void setBoneSetVar(const QString& boneSetVar) { _boneSetVar = boneSetVar; }
void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; }

View file

@ -21,7 +21,7 @@ AnimStateMachine::~AnimStateMachine() {
} }
const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) { const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
QString desiredStateID = animVars.lookup(_currentStateVar, _currentState->getID()); QString desiredStateID = animVars.lookup(_currentStateVar, _currentState->getID());
if (_currentState->getID() != desiredStateID) { if (_currentState->getID() != desiredStateID) {
@ -29,7 +29,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
bool foundState = false; bool foundState = false;
for (auto& state : _states) { for (auto& state : _states) {
if (state->getID() == desiredStateID) { if (state->getID() == desiredStateID) {
switchState(animVars, state); switchState(animVars, context, state);
foundState = true; foundState = true;
break; break;
} }
@ -42,7 +42,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
// evaluate currentState transitions // evaluate currentState transitions
auto desiredState = evaluateTransitions(animVars); auto desiredState = evaluateTransitions(animVars);
if (desiredState != _currentState) { if (desiredState != _currentState) {
switchState(animVars, desiredState); switchState(animVars, context, desiredState);
} }
assert(_currentState); assert(_currentState);
@ -62,7 +62,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
} else if (_interpType == InterpType::SnapshotPrev) { } else if (_interpType == InterpType::SnapshotPrev) {
// interp between the prev snapshot and evaluated next target. // interp between the prev snapshot and evaluated next target.
// this is useful for interping into a blend // this is useful for interping into a blend
localNextPoses = currentStateNode->evaluate(animVars, dt, triggersOut); localNextPoses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
prevPoses = &_prevPoses; prevPoses = &_prevPoses;
nextPoses = &localNextPoses; nextPoses = &localNextPoses;
} else { } else {
@ -79,7 +79,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
} }
} }
if (!_duringInterp) { if (!_duringInterp) {
_poses = currentStateNode->evaluate(animVars, dt, triggersOut); _poses = currentStateNode->evaluate(animVars, context, dt, triggersOut);
} }
return _poses; return _poses;
} }
@ -92,7 +92,7 @@ void AnimStateMachine::addState(State::Pointer state) {
_states.push_back(state); _states.push_back(state);
} }
void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointer desiredState) { void AnimStateMachine::switchState(const AnimVariantMap& animVars, const AnimContext& context, State::Pointer desiredState) {
const float FRAMES_PER_SECOND = 30.0f; const float FRAMES_PER_SECOND = 30.0f;
@ -114,7 +114,7 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointe
_prevPoses = _poses; _prevPoses = _poses;
// snapshot next pose at the target frame. // snapshot next pose at the target frame.
nextStateNode->setCurrentFrame(desiredState->_interpTarget); nextStateNode->setCurrentFrame(desiredState->_interpTarget);
_nextPoses = nextStateNode->evaluate(animVars, dt, triggers); _nextPoses = nextStateNode->evaluate(animVars, context, dt, triggers);
} else if (_interpType == InterpType::SnapshotPrev) { } else if (_interpType == InterpType::SnapshotPrev) {
// snapshot previoius pose // snapshot previoius pose
_prevPoses = _poses; _prevPoses = _poses;

View file

@ -113,7 +113,7 @@ public:
explicit AnimStateMachine(const QString& id); explicit AnimStateMachine(const QString& id);
virtual ~AnimStateMachine() override; virtual ~AnimStateMachine() override;
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, float dt, Triggers& triggersOut) override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; } void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; }
@ -123,7 +123,7 @@ protected:
void addState(State::Pointer state); void addState(State::Pointer state);
void switchState(const AnimVariantMap& animVars, State::Pointer desiredState); void switchState(const AnimVariantMap& animVars, const AnimContext& context, State::Pointer desiredState);
State::Pointer evaluateTransitions(const AnimVariantMap& animVars) const; State::Pointer evaluateTransitions(const AnimVariantMap& animVars) const;
// for AnimDebugDraw rendering // for AnimDebugDraw rendering

View file

@ -47,8 +47,6 @@ const glm::vec3 DEFAULT_LEFT_EYE_POS(0.3f, 0.9f, 0.0f);
const glm::vec3 DEFAULT_HEAD_POS(0.0f, 0.75f, 0.0f); const glm::vec3 DEFAULT_HEAD_POS(0.0f, 0.75f, 0.0f);
const glm::vec3 DEFAULT_NECK_POS(0.0f, 0.70f, 0.0f); const glm::vec3 DEFAULT_NECK_POS(0.0f, 0.70f, 0.0f);
extern Rig* OUTOFBODY_HACK_RIG_POINTER;
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
UserAnimState::ClipNodeEnum clipNodeEnum; UserAnimState::ClipNodeEnum clipNodeEnum;
@ -887,10 +885,11 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
updateAnimationStateHandlers(); updateAnimationStateHandlers();
_animVars.setRigToGeometryTransform(_rigToGeometryTransform); _animVars.setRigToGeometryTransform(_rigToGeometryTransform);
AnimContext context(_enableDebugDrawIKTargets, getGeometryToRigTransform());
// evaluate the animation // evaluate the animation
OUTOFBODY_HACK_RIG_POINTER = this;
AnimNode::Triggers triggersOut; AnimNode::Triggers triggersOut;
_internalPoseSet._relativePoses = _animNode->evaluate(_animVars, deltaTime, triggersOut); _internalPoseSet._relativePoses = _animNode->evaluate(_animVars, context, deltaTime, triggersOut);
if ((int)_internalPoseSet._relativePoses.size() != _animSkeleton->getNumJoints()) { if ((int)_internalPoseSet._relativePoses.size() != _animSkeleton->getNumJoints()) {
// animations haven't fully loaded yet. // animations haven't fully loaded yet.
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
@ -899,7 +898,6 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) {
for (auto& trigger : triggersOut) { for (auto& trigger : triggersOut) {
_animVars.setTrigger(trigger); _animVars.setTrigger(trigger);
} }
OUTOFBODY_HACK_RIG_POINTER = nullptr;
} }
applyOverridePoses(); applyOverridePoses();
@ -1365,9 +1363,10 @@ void Rig::computeAvatarBoundingCapsule(
// call overlay twice: once to verify AnimPoseVec joints and again to do the IK // call overlay twice: once to verify AnimPoseVec joints and again to do the IK
AnimNode::Triggers triggersOut; AnimNode::Triggers triggersOut;
AnimContext context(false, glm::mat4());
float dt = 1.0f; // the value of this does not matter float dt = 1.0f; // the value of this does not matter
ikNode.overlay(animVars, dt, triggersOut, _animSkeleton->getRelativeBindPoses()); ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses());
AnimPoseVec finalPoses = ikNode.overlay(animVars, dt, triggersOut, _animSkeleton->getRelativeBindPoses()); AnimPoseVec finalPoses = ikNode.overlay(animVars, context, dt, triggersOut, _animSkeleton->getRelativeBindPoses());
// convert relative poses to absolute // convert relative poses to absolute
_animSkeleton->convertRelativePosesToAbsolute(finalPoses); _animSkeleton->convertRelativePosesToAbsolute(finalPoses);

View file

@ -211,6 +211,8 @@ public:
const glm::mat4& getGeometryToRigTransform() const { return _geometryToRigTransform; } const glm::mat4& getGeometryToRigTransform() const { return _geometryToRigTransform; }
void setEnableDebugDrawIKTargets(bool enableDebugDrawIKTargets) { _enableDebugDrawIKTargets = enableDebugDrawIKTargets; }
signals: signals:
void onLoadComplete(); void onLoadComplete();
@ -315,6 +317,7 @@ protected:
mutable uint32_t _jointNameWarningCount { 0 }; mutable uint32_t _jointNameWarningCount { 0 };
glm::vec3 _desiredRigHeadPosition; glm::vec3 _desiredRigHeadPosition;
bool _truncateIKTargets { false }; bool _truncateIKTargets { false };
bool _enableDebugDrawIKTargets { false };
private: private:
QMap<int, StateHandler> _stateHandlers; QMap<int, StateHandler> _stateHandlers;