mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 17:10:41 +02:00
Got to the bottom of the bind pose question.
When TRUST_BIND_TRANSFORM is defined in AnimSkeleton, the bind pose is taken from the FBXJoint::bindTransform field, which is correct for all joints bound to actual geometry. Basically it's not trust worthy for bones NOT bound to anything. When TRUST_BIND_TRANSFORM is not defined, the bind pose is taken from the other FBXJoint fields. Unfortunatly these poses are NOT the bind pose, but instead are taken from the FBX files 'resting' pose. i.e. frame 0.
This commit is contained in:
parent
d8a20340a0
commit
559367db4a
4 changed files with 49 additions and 26 deletions
|
@ -1221,7 +1221,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
|
||||||
joints.push_back(joint);
|
joints.push_back(joint);
|
||||||
}
|
}
|
||||||
auto skeleton = make_shared<AnimSkeleton>(joints);
|
auto skeleton = make_shared<AnimSkeleton>(joints);
|
||||||
AnimPose xform(glm::vec3(1.0f), glm::quat(), glm::vec3(0.0));
|
AnimPose xform(_skeletonModel.getScale(), glm::quat(), _skeletonModel.getOffset());
|
||||||
AnimDebugDraw::getInstance().addSkeleton("my-avatar", skeleton, xform);
|
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 = make_shared<AnimClip>("clip", "https://hifi-public.s3.amazonaws.com/ozan/support/FightClubBotTest1/Animations/standard_idle.fbx", 0.0f, 90.0f, 1.0f, true);
|
||||||
|
|
|
@ -138,10 +138,10 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
_anim.resize(frameCount);
|
_anim.resize(frameCount);
|
||||||
for (int i = 0; i < frameCount; i++) {
|
for (int i = 0; i < frameCount; i++) {
|
||||||
|
|
||||||
// init all joints in animation to identity
|
// init all joints in animation to bind pose
|
||||||
_anim[i].reserve(skeletonJointCount);
|
_anim[i].reserve(skeletonJointCount);
|
||||||
for (int j = 0; j < skeletonJointCount; j++) {
|
for (int j = 0; j < skeletonJointCount; j++) {
|
||||||
_anim[i].push_back(AnimPose::identity);
|
_anim[i].push_back(_skeleton->getRelativeBindPose(j));
|
||||||
}
|
}
|
||||||
|
|
||||||
// init over all joint animations
|
// init over all joint animations
|
||||||
|
@ -149,7 +149,7 @@ void AnimClip::copyFromNetworkAnim() {
|
||||||
int k = jointMap[j];
|
int k = jointMap[j];
|
||||||
if (k >= 0 && k < skeletonJointCount) {
|
if (k >= 0 && k < skeletonJointCount) {
|
||||||
// currently FBX animations only have rotation.
|
// currently FBX animations only have rotation.
|
||||||
_anim[i][k].rot = geom.animationFrames[i].rotations[j];
|
_anim[i][k].rot = _skeleton->getRelativeBindPose(j).rot * geom.animationFrames[i].rotations[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "AnimSkeleton.h"
|
#include "AnimSkeleton.h"
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
#include "glmHelpers.h"
|
#include "glmHelpers.h"
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
|
const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
|
||||||
glm::quat(),
|
glm::quat(),
|
||||||
|
@ -17,7 +19,7 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
|
||||||
|
|
||||||
AnimPose::AnimPose(const glm::mat4& mat) {
|
AnimPose::AnimPose(const glm::mat4& mat) {
|
||||||
scale = extractScale(mat);
|
scale = extractScale(mat);
|
||||||
rot = glm::normalize(glm::quat_cast(mat));
|
rot = extractRotation(mat);
|
||||||
trans = extractTranslation(mat);
|
trans = extractTranslation(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +43,7 @@ AnimPose::operator glm::mat4() const {
|
||||||
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#define TRUST_BIND_TRANSFORM
|
||||||
|
|
||||||
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
||||||
_joints = joints;
|
_joints = joints;
|
||||||
|
@ -50,9 +53,31 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
||||||
_relativeBindPoses.reserve(joints.size());
|
_relativeBindPoses.reserve(joints.size());
|
||||||
for (size_t i = 0; i < joints.size(); i++) {
|
for (size_t i = 0; i < joints.size(); i++) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
// AJT: dump the skeleton, because wtf.
|
||||||
|
qCDebug(animation) << getJointName(i);
|
||||||
|
qCDebug(animation) << " isFree =" << _joints[i].isFree;
|
||||||
|
qCDebug(animation) << " freeLineage =" << _joints[i].freeLineage;
|
||||||
|
qCDebug(animation) << " parentIndex =" << _joints[i].parentIndex;
|
||||||
|
qCDebug(animation) << " boneRadius =" << _joints[i].boneRadius;
|
||||||
|
qCDebug(animation) << " translation =" << _joints[i].translation;
|
||||||
|
qCDebug(animation) << " preTransform =" << _joints[i].preTransform;
|
||||||
|
qCDebug(animation) << " preRotation =" << _joints[i].preRotation;
|
||||||
|
qCDebug(animation) << " rotation =" << _joints[i].rotation;
|
||||||
|
qCDebug(animation) << " postRotation =" << _joints[i].postRotation;
|
||||||
|
qCDebug(animation) << " postTransform =" << _joints[i].postTransform;
|
||||||
|
qCDebug(animation) << " transform =" << _joints[i].transform;
|
||||||
|
qCDebug(animation) << " rotationMin =" << _joints[i].rotationMin << ", rotationMax =" << _joints[i].rotationMax;
|
||||||
|
qCDebug(animation) << " inverseDefaultRotation" << _joints[i].inverseDefaultRotation;
|
||||||
|
qCDebug(animation) << " inverseBindRotation" << _joints[i].inverseBindRotation;
|
||||||
|
qCDebug(animation) << " bindTransform" << _joints[i].bindTransform;
|
||||||
|
qCDebug(animation) << " isSkeletonJoint" << _joints[i].isSkeletonJoint;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef TRUST_BIND_TRANSFORM
|
||||||
|
// trust FBXJoint::bindTransform (which is wrong for joints NOT bound to anything)
|
||||||
AnimPose absoluteBindPose(_joints[i].bindTransform);
|
AnimPose absoluteBindPose(_joints[i].bindTransform);
|
||||||
_absoluteBindPoses.push_back(absoluteBindPose);
|
_absoluteBindPoses.push_back(absoluteBindPose);
|
||||||
|
|
||||||
int parentIndex = getParentIndex(i);
|
int parentIndex = getParentIndex(i);
|
||||||
if (parentIndex >= 0) {
|
if (parentIndex >= 0) {
|
||||||
AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse();
|
AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse();
|
||||||
|
@ -60,24 +85,24 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
||||||
} else {
|
} else {
|
||||||
_relativeBindPoses.push_back(absoluteBindPose);
|
_relativeBindPoses.push_back(absoluteBindPose);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
// AJT:
|
// trust FBXJoint's local transforms (which is not really the bind pose, but the default pose in the fbx)
|
||||||
// Attempt to use relative bind pose.. but it's not working.
|
glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation);
|
||||||
/*
|
glm::mat4 relBindMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform;
|
||||||
AnimPose relBindPose(glm::vec3(1.0f), _joints[i].rotation, _joints[i].translation);
|
AnimPose relBindPose(relBindMat);
|
||||||
_relativeBindPoses.push_back(relBindPose);
|
_relativeBindPoses.push_back(relBindPose);
|
||||||
|
|
||||||
int parentIndex = getParentIndex(i);
|
int parentIndex = getParentIndex(i);
|
||||||
if (parentIndex >= 0) {
|
if (parentIndex >= 0) {
|
||||||
AnimPose parentAbsBindPose = _absoluteBindPoses[parentIndex];
|
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose);
|
||||||
_absoluteBindPoses.push_back(parentAbsBindPose * relBindPose);
|
|
||||||
} else {
|
} else {
|
||||||
_absoluteBindPoses.push_back(relBindPose);
|
_absoluteBindPoses.push_back(relBindPose);
|
||||||
}
|
}
|
||||||
*/
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
|
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
|
||||||
for (size_t i = 0; i < _joints.size(); i++) {
|
for (size_t i = 0; i < _joints.size(); i++) {
|
||||||
if (_joints[i].name == jointName) {
|
if (_joints[i].name == jointName) {
|
||||||
|
|
|
@ -167,27 +167,29 @@ static const uint32_t cyan = toRGBA(0, 128, 128, 255);
|
||||||
|
|
||||||
static void addWireframeSphereWithAxes(const AnimPose& rootPose, const AnimPose& pose, float radius, Vertex*& v) {
|
static void addWireframeSphereWithAxes(const AnimPose& rootPose, const AnimPose& pose, float radius, Vertex*& v) {
|
||||||
|
|
||||||
|
glm::vec3 base = rootPose * pose.trans;
|
||||||
|
|
||||||
// x-axis
|
// x-axis
|
||||||
v->pos = rootPose * pose.trans;
|
v->pos = base;
|
||||||
v->rgba = red;
|
v->rgba = red;
|
||||||
v++;
|
v++;
|
||||||
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(radius * 2.0f, 0.0f, 0.0f));
|
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(radius, 0.0f, 0.0f));
|
||||||
v->rgba = red;
|
v->rgba = red;
|
||||||
v++;
|
v++;
|
||||||
|
|
||||||
// y-axis
|
// y-axis
|
||||||
v->pos = rootPose * pose.trans;
|
v->pos = base;
|
||||||
v->rgba = green;
|
v->rgba = green;
|
||||||
v++;
|
v++;
|
||||||
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(0.0f, radius * 2.0f, 0.0f));
|
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(0.0f, radius, 0.0f));
|
||||||
v->rgba = green;
|
v->rgba = green;
|
||||||
v++;
|
v++;
|
||||||
|
|
||||||
// z-axis
|
// z-axis
|
||||||
v->pos = rootPose * pose.trans;
|
v->pos = base;
|
||||||
v->rgba = blue;
|
v->rgba = blue;
|
||||||
v++;
|
v++;
|
||||||
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(0.0f, 0.0f, radius * 2.0f));
|
v->pos = rootPose * (pose.trans + pose.rot * glm::vec3(0.0f, 0.0f, radius));
|
||||||
v->rgba = blue;
|
v->rgba = blue;
|
||||||
v++;
|
v++;
|
||||||
}
|
}
|
||||||
|
@ -250,16 +252,12 @@ void AnimDebugDraw::update() {
|
||||||
AnimPose pose = skeleton->getAbsoluteBindPose(i);
|
AnimPose pose = skeleton->getAbsoluteBindPose(i);
|
||||||
|
|
||||||
// draw axes
|
// draw axes
|
||||||
const float radius = 0.01f;
|
const float radius = 0.1f;
|
||||||
addWireframeSphereWithAxes(rootPose, pose, radius, v);
|
addWireframeSphereWithAxes(rootPose, pose, radius, v);
|
||||||
|
|
||||||
// line to parent.
|
// line to parent.
|
||||||
auto parentIndex = skeleton->getParentIndex(i);
|
auto parentIndex = skeleton->getParentIndex(i);
|
||||||
//qCDebug(renderutils) << skeleton->getJointName(i) << " index = " << i;
|
|
||||||
//qCDebug(renderutils) << " absPose =" << skeleton->getAbsoluteBindPose(i);
|
|
||||||
//qCDebug(renderutils) << " relPose =" << skeleton->getRelativeBindPose(i);
|
|
||||||
if (parentIndex >= 0) {
|
if (parentIndex >= 0) {
|
||||||
//qCDebug(renderutils) << " parent =" << parentIndex;
|
|
||||||
assert(parentIndex < skeleton->getNumJoints());
|
assert(parentIndex < skeleton->getNumJoints());
|
||||||
AnimPose parentPose = skeleton->getAbsoluteBindPose(parentIndex);
|
AnimPose parentPose = skeleton->getAbsoluteBindPose(parentIndex);
|
||||||
addWireframeBoneAxis(rootPose, pose, parentPose, radius, v);
|
addWireframeBoneAxis(rootPose, pose, parentPose, radius, v);
|
||||||
|
@ -287,7 +285,7 @@ void AnimDebugDraw::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw axes
|
// draw axes
|
||||||
const float radius = 0.01f;
|
const float radius = 0.1f;
|
||||||
addWireframeSphereWithAxes(rootPose, absAnimPose[i], radius, v);
|
addWireframeSphereWithAxes(rootPose, absAnimPose[i], radius, v);
|
||||||
|
|
||||||
if (parentIndex >= 0) {
|
if (parentIndex >= 0) {
|
||||||
|
|
Loading…
Reference in a new issue