JointState has our own copy of any ivars we want from FBXJoint, instead of keeping a reference to the fbx.

This commit is contained in:
Howard Stearns 2015-08-06 16:54:09 -07:00
parent a4f105f6c3
commit 42cc34cd64
9 changed files with 131 additions and 84 deletions

View file

@ -56,12 +56,12 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
}
}
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index) {
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index) {
// get the rotation axes in joint space and use them to adjust the rotation
glm::mat3 axes = glm::mat3_cast(glm::quat());
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() *
glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) *
joint.preTransform * glm::mat4_cast(joint.preRotation)));
state.getPreTransform() * glm::mat4_cast(state.getPreRotation())));
glm::vec3 pitchYawRoll = safeEulerAngles(_owningHead->getFinalOrientationInLocalFrame());
glm::vec3 lean = glm::radians(glm::vec3(_owningHead->getFinalLeanForward(),
_owningHead->getTorsoTwist(),
@ -71,15 +71,15 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2]))
* glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1]))
* glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0]))
* joint.rotation, DEFAULT_PRIORITY);
* state.getOriginalRotation(), DEFAULT_PRIORITY);
}
void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const FBXJoint& joint, int index) {
void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index) {
// likewise with the eye joints
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
glm::mat4 inverse = glm::inverse(glm::mat4_cast(model->getRotation()) * parentState.getTransform() *
glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) *
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getOriginalRotation()));
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f));
glm::vec3 lookAtDelta = _owningHead->getCorrectedLookAtPosition() - model->getTranslation();
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * _owningHead->getSaccade(), 1.0f));
@ -87,22 +87,22 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
_rig->setJointRotationInConstrainedFrame(index, glm::angleAxis(glm::clamp(glm::angle(between),
-MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
joint.rotation, DEFAULT_PRIORITY);
state.getOriginalRotation(), DEFAULT_PRIORITY);
}
void FaceModel::maybeUpdateNeckAndEyeRotation(int index) {
const JointState& state = _rig->getJointState(index);
const FBXJoint& joint = state.getFBXJoint();
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const int parentIndex = state.getParentIndex();
// guard against out-of-bounds access to _jointStates
if (joint.parentIndex != -1 && joint.parentIndex >= 0 && joint.parentIndex < _rig->getJointStateCount()) {
const JointState& parentState = _rig->getJointState(joint.parentIndex);
if (parentIndex != -1 && parentIndex >= 0 && parentIndex < _rig->getJointStateCount()) {
const JointState& parentState = _rig->getJointState(parentIndex);
if (index == geometry.neckJointIndex) {
maybeUpdateNeckRotation(parentState, joint, index);
maybeUpdateNeckRotation(parentState, state, index);
} else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) {
maybeUpdateEyeRotation(this, parentState, joint, index);
maybeUpdateEyeRotation(this, parentState, state, index);
}
}
}

View file

@ -26,8 +26,8 @@ public:
virtual void simulate(float deltaTime, bool fullUpdate = true);
void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index);
void maybeUpdateEyeRotation(Model* model, const JointState& parentState, const FBXJoint& joint, int index);
void maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index);
void maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index);
void maybeUpdateNeckAndEyeRotation(int index);
/// Retrieve the positions of up to two eye meshes.

View file

