Better debug rendering of animations.

* added mat4 cast and mat4 ctors to AnimPose.
This commit is contained in:
Anthony J. Thibault 2015-08-02 15:22:30 -07:00 committed by Anthony J. Thibault
parent df79463750
commit 55da34f713
5 changed files with 83 additions and 23 deletions

View file

@ -1221,11 +1221,13 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
joints.push_back(joint);
}
auto skeleton = make_shared<AnimSkeleton>(joints);
//AnimDebugDraw::getInstance().addSkeleton("my-avatar", skeleton, AnimPose::identity);
AnimPose xform(glm::vec3(0.01f), glm::quat(), glm::vec3(0.0));
AnimDebugDraw::getInstance().addSkeleton("my-avatar", skeleton, xform);
_animNode = make_shared<AnimClip>("clip", "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx", 0.0f, 90.0f, 1.0f, true);
_animNode->setSkeleton(skeleton);
AnimDebugDraw::getInstance().addAnimNode("clip", _animNode, AnimPose::identity);
xform.trans.z += 1.0f;
AnimDebugDraw::getInstance().addAnimNode("clip", _animNode, xform);
}
if (shouldDrawHead != _prevShouldDrawHead) {

View file

@ -138,18 +138,18 @@ void AnimClip::copyFromNetworkAnim() {
_anim.resize(frameCount);
for (int i = 0; i < frameCount; i++) {
// init all joints in animation to bind pose
// init all joints in animation to relative bind pose
_anim[i].reserve(skeletonJointCount);
for (int j = 0; j < skeletonJointCount; j++) {
_anim[i].push_back(_skeleton->getBindPose(j));
_anim[i].push_back(_skeleton->getRelativeBindPose(j));
}
// init over all joint animations
for (int j = 0; j < animJointCount; j++) {
int k = jointMap[j];
if (k >= 0 && k < skeletonJointCount) {
// currently animations only have rotation.
_anim[i][k].rot = geom.animationFrames[i].rotations[j];
// currently FBX animations only have rotation.
_anim[i][k].rot = _skeleton->getRelativeBindPose(k).rot * geom.animationFrames[i].rotations[j];
}
}
}

View file

@ -14,15 +14,38 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
glm::quat(),
glm::vec3(0.0f));
AnimPose::AnimPose(const glm::mat4& mat) {
scale = extractScale(mat);
rot = glm::quat_cast(mat);
trans = extractTranslation(mat);
}
AnimPose::operator glm::mat4() const {
glm::vec3 xAxis = rot * glm::vec3(scale.x, 0.0f, 0.0f);
glm::vec3 yAxis = rot * glm::vec3(0.0f, scale.y, 0.0f);
glm::vec3 zAxis = rot * glm::vec3(0.0f, 0.0f, scale.z);
return glm::mat4(glm::vec4(xAxis, 0.0f), glm::vec4(yAxis, 0.0f),
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
}
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
_joints = joints;
// build a cache of bind poses
_bindPoses.reserve(joints.size());
_absoluteBindPoses.reserve(joints.size());
_relativeBindPoses.reserve(joints.size());
for (size_t i = 0; i < joints.size(); i++) {
_bindPoses.push_back(AnimPose(extractScale(_joints[i].bindTransform),
glm::quat_cast(_joints[i].bindTransform),
extractTranslation(_joints[i].bindTransform)));
glm::mat4 absBindMat = _joints[i].bindTransform;
AnimPose absBindPose(_joints[i].bindTransform);
_absoluteBindPoses.push_back(absBindPose);
int parentIndex = getParentIndex(i);
if (parentIndex >= 0) {
glm::mat4 invParentAbsBindMat = glm::inverse(_joints[parentIndex].bindTransform);
glm::mat4 relBindMat = invParentAbsBindMat * absBindMat;
_relativeBindPoses.push_back(AnimPose(relBindMat));
} else {
_relativeBindPoses.push_back(absBindPose);
}
}
}
@ -39,8 +62,12 @@ int AnimSkeleton::getNumJoints() const {
return _joints.size();
}
AnimPose AnimSkeleton::getBindPose(int jointIndex) const {
return _bindPoses[jointIndex];
AnimPose AnimSkeleton::getAbsoluteBindPose(int jointIndex) const {
return _absoluteBindPoses[jointIndex];
}
AnimPose AnimSkeleton::getRelativeBindPose(int jointIndex) const {
return _relativeBindPoses[jointIndex];
}
int AnimSkeleton::getParentIndex(int jointIndex) const {

View file

@ -16,13 +16,20 @@
struct AnimPose {
AnimPose() {}
AnimPose(const glm::mat4& mat);
AnimPose(const glm::vec3& scaleIn, const glm::quat& rotIn, const glm::vec3& transIn) : scale(scaleIn), rot(rotIn), trans(transIn) {}
static const AnimPose identity;
glm::vec3 operator*(const glm::vec3& pos) const {
return trans + (rot * (scale * pos));
glm::vec3 operator*(const glm::vec3& rhs) const {
return trans + (rot * (scale * rhs));
}
AnimPose operator*(const AnimPose& rhs) const {
return AnimPose(static_cast<glm::mat4>(*this) * static_cast<glm::mat4>(rhs));
}
operator glm::mat4() const;
glm::vec3 scale;
glm::quat rot;
glm::vec3 trans;
@ -35,12 +42,19 @@ public:
AnimSkeleton(const std::vector<FBXJoint>& joints);
int nameToJointIndex(const QString& jointName) const;
int getNumJoints() const;
AnimPose getBindPose(int jointIndex) const;
// absolute pose, not relative to parent
AnimPose getAbsoluteBindPose(int jointIndex) const;
// relative to parent pose
AnimPose getRelativeBindPose(int jointIndex) const;
int getParentIndex(int jointIndex) const;
protected:
std::vector<FBXJoint> _joints;
std::vector<AnimPose> _bindPoses;
std::vector<AnimPose> _absoluteBindPoses;
std::vector<AnimPose> _relativeBindPoses;
};
#endif

View file

@ -228,15 +228,12 @@ void AnimDebugDraw::update() {
AnimNode::Pointer& animNode = iter.second.first;
auto poses = animNode->getPosesInternal();
numVerts += poses.size() * 6;
/*
auto skeleton = animNode->getSkeleton();
for (int i = 0; i < poses.size(); i++) {
// TODO: need skeleton!
if (skeleton->getParentIndex(i) >= 0) {
numVerts += 2;
}
}
*/
}
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);
@ -245,8 +242,9 @@ void AnimDebugDraw::update() {
for (auto&& iter : _skeletons) {
AnimSkeleton::Pointer& skeleton = iter.second.first;
AnimPose& rootPose = iter.second.second;
for (int i = 0; i < skeleton->getNumJoints(); i++) {
AnimPose pose = skeleton->getBindPose(i);
AnimPose pose = skeleton->getAbsoluteBindPose(i);
// draw axes
const float radius = 1.0f;
@ -254,7 +252,7 @@ void AnimDebugDraw::update() {
// line to parent.
if (skeleton->getParentIndex(i) >= 0) {
AnimPose parentPose = skeleton->getBindPose(skeleton->getParentIndex(i));
AnimPose parentPose = skeleton->getAbsoluteBindPose(skeleton->getParentIndex(i));
addWireframeBoneAxis(rootPose, pose, parentPose, radius, v);
}
}
@ -264,10 +262,29 @@ void AnimDebugDraw::update() {
AnimNode::Pointer& animNode = iter.second.first;
AnimPose& rootPose = iter.second.second;
auto poses = animNode->getPosesInternal();
auto skeleton = animNode->getSkeleton();
std::vector<AnimPose> absAnimPose;
absAnimPose.reserve(skeleton->getNumJoints());
for (size_t i = 0; i < poses.size(); i++) {
auto parentIndex = skeleton->getParentIndex(i);
if (parentIndex >= 0) {
absAnimPose[i] = absAnimPose[parentIndex] * poses[i];
} else {
absAnimPose[i] = poses[i];
}
// draw axes
const float radius = 1.0f;
addWireframeSphereWithAxes(rootPose, poses[i], radius, v);
addWireframeSphereWithAxes(rootPose, absAnimPose[i], radius, v);
if (parentIndex >= 0) {
// draw line to parent
addWireframeBoneAxis(rootPose, absAnimPose[i], absAnimPose[parentIndex], radius, v);
}
}
}