mirror of
https://github.com/lubosz/overte.git
synced 2025-04-18 04:18:17 +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);
|
||||
}
|
||||
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);
|
||||
|
||||
_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);
|
||||
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);
|
||||
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
|
||||
|
@ -149,7 +149,7 @@ void AnimClip::copyFromNetworkAnim() {
|
|||
int k = jointMap[j];
|
||||
if (k >= 0 && k < skeletonJointCount) {
|
||||
// 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 "AnimationLogging.h"
|
||||
#include "glmHelpers.h"
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
|
||||
glm::quat(),
|
||||
|
@ -17,7 +19,7 @@ const AnimPose AnimPose::identity = AnimPose(glm::vec3(1.0f),
|
|||
|
||||
AnimPose::AnimPose(const glm::mat4& mat) {
|
||||
scale = extractScale(mat);
|
||||
rot = glm::normalize(glm::quat_cast(mat));
|
||||
rot = extractRotation(mat);
|
||||
trans = extractTranslation(mat);
|
||||
}
|
||||
|
||||
|
@ -41,6 +43,7 @@ AnimPose::operator glm::mat4() const {
|
|||
glm::vec4(zAxis, 0.0f), glm::vec4(trans, 1.0f));
|
||||
}
|
||||
|
||||
//#define TRUST_BIND_TRANSFORM
|
||||
|
||||
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
||||
_joints = joints;
|
||||
|
@ -50,9 +53,31 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
|||
_relativeBindPoses.reserve(joints.size());
|
||||
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);
|
||||
_absoluteBindPoses.push_back(absoluteBindPose);
|
||||
|
||||
int parentIndex = getParentIndex(i);
|
||||
if (parentIndex >= 0) {
|
||||
AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse();
|
||||
|
@ -60,24 +85,24 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
|
|||
} else {
|
||||
_relativeBindPoses.push_back(absoluteBindPose);
|
||||
}
|
||||
|
||||
// AJT:
|
||||
// Attempt to use relative bind pose.. but it's not working.
|
||||
/*
|
||||
AnimPose relBindPose(glm::vec3(1.0f), _joints[i].rotation, _joints[i].translation);
|
||||
#else
|
||||
// trust FBXJoint's local transforms (which is not really the bind pose, but the default pose in the fbx)
|
||||
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(relBindMat);
|
||||
_relativeBindPoses.push_back(relBindPose);
|
||||
|
||||
int parentIndex = getParentIndex(i);
|
||||
if (parentIndex >= 0) {
|
||||
AnimPose parentAbsBindPose = _absoluteBindPoses[parentIndex];
|
||||
_absoluteBindPoses.push_back(parentAbsBindPose * relBindPose);
|
||||
_absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose);
|
||||
} else {
|
||||
_absoluteBindPoses.push_back(relBindPose);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
|
||||
for (size_t i = 0; i < _joints.size(); i++) {
|
||||
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) {
|
||||
|
||||
glm::vec3 base = rootPose * pose.trans;
|
||||
|
||||
// x-axis
|
||||
v->pos = rootPose * pose.trans;
|
||||
v->pos = base;
|
||||
v->rgba = red;
|
||||
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++;
|
||||
|
||||
// y-axis
|
||||
v->pos = rootPose * pose.trans;
|
||||
v->pos = base;
|
||||
v->rgba = green;
|
||||
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++;
|
||||
|
||||
// z-axis
|
||||
v->pos = rootPose * pose.trans;
|
||||
v->pos = base;
|
||||
v->rgba = blue;
|
||||
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++;
|
||||
}
|
||||
|
@ -250,16 +252,12 @@ void AnimDebugDraw::update() {
|
|||
AnimPose pose = skeleton->getAbsoluteBindPose(i);
|
||||
|
||||
// draw axes
|
||||
const float radius = 0.01f;
|
||||
const float radius = 0.1f;
|
||||
addWireframeSphereWithAxes(rootPose, pose, radius, v);
|
||||
|
||||
// line to parent.
|
||||
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) {
|
||||
//qCDebug(renderutils) << " parent =" << parentIndex;
|
||||
assert(parentIndex < skeleton->getNumJoints());
|
||||
AnimPose parentPose = skeleton->getAbsoluteBindPose(parentIndex);
|
||||
addWireframeBoneAxis(rootPose, pose, parentPose, radius, v);
|
||||
|
@ -287,7 +285,7 @@ void AnimDebugDraw::update() {
|
|||
}
|
||||
|
||||
// draw axes
|
||||
const float radius = 0.01f;
|
||||
const float radius = 0.1f;
|
||||
addWireframeSphereWithAxes(rootPose, absAnimPose[i], radius, v);
|
||||
|
||||
if (parentIndex >= 0) {
|
||||
|
|
Loading…
Reference in a new issue