From 30264e9c3dd89d5f6fe36abaf93390b229ee1f34 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 2 Sep 2015 21:04:29 -0700 Subject: [PATCH] Added animation debug draw items to menu. * Debug Draw Bind Pose - used to display the current avatar's bind pose * Debug Draw Animation - used to display the current avatar's AnimGraph animation. Currently does not work with old animation so it's only valid when Enable Anim Graph is true. * Draw Mesh - used to hide or display the avatar mesh. --- interface/src/Menu.cpp | 6 ++ interface/src/Menu.h | 3 + interface/src/avatar/MyAvatar.cpp | 43 +++++++++++++ interface/src/avatar/MyAvatar.h | 7 +++ libraries/animation/src/AnimNode.h | 1 + libraries/animation/src/Rig.h | 4 ++ libraries/render-utils/src/AnimDebugDraw.cpp | 65 +++++++++++++------- libraries/render-utils/src/AnimDebugDraw.h | 10 +-- 8 files changed, 113 insertions(+), 26 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8f6ce50eab..216fa70121 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -435,6 +435,12 @@ Menu::Menu() { avatar, SLOT(setEnableRigAnimations(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableAnimGraph, 0, false, avatar, SLOT(setEnableAnimGraph(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawBindPose, 0, false, + avatar, SLOT(setEnableDebugDrawBindPose(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawAnimPose, 0, false, + avatar, SLOT(setEnableDebugDrawAnimPose(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true, + avatar, SLOT(setEnableMeshVisible(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4a3059259b..3b87de2c43 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -132,6 +132,8 @@ namespace MenuOption { const QString AddRemoveFriends = "Add/Remove Friends..."; const QString AddressBar = "Show Address Bar"; const QString Animations = "Animations..."; + const QString AnimDebugDrawAnimPose = "Debug Draw Animation"; + const QString AnimDebugDrawBindPose = "Debug Draw Bind Pose"; const QString Atmosphere = "Atmosphere"; const QString Attachments = "Attachments..."; const QString AudioNoiseReduction = "Audio Noise Reduction"; @@ -215,6 +217,7 @@ namespace MenuOption { const QString Log = "Log"; const QString LogExtraTimings = "Log Extra Timing Details"; const QString LowVelocityFilter = "Low Velocity Filter"; + const QString MeshVisible = "Draw Mesh"; const QString Mirror = "Mirror"; const QString MuteAudio = "Mute Microphone"; const QString MuteEnvironment = "Mute Environment"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c89a583f32..f6ec1242f2 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "devices/Faceshift.h" @@ -718,6 +719,27 @@ void MyAvatar::setEnableAnimGraph(bool isEnabled) { } } +void MyAvatar::setEnableDebugDrawBindPose(bool isEnabled) { + _enableDebugDrawBindPose = isEnabled; + + if (!isEnabled) { + AnimDebugDraw::getInstance().removeSkeleton("myAvatar"); + } +} + +void MyAvatar::setEnableDebugDrawAnimPose(bool isEnabled) { + _enableDebugDrawAnimPose = isEnabled; + + if (!isEnabled) { + AnimDebugDraw::getInstance().removeAnimNode("myAvatar"); + } +} + +void MyAvatar::setEnableMeshVisible(bool isEnabled) { + render::ScenePointer scene = Application::getInstance()->getMain3DScene(); + _skeletonModel.setVisibleInScene(isEnabled, scene); +} + void MyAvatar::loadData() { Settings settings; settings.beginGroup("Avatar"); @@ -1230,6 +1252,27 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { _skeletonModel.initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry()); } + if (_enableDebugDrawBindPose || _enableDebugDrawAnimPose) { + + AnimSkeleton::ConstPointer animSkeleton = _rig->getAnimSkeleton(); + AnimNode::ConstPointer animNode = _rig->getAnimNode(); + + // bones space is rotated + glm::quat rotY180 = glm::angleAxis((float)M_PI, glm::vec3(0.0f, 1.0f, 0.0f)); + AnimPose xform(glm::vec3(1), rotY180 * getOrientation(), getPosition()); + + if (animSkeleton && _enableDebugDrawBindPose) { + glm::vec4 gray(0.2f, 0.2f, 0.2f, 0.2f); + AnimDebugDraw::getInstance().addSkeleton("myAvatar", animSkeleton, xform, gray); + } + + // This only works for when new anim system is enabled, at the moment. + if (animNode && animSkeleton && _enableDebugDrawAnimPose && _rig->getEnableAnimGraph()) { + glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f); + AnimDebugDraw::getInstance().addAnimNode("myAvatar", animNode, xform, cyan); + } + } + if (shouldDrawHead != _prevShouldDrawHead) { _skeletonModel.setCauterizeBones(!shouldDrawHead); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 25e25e0960..1774eec71f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -190,8 +190,12 @@ public slots: void loadLastRecording(); virtual void rebuildSkeletonBody(); + void setEnableRigAnimations(bool isEnabled); void setEnableAnimGraph(bool isEnabled); + void setEnableDebugDrawBindPose(bool isEnabled); + void setEnableDebugDrawAnimPose(bool isEnabled); + void setEnableMeshVisible(bool isEnabled); signals: void transformChanged(); @@ -314,6 +318,9 @@ private: std::unordered_set _headBoneSet; RigPointer _rig; bool _prevShouldDrawHead; + + bool _enableDebugDrawBindPose = false; + bool _enableDebugDrawAnimPose = false; }; #endif // hifi_MyAvatar_h diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 3a54710b39..4675ae358f 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -43,6 +43,7 @@ public: NumTypes }; using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; using Triggers = std::vector; friend class AnimDebugDraw; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 845878f8a2..109605587e 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -159,6 +159,7 @@ public: void setEnableRig(bool isEnabled) { _enableRig = isEnabled; } void setEnableAnimGraph(bool isEnabled) { _enableAnimGraph = isEnabled; } + bool getEnableAnimGraph() const { return _enableAnimGraph; } void updateFromHeadParameters(const HeadParameters& params); void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, @@ -169,6 +170,9 @@ public: void initAnimGraph(const QUrl& url, const FBXGeometry& fbxGeometry); + AnimNode::ConstPointer getAnimNode() const { return _animNode; } + AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; } + protected: void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index 7bbf656f35..1c0f7e0054 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -80,6 +80,13 @@ static uint32_t toRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { return ((uint32_t)r | (uint32_t)g << 8 | (uint32_t)b << 16 | (uint32_t)a << 24); } +static uint32_t toRGBA(const glm::vec4& v) { + return toRGBA(static_cast(v.r * 255.0f), + static_cast(v.g * 255.0f), + static_cast(v.b * 255.0f), + static_cast(v.a * 255.0f)); +} + gpu::PipelinePointer AnimDebugDraw::_pipeline; AnimDebugDraw::AnimDebugDraw() : @@ -145,16 +152,16 @@ AnimDebugDraw::~AnimDebugDraw() { } } -void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const AnimPose& rootPose) { - _skeletons[key] = SkeletonInfo(skeleton, rootPose); +void AnimDebugDraw::addSkeleton(std::string key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color) { + _skeletons[key] = SkeletonInfo(skeleton, rootPose, color); } void AnimDebugDraw::removeSkeleton(std::string key) { _skeletons.erase(key); } -void AnimDebugDraw::addAnimNode(std::string key, AnimNode::Pointer animNode, const AnimPose& rootPose) { - _animNodes[key] = AnimNodeInfo(animNode, rootPose); +void AnimDebugDraw::addAnimNode(std::string key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color) { + _animNodes[key] = AnimNodeInfo(animNode, rootPose, color); } void AnimDebugDraw::removeAnimNode(std::string key) { @@ -164,7 +171,6 @@ void AnimDebugDraw::removeAnimNode(std::string key) { static const uint32_t red = toRGBA(255, 0, 0, 255); static const uint32_t green = toRGBA(0, 255, 0, 255); static const uint32_t blue = toRGBA(0, 0, 255, 255); -static const uint32_t cyan = toRGBA(0, 128, 128, 255); const int NUM_CIRCLE_SLICES = 24; @@ -182,7 +188,7 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius float rSinTheta = radius * sin(dTheta * i); xRing[i] = finalPose * glm::vec3(0.0f, rCosTheta, rSinTheta); yRing[i] = finalPose * glm::vec3(rCosTheta, 0.0f, rSinTheta); - zRing[i] = finalPose *glm::vec3(rCosTheta, rSinTheta, 0.0f); + zRing[i] = finalPose * glm::vec3(rCosTheta, rSinTheta, 0.0f); } // x-axis @@ -240,8 +246,10 @@ static void addBone(const AnimPose& rootPose, const AnimPose& pose, float radius } } -static void addLink(const AnimPose& rootPose, const AnimPose& pose, - const AnimPose& parentPose, float radius, Vertex*& v) { +static void addLink(const AnimPose& rootPose, const AnimPose& pose, const AnimPose& parentPose, + float radius, const glm::vec4& colorVec, Vertex*& v) { + + uint32_t color = toRGBA(colorVec); AnimPose pose0 = rootPose * parentPose; AnimPose pose1 = rootPose * pose; @@ -271,19 +279,19 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, for (int i = 0; i < NUM_BASE_CORNERS; i++) { v->pos = boneBaseCorners[i]; - v->rgba = cyan; + v->rgba = color; v++; v->pos = boneBaseCorners[(i + 1) % NUM_BASE_CORNERS]; - v->rgba = cyan; + v->rgba = color; v++; } for (int i = 0; i < NUM_BASE_CORNERS; i++) { v->pos = boneBaseCorners[i]; - v->rgba = cyan; + v->rgba = color; v++; v->pos = boneTip; - v->rgba = cyan; + v->rgba = color; v++; } } else { @@ -292,10 +300,10 @@ static void addLink(const AnimPose& rootPose, const AnimPose& pose, // We add the same line multiple times, so the vertex count is correct. for (int i = 0; i < NUM_BASE_CORNERS * 2; i++) { v->pos = pose0.trans; - v->rgba = cyan; + v->rgba = color; v++; v->pos = pose1.trans; - v->rgba = cyan; + v->rgba = color; v++; } } @@ -319,7 +327,7 @@ void AnimDebugDraw::update() { // figure out how many verts we will need. int numVerts = 0; for (auto&& iter : _skeletons) { - AnimSkeleton::Pointer& skeleton = iter.second.first; + AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second); numVerts += skeleton->getNumJoints() * VERTICES_PER_BONE; for (int i = 0; i < skeleton->getNumJoints(); i++) { auto parentIndex = skeleton->getParentIndex(i); @@ -330,7 +338,7 @@ void AnimDebugDraw::update() { } for (auto&& iter : _animNodes) { - AnimNode::Pointer& animNode = iter.second.first; + AnimNode::ConstPointer& animNode = std::get<0>(iter.second); auto poses = animNode->getPosesInternal(); numVerts += poses.size() * VERTICES_PER_BONE; auto skeleton = animNode->getSkeleton(); @@ -346,8 +354,13 @@ void AnimDebugDraw::update() { Vertex* verts = (Vertex*)data._vertexBuffer->editData(); Vertex* v = verts; for (auto&& iter : _skeletons) { - AnimSkeleton::Pointer& skeleton = iter.second.first; - AnimPose& rootPose = iter.second.second; + AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second); + AnimPose rootPose = std::get<1>(iter.second); + int hipsIndex = skeleton->nameToJointIndex("Hips"); + if (hipsIndex >= 0) { + rootPose.trans -= skeleton->getRelativeBindPose(hipsIndex).trans; + } + glm::vec4 color = std::get<2>(iter.second); for (int i = 0; i < skeleton->getNumJoints(); i++) { AnimPose pose = skeleton->getAbsoluteBindPose(i); @@ -362,14 +375,22 @@ void AnimDebugDraw::update() { if (parentIndex >= 0) { assert(parentIndex < skeleton->getNumJoints()); AnimPose parentPose = skeleton->getAbsoluteBindPose(parentIndex); - addLink(rootPose, pose, parentPose, radius, v); + addLink(rootPose, pose, parentPose, radius, color, v); } } } for (auto&& iter : _animNodes) { - AnimNode::Pointer& animNode = iter.second.first; - AnimPose& rootPose = iter.second.second; + AnimNode::ConstPointer& animNode = std::get<0>(iter.second); + AnimPose rootPose = std::get<1>(iter.second); + if (animNode->_skeleton) { + int hipsIndex = animNode->_skeleton->nameToJointIndex("Hips"); + if (hipsIndex >= 0) { + rootPose.trans -= animNode->_skeleton->getRelativeBindPose(hipsIndex).trans; + } + } + glm::vec4 color = std::get<2>(iter.second); + auto poses = animNode->getPosesInternal(); auto skeleton = animNode->getSkeleton(); @@ -392,7 +413,7 @@ void AnimDebugDraw::update() { if (parentIndex >= 0) { assert((size_t)parentIndex < poses.size()); // draw line to parent - addLink(rootPose, absAnimPose[i], absAnimPose[parentIndex], radius, v); + addLink(rootPose, absAnimPose[i], absAnimPose[parentIndex], radius, color, v); } } } diff --git a/libraries/render-utils/src/AnimDebugDraw.h b/libraries/render-utils/src/AnimDebugDraw.h index 34ee9c50c0..489213b80b 100644 --- a/libraries/render-utils/src/AnimDebugDraw.h +++ b/libraries/render-utils/src/AnimDebugDraw.h @@ -10,6 +10,8 @@ #ifndef hifi_AnimDebugDraw_h #define hifi_AnimDebugDraw_h +#include + #include "render/Scene.h" #include "gpu/Pipeline.h" #include "AnimNode.h" @@ -25,10 +27,10 @@ public: AnimDebugDraw(); ~AnimDebugDraw(); - void addSkeleton(std::string key, AnimSkeleton::Pointer skeleton, const AnimPose& rootPose); + void addSkeleton(std::string key, AnimSkeleton::ConstPointer skeleton, const AnimPose& rootPose, const glm::vec4& color); void removeSkeleton(std::string key); - void addAnimNode(std::string key, AnimNode::Pointer skeleton, const AnimPose& rootPose); + void addAnimNode(std::string key, AnimNode::ConstPointer animNode, const AnimPose& rootPose, const glm::vec4& color); void removeAnimNode(std::string key); void update(); @@ -40,8 +42,8 @@ protected: static gpu::PipelinePointer _pipeline; - typedef std::pair SkeletonInfo; - typedef std::pair AnimNodeInfo; + typedef std::tuple SkeletonInfo; + typedef std::tuple AnimNodeInfo; std::unordered_map _skeletons; std::unordered_map _animNodes;