WIP checkpoint

* No longer normalizing scale in AnimSkeleton and AnimClip
  This means graph is animating in 'geometry' coordinates
  before unit scale is even applied.  This is necessary to
  properly work with both Avatar based models and ModelEntity
  based models

Many things are broken.
  * debug rendering (translations are x100)
  * IK hand targets
  * follow cam
  * I did not even dare to try HMD mode
This commit is contained in:
Anthony J. Thibault 2015-11-18 18:47:33 -08:00
parent b054ef1488
commit 721da29432
9 changed files with 72 additions and 43 deletions

View file

@ -359,11 +359,11 @@ void MyAvatar::updateHMDFollowVelocity() {
// This is so the correct camera can be used for rendering.
void MyAvatar::updateSensorToWorldMatrix() {
#ifdef DEBUG_RENDERING
//#ifdef DEBUG_RENDERING
// draw marker about avatar's position
const glm::vec4 red(1.0f, 0.0f, 0.0f, 1.0f);
DebugDraw::getInstance().addMyAvatarMarker("pos", glm::quat(), glm::vec3(), red);
#endif
//#endif
// update the sensor mat so that the body position will end up in the desired
// position when driven from the head.
@ -1286,7 +1286,10 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
if (_enableDebugDrawAnimPose && _debugDrawSkeleton) {
glm::vec4 cyan(0.1f, 0.6f, 0.6f, 1.0f);
auto rig = _skeletonModel.getRig();
// AJT: TODO move this into rig!
// build AnimPoseVec from JointStates.
// AJT: TODO THIS SHIT IS ALL BROKEN
AnimPoseVec poses;
poses.reserve(_debugDrawSkeleton->getNumJoints());
for (int i = 0; i < _debugDrawSkeleton->getNumJoints(); i++) {
@ -1297,6 +1300,11 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
_rig->getJointTranslation(i, jointTrans);
pose.rot = pose.rot * jointRot;
pose.trans = jointTrans;
/*
if (_debugDrawSkeleton->getParentIndex(i) < 0) {
pose = _rig->getGeometryOffset() * pose;
}
*/
poses.push_back(pose);
}
@ -1765,6 +1773,7 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const {
const glm::vec3 DEFAULT_NECK_POS(0.0f, 1.70f, 0.0f);
const glm::vec3 DEFAULT_HIPS_POS(0.0f, 1.05f, 0.0f);
AnimPose geometryOffset = _rig->getGeometryOffset();
vec3 localEyes, localNeck;
if (!_debugDrawSkeleton) {
const glm::quat rotY180 = glm::angleAxis((float)PI, glm::vec3(0.0f, 1.0f, 0.0f));
@ -1780,10 +1789,10 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const {
int neckIndex = _debugDrawSkeleton->nameToJointIndex("Neck");
int hipsIndex = _debugDrawSkeleton->nameToJointIndex("Hips");
glm::vec3 absRightEyePos = rightEyeIndex != -1 ? _debugDrawSkeleton->getAbsoluteBindPose(rightEyeIndex).trans : DEFAULT_RIGHT_EYE_POS;
glm::vec3 absLeftEyePos = leftEyeIndex != -1 ? _debugDrawSkeleton->getAbsoluteBindPose(leftEyeIndex).trans : DEFAULT_LEFT_EYE_POS;
glm::vec3 absNeckPos = neckIndex != -1 ? _debugDrawSkeleton->getAbsoluteBindPose(neckIndex).trans : DEFAULT_NECK_POS;
glm::vec3 absHipsPos = neckIndex != -1 ? _debugDrawSkeleton->getAbsoluteBindPose(hipsIndex).trans : DEFAULT_HIPS_POS;
glm::vec3 absRightEyePos = rightEyeIndex != -1 ? geometryOffset * _debugDrawSkeleton->getAbsoluteBindPose(rightEyeIndex).trans : DEFAULT_RIGHT_EYE_POS;
glm::vec3 absLeftEyePos = leftEyeIndex != -1 ? geometryOffset * _debugDrawSkeleton->getAbsoluteBindPose(leftEyeIndex).trans : DEFAULT_LEFT_EYE_POS;
glm::vec3 absNeckPos = neckIndex != -1 ? geometryOffset * _debugDrawSkeleton->getAbsoluteBindPose(neckIndex).trans : DEFAULT_NECK_POS;
glm::vec3 absHipsPos = neckIndex != -1 ? geometryOffset * _debugDrawSkeleton->getAbsoluteBindPose(hipsIndex).trans : DEFAULT_HIPS_POS;
const glm::quat rotY180 = glm::angleAxis((float)PI, glm::vec3(0.0f, 1.0f, 0.0f));
localEyes = rotY180 * (((absRightEyePos + absLeftEyePos) / 2.0f) - absHipsPos);

View file

@ -43,7 +43,8 @@ SkeletonModel::~SkeletonModel() {
void SkeletonModel::initJointStates() {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
glm::mat4 geometryOffset = geometry.offset;
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
int rootJointIndex = geometry.rootJointIndex;
int leftHandJointIndex = geometry.leftHandJointIndex;
@ -241,9 +242,9 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
Model::simulate(deltaTime, fullUpdate);
// let rig compute the model offset
glm::vec3 modelOffset;
if (_rig->getModelOffset(modelOffset)) {
setOffset(modelOffset);
glm::vec3 registrationPoint;
if (_rig->getModelRegistrationPoint(registrationPoint)) {
setOffset(registrationPoint);
}
if (!isActive() || !_owningAvatar->isMyAvatar()) {

View file

@ -107,8 +107,6 @@ void AnimClip::copyFromNetworkAnim() {
const int skeletonJointCount = _skeleton->getNumJoints();
_anim.resize(frameCount);
const glm::vec3 offsetScale = extractScale(geom.offset);
for (int frame = 0; frame < frameCount; frame++) {
// init all joints in animation to bind pose
@ -125,23 +123,25 @@ void AnimClip::copyFromNetworkAnim() {
// skip joints that are in the animation but not in the skeleton.
if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) {
const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint] * offsetScale;
const AnimPose& relBindPose = _skeleton->getRelativeBindPose(skeletonJoint);
const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint];
// AJT: TODO: use the actual preRotation not the bind pose here.
const AnimPose& jointOrientPose = _skeleton->getRelativeBindPose(skeletonJoint);
const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint);
// used to adjust translation offsets, so large translation animatons on the reference skeleton
// will be adjusted when played on a skeleton with short limbs.
float limbLengthScale = fabsf(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relBindPose.trans) / glm::length(fbxZeroTrans));
float limbLengthScale = fabsf(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relDefaultPose.trans) / glm::length(fbxZeroTrans));
AnimPose& pose = _anim[frame][skeletonJoint];
const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame];
// rotation in fbxAnimationFrame is a delta from a reference skeleton bind pose.
pose.rot = relBindPose.rot * fbxAnimFrame.rotations[animJoint];
// rotation in fbxAnimationFrame is a delta from its jointOrientPose (aka preRotation)
pose.rot = jointOrientPose.rot * fbxAnimFrame.rotations[animJoint];
// translation in fbxAnimationFrame is not a delta.
// convert it into a delta by subtracting from the first frame.
const glm::vec3& fbxTrans = fbxAnimFrame.translations[animJoint] * offsetScale;
pose.trans = relBindPose.trans + limbLengthScale * (fbxTrans - fbxZeroTrans);
const glm::vec3& fbxTrans = fbxAnimFrame.translations[animJoint];
pose.trans = relDefaultPose.trans + limbLengthScale * (fbxTrans - fbxZeroTrans);
}
}
}

View file

@ -24,12 +24,17 @@ AnimSkeleton::AnimSkeleton(const FBXGeometry& fbxGeometry) {
joints.push_back(joint);
}
// AJT: REMOVE
/*
AnimPose geometryOffset(fbxGeometry.offset);
buildSkeletonFromJoints(joints, geometryOffset);
*/
buildSkeletonFromJoints(joints);
}
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset) {
buildSkeletonFromJoints(joints, geometryOffset);
AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
buildSkeletonFromJoints(joints);
}
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
@ -94,7 +99,7 @@ AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& poses)
}
}
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset) {
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) {
_joints = joints;
// build a cache of bind poses
@ -143,12 +148,17 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints,
}
}
// AJT: REMOVE
/*
// now we want to normalize scale from geometryOffset to all poses.
// This will ensure our bone translations will be in meters, even if the model was authored with some other unit of mesure.
normalizeScale(geometryOffset, _relativeBindPoses, _absoluteBindPoses);
normalizeScale(geometryOffset, _relativeDefaultPoses, _absoluteDefaultPoses);
*/
}
/*
// AJT: REMOVE
void AnimSkeleton::normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const {
for (auto& absPose : absPoses) {
absPose.trans = (geometryOffset * absPose).trans;
@ -164,6 +174,7 @@ void AnimSkeleton::normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& r
}
}
}
*/
#define DUMP_FBX_JOINTS