@ -401,7 +401,7 @@ bool SkeletonModel::getNeckParentRotationFromDefaultOrientation(glm::quat& neckP
glm::quat worldFrameRotation;
bool success = getJointRotationInWorldFrame(parentIndex, worldFrameRotation);
if (success) {
neckParentRotation = worldFrameRotation * _rig->getJointState(parentIndex).getFBXJoint().inverseDefaultRotation;
neckParentRotation = worldFrameRotation * _rig->getJointState(parentIndex).getInverseDefaultRotation();
}
return success;
}
@ -477,18 +477,17 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
for (int i = 0; i < numStates; i++) {
// compute the default transform of this joint
const JointState& state = _rig->getJointState(i);
const FBXJoint& joint = state.getFBXJoint();
int parentIndex = joint.parentIndex;
int parentIndex = state.getParentIndex();
if (parentIndex == -1) {
transforms[i] = _rig->getJointTransform(i);
} else {
glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
* joint.preTransform * glm::mat4_cast(modifiedRotation) * joint.postTransform;
glm::quat modifiedRotation = state.getPreRotation() * state.getOriginalRotation() * state.getPostRotation();
transforms[i] = transforms[parentIndex] * glm::translate(state.getTranslation())
* state.getPreTransform() * glm::mat4_cast(modifiedRotation) * state.getPostTransform();
}
// Each joint contributes a sphere at its position
glm::vec3 axis(joint.boneRadius);
glm::vec3 axis(state.getBoneRadius());
glm::vec3 jointPosition = extractTranslation(transforms[i]);
totalExtents.addPoint(jointPosition + axis);
totalExtents.addPoint(jointPosition - axis);

View file

@ -17,7 +17,6 @@ void AvatarRig::updateJointState(int index, glm::mat4 parentTransform) {
return; // bail
}
JointState& state = _jointStates[index];
const FBXJoint& joint = state.getFBXJoint();
// compute model transforms
if (index == _rootJointIndex) {
@ -26,7 +25,7 @@ void AvatarRig::updateJointState(int index, glm::mat4 parentTransform) {
clearJointTransformTranslation(index);
} else {
// guard against out-of-bounds access to _jointStates
int parentIndex = joint.parentIndex;
int parentIndex = state.getParentIndex();
if (parentIndex >= 0 && parentIndex < _jointStates.size()) {
const JointState& parentState = _jointStates.at(parentIndex);
state.computeTransform(parentState.getTransform(), parentState.getTransformChanged());
@ -53,8 +52,8 @@ void AvatarRig::setHandPosition(int jointIndex,
}
// precomputed lengths
float upperArmLength = _jointStates[elbowJointIndex].getFBXJoint().distanceToParent * scale;
float lowerArmLength = _jointStates[jointIndex].getFBXJoint().distanceToParent * scale;
float upperArmLength = _jointStates[elbowJointIndex].getDistanceToParent() * scale;
float lowerArmLength = _jointStates[jointIndex].getDistanceToParent() * scale;
// first set wrist position
glm::vec3 wristPosition = position;

View file

@ -14,15 +14,14 @@
/// Updates the state of the joint at the specified index.
void EntityRig::updateJointState(int index, glm::mat4 parentTransform) {
JointState& state = _jointStates[index];
const FBXJoint& joint = state.getFBXJoint();
// compute model transforms
int parentIndex = joint.parentIndex;
int parentIndex = state.getParentIndex();
if (parentIndex == -1) {
state.computeTransform(parentTransform);
} else {
// guard against out-of-bounds access to _jointStates
if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) {
if (parentIndex >= 0 && parentIndex < _jointStates.size()) {
const JointState& parentState = _jointStates.at(parentIndex);
state.computeTransform(parentState.getTransform(), parentState.getTransformChanged());
}

View file

@ -24,7 +24,6 @@ JointState::JointState() :
_rotationIsValid(false),
_positionInParentFrame(0.0f),
_distanceToParent(0.0f),
_fbxJoint(NULL),
_constraint(NULL) {
}
@ -37,8 +36,21 @@ JointState::JointState(const JointState& other) : _constraint(NULL) {
_positionInParentFrame = other._positionInParentFrame;
_distanceToParent = other._distanceToParent;
_animationPriority = other._animationPriority;
_fbxJoint = other._fbxJoint;
// DO NOT copy _constraint
_name = other._name;
_isFree = other._isFree;
_boneRadius = other._boneRadius;
_parentIndex = other._parentIndex;
_translation = other._translation;
_originalRotation = other._originalRotation;
_inverseDefaultRotation = other._inverseDefaultRotation;
_rotationMin = other._rotationMin;
_rotationMax = other._rotationMax;
_preRotation = other._preRotation;
_postRotation = other._postRotation;
_preTransform = other._preTransform;
_postTransform = other._postTransform;
_inverseBindRotation = other._inverseBindRotation;
}
JointState::~JointState() {
@ -65,8 +77,20 @@ void JointState::setFBXJoint(const FBXJoint* joint) {
_transformChanged = true;
_rotationIsValid = false;
// NOTE: JointState does not own the FBXJoint to which it points.
_fbxJoint = joint;
_name = joint->name;
_isFree = joint->isFree;
_boneRadius = joint->boneRadius;
_parentIndex = joint->parentIndex;
_translation = joint->translation;
_originalRotation = joint->rotation;
_inverseDefaultRotation = joint->inverseDefaultRotation;
_rotationMin = joint->rotationMin;
_rotationMax = joint->rotationMax;
_preRotation = joint->preRotation;
_postRotation = joint->postRotation;
_preTransform = joint->preTransform;
_postTransform = joint->postTransform;
_inverseBindRotation = joint->inverseBindRotation;
if (_constraint) {
delete _constraint;
_constraint = NULL;
@ -78,10 +102,10 @@ void JointState::buildConstraint() {
delete _constraint;
_constraint = NULL;
}
if (glm::distance2(glm::vec3(-PI), _fbxJoint->rotationMin) > EPSILON ||
glm::distance2(glm::vec3(PI), _fbxJoint->rotationMax) > EPSILON ) {
if (glm::distance2(glm::vec3(-PI), _rotationMin) > EPSILON ||
glm::distance2(glm::vec3(PI), _rotationMax) > EPSILON ) {
// this joint has rotation constraints
_constraint = AngularConstraint::newAngularConstraint(_fbxJoint->rotationMin, _fbxJoint->rotationMax);
_constraint = AngularConstraint::newAngularConstraint(_rotationMin, _rotationMax);
}
}
@ -98,7 +122,21 @@ void JointState::copyState(const JointState& state) {
_visibleTransform = state._visibleTransform;
_visibleRotation = extractRotation(_visibleTransform);
_visibleRotationInConstrainedFrame = state._visibleRotationInConstrainedFrame;
// DO NOT copy _fbxJoint or _constraint
// DO NOT copy _constraint
_name = state._name;
_isFree = state._isFree;
_boneRadius = state._boneRadius;
_parentIndex = state._parentIndex;
_originalRotation = state._originalRotation;
_inverseDefaultRotation = state._inverseDefaultRotation;
_translation = state._translation;
_rotationMin = state._rotationMin;
_rotationMax = state._rotationMax;
_preRotation = state._preRotation;
_postRotation = state._postRotation;
_preTransform = state._preTransform;
_postTransform = state._postTransform;
_inverseBindRotation = state._inverseBindRotation;
}
void JointState::initTransform(const glm::mat4& parentTransform) {
@ -112,9 +150,9 @@ void JointState::computeTransform(const glm::mat4& parentTransform, bool parentT
return;
}
glm::quat rotationInParentFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform;
glm::mat4 newTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame;
glm::quat rotationInParentFrame = _preRotation * _rotationInConstrainedFrame * _postRotation;
glm::mat4 transformInParentFrame = _preTransform * glm::mat4_cast(rotationInParentFrame) * _postTransform;
glm::mat4 newTransform = parentTransform * glm::translate(_translation) * transformInParentFrame;
if (newTransform != _transform) {
_transform = newTransform;
@ -124,37 +162,35 @@ void JointState::computeTransform(const glm::mat4& parentTransform, bool parentT
}
void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
glm::quat rotationInParentFrame = _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation;
glm::mat4 transformInParentFrame = _fbxJoint->preTransform * glm::mat4_cast(rotationInParentFrame) * _fbxJoint->postTransform;
_visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * transformInParentFrame;
glm::quat rotationInParentFrame = _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
glm::mat4 transformInParentFrame = _preTransform * glm::mat4_cast(rotationInParentFrame) * _postTransform;
_visibleTransform = parentTransform * glm::translate(_translation) * transformInParentFrame;
_visibleRotation = extractRotation(_visibleTransform);
}
glm::quat JointState::getRotationInBindFrame() const {
return getRotation() * _fbxJoint->inverseBindRotation;
return getRotation() * _inverseBindRotation;
}
glm::quat JointState::getRotationInParentFrame() const {
return _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
return _preRotation * _rotationInConstrainedFrame * _postRotation;
}
glm::quat JointState::getVisibleRotationInParentFrame() const {
return _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation;
return _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
}
void JointState::restoreRotation(float fraction, float priority) {
assert(_fbxJoint != NULL);
if (priority == _animationPriority || _animationPriority == 0.0f) {
setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _fbxJoint->rotation, fraction));
setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _originalRotation, fraction));
_animationPriority = 0.0f;
}
}
void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain) {
// rotation is from bind- to model-frame
assert(_fbxJoint != NULL);
if (priority >= _animationPriority) {
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_inverseBindRotation);
if (constrain && _constraint) {
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
}
@ -175,7 +211,6 @@ void JointState::clearTransformTranslation() {
void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
// NOTE: delta is in model-frame
assert(_fbxJoint != NULL);
if (priority < _animationPriority || delta == glm::quat()) {
return;
}
@ -196,14 +231,13 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa
/// This helps keep an IK solution stable.
void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float priority) {
// NOTE: delta is in model-frame
assert(_fbxJoint != NULL);
if (priority < _animationPriority) {
return;
}
_animationPriority = priority;
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation();
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
targetRotation = safeMix(targetRotation, _originalRotation, mixFactor);
}
if (_constraint) {
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
@ -213,10 +247,8 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float
void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor) {
// NOTE: delta is in model-frame
assert(_fbxJoint != NULL);
glm::quat targetRotation = _visibleRotationInConstrainedFrame * glm::inverse(_visibleRotation) * delta * _visibleRotation;
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
//targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
targetRotation = safeMix(targetRotation, _rotationInConstrainedFrame, mixFactor);
}
setVisibleRotationInConstrainedFrame(targetRotation);
@ -225,11 +257,11 @@ void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor
glm::quat JointState::computeParentRotation() const {
// R = Rp * Rpre * r * Rpost
// Rp = R * (Rpre * r * Rpost)^
return getRotation() * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation);
return getRotation() * glm::inverse(_preRotation * _rotationInConstrainedFrame * _postRotation);
}
glm::quat JointState::computeVisibleParentRotation() const {
return _visibleRotation * glm::inverse(_fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation);
return _visibleRotation * glm::inverse(_preRotation * _visibleRotationInConstrainedFrame * _postRotation);
}
void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain, float mix) {
@ -248,17 +280,17 @@ void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRo
_rotationInConstrainedFrame = targetRotation;
_transformChanged = true;
// R' = Rp * Rpre * r' * Rpost
_rotation = parentRotation * _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
_rotation = parentRotation * _preRotation * _rotationInConstrainedFrame * _postRotation;
}
void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) {
glm::quat parentRotation = computeVisibleParentRotation();
_visibleRotationInConstrainedFrame = targetRotation;
_visibleRotation = parentRotation * _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation;
_visibleRotation = parentRotation * _preRotation * _visibleRotationInConstrainedFrame * _postRotation;
}
bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const {
glm::quat defaultRotation = _fbxJoint->rotation;
glm::quat defaultRotation = _originalRotation;
return glm::abs(rotation.x - defaultRotation.x) < tolerance &&
glm::abs(rotation.y - defaultRotation.y) < tolerance &&
glm::abs(rotation.z - defaultRotation.z) < tolerance &&
@ -266,13 +298,12 @@ bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) c
}
glm::quat JointState::getDefaultRotationInParentFrame() const {
// NOTE: the result is constant and could be cached in the FBXJoint
return _fbxJoint->preRotation * _fbxJoint->rotation * _fbxJoint->postRotation;
// NOTE: the result is constant and could be cached
return _preRotation * _originalRotation * _postRotation;
}
const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const {
assert(_fbxJoint != NULL);
return _fbxJoint->translation;
return _translation;
}
void JointState::slaveVisibleTransform() {

View file

@ -31,7 +31,6 @@ public:
~JointState();
void setFBXJoint(const FBXJoint* joint);
const FBXJoint& getFBXJoint() const { return *_fbxJoint; }
void buildConstraint();
void copyState(const JointState& state);
@ -61,7 +60,7 @@ public:
const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; }
float getDistanceToParent() const { return _distanceToParent; }
int getParentIndex() const { return _fbxJoint->parentIndex; }
int getParentIndex() const { return _parentIndex; }
/// \param delta is in the model-frame
void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f);
@ -108,6 +107,17 @@ public:
void setTransform(const glm::mat4& transform) { _transform = transform; }
void setVisibleTransform(const glm::mat4& transform) { _visibleTransform = transform; }
const glm::vec3& getTranslation() const { return _translation; }
const glm::mat4& getPreTransform() const { return _preTransform; }
const glm::mat4& getPostTransform() const { return _postTransform; }
const glm::quat& getPreRotation() const { return _preRotation; }
const glm::quat& getPostRotation() const { return _postRotation; }
const glm::quat& getOriginalRotation() const { return _originalRotation; }
const glm::quat& getInverseDefaultRotation() const { return _inverseDefaultRotation; }
const QString& getName() const { return _name; }
float getBoneRadius() const { return _boneRadius; }
bool getIsFree() const { return _isFree; }
private:
void setRotationInConstrainedFrameInternal(const glm::quat& targetRotation);
@ -126,7 +136,20 @@ private:
glm::quat _visibleRotation;
glm::quat _visibleRotationInConstrainedFrame;
const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
glm::quat _originalRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform
glm::quat _inverseDefaultRotation;
glm::vec3 _translation;
float _boneRadius;
bool _isFree;
glm::vec3 _rotationMin;
glm::vec3 _rotationMax;
glm::quat _preRotation;
glm::quat _postRotation;
glm::mat4 _preTransform;
glm::mat4 _postTransform;
glm::quat _inverseBindRotation;
int _parentIndex;
QString _name;
AngularConstraint* _constraint; // JointState owns its AngularConstraint
};