View file

@ -24,7 +24,7 @@ public:
using ConstPointer = std::shared_ptr<const AnimSkeleton>;
AnimSkeleton(const FBXGeometry& fbxGeometry);
AnimSkeleton(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset);
AnimSkeleton(const std::vector<FBXJoint>& joints);
int nameToJointIndex(const QString& jointName) const;
const QString& getJointName(int jointIndex) const;
int getNumJoints() const;
@ -54,8 +54,9 @@ public:
#endif
protected:
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset);
void normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const;
void buildSkeletonFromJoints(const std::vector<FBXJoint>& joints);
// AJT: REMOVE
//void normalizeScale(const AnimPose& geometryOffset, AnimPoseVec& relPoses, AnimPoseVec& absPoses) const;
std::vector<FBXJoint> _joints;
AnimPoseVec _absoluteBindPoses;

View file

@ -73,7 +73,7 @@ glm::quat JointState::getRotation() const {
void JointState::initTransform(const glm::mat4& parentTransform) {
_unitsScale = extractScale(parentTransform);
//_unitsScale = extractScale(parentTransform);
computeTransform(parentTransform);
_positionInParentFrame = glm::inverse(extractRotation(parentTransform)) * (extractTranslation(_transform) - extractTranslation(parentTransform));

View file

@ -167,9 +167,10 @@ void Rig::initJointStates(const FBXGeometry& geometry, glm::mat4 modelOffset, in
int leftHandJointIndex, int leftElbowJointIndex, int leftShoulderJointIndex,
int rightHandJointIndex, int rightElbowJointIndex, int rightShoulderJointIndex) {
_geometryOffset = AnimPose(geometry.offset);
_animSkeleton = std::make_shared<AnimSkeleton>(geometry);
_animSkeleton->dump();
//_animSkeleton->dump();
computeEyesInRootFrame(_animSkeleton->getRelativeDefaultPoses());
@ -198,12 +199,13 @@ void Rig::initJointStates(const FBXGeometry& geometry, glm::mat4 modelOffset, in
// was old Rig::initJointStates
// compute model transforms
glm::mat4 rootTransform = (glm::mat4)(_modelOffset * _geometryOffset);
int numStates = _animSkeleton->getNumJoints();
for (int i = 0; i < numStates; ++i) {
JointState& state = _jointStates[i];
int parentIndex = state.getParentIndex();
if (parentIndex == -1) {
state.initTransform(modelOffset);
state.initTransform(rootTransform);
} else {
const JointState& parentState = _jointStates.at(parentIndex);
state.initTransform(parentState.getTransform());
@ -248,7 +250,6 @@ void Rig::setModelOffset(const glm::mat4& modelOffset) {
_legacyModelOffset = modelOffset;
}
_modelOffset = AnimPose(modelOffset);
_modelScale = _modelOffset.scale;
}
// AJT: REMOVE
@ -1220,9 +1221,9 @@ void Rig::initAnimGraph(const QUrl& url) {
});
}
bool Rig::getModelOffset(glm::vec3& modelOffsetOut) const {
bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const {
if (_animSkeleton && _rootJointIndex >= 0) {
modelOffsetOut = -_animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans;
modelRegistrationPointOut = _geometryOffset * -_animSkeleton->getAbsoluteBindPose(_rootJointIndex).trans;
return true;
} else {
return false;
@ -1263,15 +1264,19 @@ void Rig::buildAbsolutePoses() {
}
for (int i = 0; i < (int)_absolutePoses.size(); i++) {
_absolutePoses[i] = _modelOffset * _geometryOffset * _absolutePoses[i];
// AJT: REMOVE
/*
_absolutePoses[i].trans = _modelOffset.trans + _absolutePoses[i].trans;
_absolutePoses[i].rot = _modelOffset.rot * _absolutePoses[i].rot;
_absolutePoses[i].scale = _absolutePoses[i].scale * _modelScale;
*/
}
// AJT: LEGACY
{
// Build the joint states
glm::mat4 rootTransform = _legacyModelOffset;
glm::mat4 rootTransform = (glm::mat4)(_modelOffset * _geometryOffset);
for (int i = 0; i < (int)_animSkeleton->getNumJoints(); i++) {
JointState& state = _jointStates[i];
@ -1300,12 +1305,12 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
//if (_jointStates.size() == 73) {
// check for differences between jointStates and _absolutePoses!
{
if (false) {
// should display for model entities
glm::mat4 newMat = _absolutePoses[jointIndex];
glm::mat4 oldMat = _jointStates[jointIndex].getTransform();
const float EPSILON = 0.005f;
const float EPSILON = 0.01f;
if (glm::length(newMat[0] - oldMat[0]) > EPSILON ||
glm::length(newMat[1] - oldMat[1]) > EPSILON ||
glm::length(newMat[2] - oldMat[2]) > EPSILON ||
@ -1321,9 +1326,9 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
// AJT: LEGACY
{
//return _jointStates[jointIndex].getTransform();
return _jointStates[jointIndex].getTransform();
}
return _absolutePoses[jointIndex];
//return _absolutePoses[jointIndex];
}

View file

@ -94,6 +94,7 @@ public:
int indexOfJoint(const QString& jointName);
void setModelOffset(const glm::mat4& modelOffset);
const AnimPose& getGeometryOffset() const { return _geometryOffset; }
// AJT: REMOVE
/*
@ -162,7 +163,7 @@ public:
void removeAnimationStateHandler(QScriptValue handler);
void animationStateHandlerResult(int identifier, QScriptValue result);
bool getModelOffset(glm::vec3& modelOffsetOut) const;
bool getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const;
const glm::vec3& getEyesInRootFrame() const { return _eyesInRootFrame; }
@ -182,8 +183,9 @@ public:
QVector<JointState> _jointStates;
glm::mat4 _legacyModelOffset;
AnimPose _modelOffset;
glm::vec3 _modelScale;
// AJT: TODO document these better
AnimPose _modelOffset; // model to avatar space (without 180 flip)
AnimPose _geometryOffset; // geometry to model space (includes unit offset & fst offsets)
AnimPoseVec _relativePoses; // in fbx model space relative to parent.
AnimPoseVec _absolutePoses; // in fbx model space after _modelOffset is applied.
AnimPoseVec _overridePoses; // in fbx model space relative to parent.

View file

@ -107,7 +107,7 @@ void Model::initJointTransforms() {
return;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
_rig->setModelOffset(modelOffset);
}
@ -160,7 +160,7 @@ bool Model::updateGeometry() {
// virtual
void Model::initJointStates() {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset);
int rootJointIndex = geometry.rootJointIndex;
int leftHandJointIndex = geometry.leftHandJointIndex;
@ -947,7 +947,7 @@ void Model::simulateInternal(float deltaTime) {
// update the world space transforms for all joints
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset);
updateRig(deltaTime, parentTransform);
}
void Model::updateClusterMatrices() {
@ -1011,7 +1011,7 @@ void Model::updateClusterMatrices() {
void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const QVector<int>& freeLineage = geometry.joints.at(endIndex).freeLineage;
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset);
_rig->inverseKinematics(endIndex, targetPosition, targetRotation, priority, freeLineage, parentTransform);
}