View file

@ -222,7 +222,7 @@ float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform
// Should we be using .fst mapping instead/also?
int Rig::indexOfJoint(const QString& jointName) {
for (int i = 0; i < _jointStates.count(); i++) {
if (_jointStates[i].getFBXJoint().name == jointName) {
if (_jointStates[i].getName() == jointName) {
return i;
}
}
@ -235,8 +235,7 @@ void Rig::initJointTransforms(glm::mat4 parentTransform) {
int numStates = _jointStates.size();
for (int i = 0; i < numStates; ++i) {
JointState& state = _jointStates[i];
const FBXJoint& joint = state.getFBXJoint();
int parentIndex = joint.parentIndex;
int parentIndex = state.getParentIndex();
if (parentIndex == -1) {
state.initTransform(parentTransform);
} else {
@ -528,8 +527,7 @@ bool Rig::setJointPosition(int jointIndex, const glm::vec3& position, const glm:
for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) {
int index = freeLineage.at(j);
JointState& state = _jointStates[index];
const FBXJoint& joint = state.getFBXJoint();
if (!(joint.isFree || allIntermediatesFree)) {
if (!(state.getIsFree() || allIntermediatesFree)) {
continue;
}
glm::vec3 jointPosition = extractTranslation(state.getTransform());
@ -598,8 +596,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q
{
int index = freeLineage.last();
const JointState& state = _jointStates.at(index);
const FBXJoint& joint = state.getFBXJoint();
int parentIndex = joint.parentIndex;
int parentIndex = state.getParentIndex();
if (parentIndex == -1) {
topParentTransform = parentTransform;
} else {
@ -624,8 +621,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q
for (int j = 1; j < numFree; j++) {
int nextIndex = freeLineage.at(j);
JointState& nextState = _jointStates[nextIndex];
FBXJoint nextJoint = nextState.getFBXJoint();
if (! nextJoint.isFree) {
if (! nextState.getIsFree()) {
continue;
}
@ -799,20 +795,20 @@ void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, floa
glm::angleAxis(- RADIANS_PER_DEGREE * leanSideways, inverse * zAxis) *
glm::angleAxis(- RADIANS_PER_DEGREE * leanForward, inverse * xAxis) *
glm::angleAxis(RADIANS_PER_DEGREE * torsoTwist, inverse * yAxis) *
getJointState(index).getFBXJoint().rotation, DEFAULT_PRIORITY);
getJointState(index).getOriginalRotation(), DEFAULT_PRIORITY);
}
}
void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, float leanSideways, float leanForward, float torsoTwist) {
if (index >= 0 && _jointStates[index].getParentIndex() >= 0) {
auto& parentState = _jointStates[_jointStates[index].getParentIndex()];
auto joint = _jointStates[index].getFBXJoint();
auto& state = _jointStates[index];
auto& parentState = _jointStates[state.getParentIndex()];
// get the rotation axes in joint space and use them to adjust the rotation
glm::mat3 axes = glm::mat3_cast(glm::quat());
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() *
glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) *
joint.preTransform * glm::mat4_cast(joint.preRotation)));
state.getPreTransform() * glm::mat4_cast(state.getPreRotation())));
glm::vec3 pitchYawRoll = safeEulerAngles(localHeadOrientation);
glm::vec3 lean = glm::radians(glm::vec3(leanForward, torsoTwist, leanSideways));
pitchYawRoll -= lean;
@ -820,19 +816,19 @@ void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, floa
glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) *
glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) *
glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) *
joint.rotation, DEFAULT_PRIORITY);
state.getOriginalRotation(), DEFAULT_PRIORITY);
}
}
void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade) {
if (index >= 0 && _jointStates[index].getParentIndex() >= 0) {
auto& parentState = _jointStates[_jointStates[index].getParentIndex()];
auto joint = _jointStates[index].getFBXJoint();
auto& state = _jointStates[index];
auto& parentState = _jointStates[state.getParentIndex()];
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
glm::mat4 inverse = glm::inverse(parentState.getTransform() *
glm::translate(getJointDefaultTranslationInConstrainedFrame(index)) *
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getOriginalRotation()));
glm::vec3 front = glm::vec3(inverse * glm::vec4(worldHeadOrientation * IDENTITY_FRONT, 0.0f));
glm::vec3 lookAtDelta = lookAt;
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * saccade, 1.0f));
@ -840,6 +836,6 @@ void Rig::updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
float angle = glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE);
glm::quat rot = glm::angleAxis(angle, glm::axis(between));
setJointRotationInConstrainedFrame(index, rot * joint.rotation, DEFAULT_PRIORITY);
setJointRotationInConstrainedFrame(index, rot * state.getOriginalRotation(), DEFAULT_PRIORITY);
}
}

View file

@ -79,7 +79,7 @@ void RigTests::initTestCase() {
static void reportJoint(int index, JointState joint) { // Handy for debugging
std::cout << "\n";
std::cout << index << " " << joint.getFBXJoint().name.toUtf8().data() << "\n";
std::cout << index << " " << joint.getName.toUtf8().data() << "\n";
std::cout << " pos:" << joint.getPosition() << "/" << joint.getPositionInParentFrame() << " from " << joint.getParentIndex() << "\n";
std::cout << " rot:" << safeEulerAngles(joint.getRotation()) << "/" << safeEulerAngles(joint.getRotationInParentFrame()) << "/" << safeEulerAngles(joint.getRotationInBindFrame()) << "\n";
std::cout << "\n";