mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:24:00 +02:00
Merge pull request #2946 from AndrewMeadows/inertia
cleanup: JointState transitions toward a proper class
This commit is contained in:
commit
859461a1aa
4 changed files with 133 additions and 116 deletions
|
@ -49,9 +49,9 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||
// get the rotation axes in joint space and use them to adjust the rotation
|
||||
glm::mat3 axes = glm::mat3_cast(_rotation);
|
||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
|
||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state._translation) *
|
||||
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
||||
state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
|
||||
state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
|
||||
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1]))
|
||||
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0]))
|
||||
* joint.rotation;
|
||||
|
@ -59,23 +59,23 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
|
|||
|
||||
void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||
// likewise with the eye joints
|
||||
glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) *
|
||||
glm::mat4 inverse = glm::inverse(parentState._transform * glm::translate(state._translation) *
|
||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f));
|
||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
||||
_owningHead->getSaccade() - _translation, 1.0f));
|
||||
glm::quat between = rotationBetween(front, lookAt);
|
||||
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
|
||||
state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||
state._rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||
joint.rotation;
|
||||
}
|
||||
|
||||
void FaceModel::updateJointState(int index) {
|
||||
JointState& state = _jointStates[index];
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
if (joint.parentIndex != -1) {
|
||||
const JointState& parentState = _jointStates.at(joint.parentIndex);
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
if (index == geometry.neckJointIndex) {
|
||||
maybeUpdateNeckRotation(parentState, joint, state);
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|||
}
|
||||
int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex);
|
||||
if (jointIndex != -1) {
|
||||
setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), true, PALM_PRIORITY);
|
||||
setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), PALM_PRIORITY);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -188,8 +188,8 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
|||
setJointPosition(parentJointIndex, palm.getPosition() + forearmVector *
|
||||
geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale),
|
||||
glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
|
||||
setJointRotation(parentJointIndex, palmRotation, true, PALM_PRIORITY);
|
||||
_jointStates[jointIndex].rotation = glm::quat();
|
||||
setJointRotation(parentJointIndex, palmRotation, PALM_PRIORITY);
|
||||
_jointStates[jointIndex]._rotation = glm::quat();
|
||||
|
||||
} else {
|
||||
setJointPosition(jointIndex, palm.getPosition(), palmRotation,
|
||||
|
@ -199,10 +199,10 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
|||
|
||||
void SkeletonModel::updateJointState(int index) {
|
||||
JointState& state = _jointStates[index];
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
if (joint.parentIndex != -1) {
|
||||
const JointState& parentState = _jointStates.at(joint.parentIndex);
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
if (index == geometry.leanJointIndex) {
|
||||
maybeUpdateLeanRotation(parentState, joint, state);
|
||||
|
||||
|
@ -217,9 +217,9 @@ void SkeletonModel::updateJointState(int index) {
|
|||
Model::updateJointState(index);
|
||||
|
||||
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
||||
state.transform[3][0] = 0.0f;
|
||||
state.transform[3][1] = 0.0f;
|
||||
state.transform[3][2] = 0.0f;
|
||||
state._transform[3][0] = 0.0f;
|
||||
state._transform[3][1] = 0.0f;
|
||||
state._transform[3][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,9 +229,9 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
|
|||
}
|
||||
// get the rotation axes in joint space and use them to adjust the rotation
|
||||
glm::mat3 axes = glm::mat3_cast(_rotation);
|
||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
|
||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState._transform * glm::translate(state._translation) *
|
||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
|
||||
state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
|
||||
state._rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
|
||||
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(),
|
||||
glm::normalize(inverse * axes[0])) * joint.rotation;
|
||||
}
|
||||
|
@ -255,11 +255,11 @@ void SkeletonModel::renderJointConstraints(int jointIndex) {
|
|||
do {
|
||||
const FBXJoint& joint = geometry.joints.at(jointIndex);
|
||||
const JointState& jointState = _jointStates.at(jointIndex);
|
||||
glm::vec3 position = extractTranslation(jointState.transform) + _translation;
|
||||
glm::vec3 position = extractTranslation(jointState._transform) + _translation;
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex).combinedRotation;
|
||||
glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex)._combinedRotation;
|
||||
glm::vec3 rotationAxis = glm::axis(parentRotation);
|
||||
glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
float fanScale = directionSize * 0.75f;
|
||||
|
@ -292,7 +292,7 @@ void SkeletonModel::renderJointConstraints(int jointIndex) {
|
|||
}
|
||||
glPopMatrix();
|
||||
|
||||
renderOrientationDirections(position, jointState.combinedRotation, directionSize);
|
||||
renderOrientationDirections(position, jointState._combinedRotation, directionSize);
|
||||
jointIndex = joint.parentIndex;
|
||||
|
||||
} while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree);
|
||||
|
@ -355,12 +355,12 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c
|
|||
glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f);
|
||||
|
||||
glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
|
||||
setJointRotation(shoulderJointIndex, shoulderRotation, true, PALM_PRIORITY);
|
||||
setJointRotation(shoulderJointIndex, shoulderRotation, PALM_PRIORITY);
|
||||
|
||||
setJointRotation(elbowJointIndex, rotationBetween(shoulderRotation * forwardVector,
|
||||
wristPosition - elbowPosition) * shoulderRotation, true, PALM_PRIORITY);
|
||||
wristPosition - elbowPosition) * shoulderRotation, PALM_PRIORITY);
|
||||
|
||||
setJointRotation(jointIndex, rotation, true, PALM_PRIORITY);
|
||||
setJointRotation(jointIndex, rotation, PALM_PRIORITY);
|
||||
}
|
||||
|
||||
bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
|
||||
|
|
|
@ -135,13 +135,11 @@ void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locati
|
|||
program.release();
|
||||
}
|
||||
|
||||
QVector<Model::JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
||||
QVector<JointState> Model::createJointStates(const FBXGeometry& geometry) {
|
||||
QVector<JointState> jointStates;
|
||||
foreach (const FBXJoint& joint, geometry.joints) {
|
||||
JointState state;
|
||||
state.translation = joint.translation;
|
||||
state.rotation = joint.rotation;
|
||||
state.animationPriority = 0.0f;
|
||||
state.setFBXJoint(joint);
|
||||
jointStates.append(state);
|
||||
}
|
||||
|
||||
|
@ -160,23 +158,17 @@ QVector<Model::JointState> Model::createJointStates(const FBXGeometry& geometry)
|
|||
continue;
|
||||
}
|
||||
JointState& state = jointStates[i];
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
int parentIndex = joint.parentIndex;
|
||||
if (parentIndex == -1) {
|
||||
_rootIndex = i;
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = baseTransform * geometry.offset * glm::translate(state.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
state.combinedRotation = _rotation * combinedRotation;
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||
state.updateWorldTransform(baseTransform, _rotation);
|
||||
++numJointsSet;
|
||||
jointIsSet[i] = true;
|
||||
} else if (jointIsSet[parentIndex]) {
|
||||
const JointState& parentState = jointStates.at(parentIndex);
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = parentState.transform * glm::translate(state.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
state.combinedRotation = parentState.combinedRotation * combinedRotation;
|
||||
state.updateWorldTransform(parentState._transform, parentState._combinedRotation);
|
||||
++numJointsSet;
|
||||
jointIsSet[i] = true;
|
||||
}
|
||||
|
@ -372,7 +364,7 @@ void Model::reset() {
|
|||
}
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
_jointStates[i].rotation = geometry.joints.at(i).rotation;
|
||||
_jointStates[i]._rotation = geometry.joints.at(i).rotation;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -582,7 +574,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
|
|||
if (index == -1 || index >= _jointStates.size()) {
|
||||
return false;
|
||||
}
|
||||
rotation = _jointStates.at(index).rotation;
|
||||
rotation = _jointStates.at(index)._rotation;
|
||||
const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
||||
return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
|
||||
glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
|
||||
|
@ -593,13 +585,13 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
|
|||
void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority) {
|
||||
if (index != -1 && index < _jointStates.size()) {
|
||||
JointState& state = _jointStates[index];
|
||||
if (priority >= state.animationPriority) {
|
||||
if (priority >= state._animationPriority) {
|
||||
if (valid) {
|
||||
state.rotation = rotation;
|
||||
state.animationPriority = priority;
|
||||
} else if (priority == state.animationPriority) {
|
||||
state.rotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
||||
state.animationPriority = 0.0f;
|
||||
state._rotation = rotation;
|
||||
state._animationPriority = priority;
|
||||
} else if (priority == state._animationPriority) {
|
||||
state._rotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
||||
state._animationPriority = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -632,7 +624,7 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
|
|||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
position = _translation + extractTranslation(_jointStates[jointIndex].transform);
|
||||
position = _translation + extractTranslation(_jointStates[jointIndex]._transform);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -640,7 +632,7 @@ bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind)
|
|||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
rotation = _jointStates[jointIndex].combinedRotation *
|
||||
rotation = _jointStates[jointIndex]._combinedRotation *
|
||||
(fromBind ? _geometry->getFBXGeometry().joints[jointIndex].inverseBindRotation :
|
||||
_geometry->getFBXGeometry().joints[jointIndex].inverseDefaultRotation);
|
||||
return true;
|
||||
|
@ -858,11 +850,11 @@ void Model::updateShapePositions() {
|
|||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
// shape position and rotation need to be in world-frame
|
||||
glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition);
|
||||
glm::vec3 worldPosition = extractTranslation(_jointStates[i].transform) + jointToShapeOffset + _translation;
|
||||
glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i]._combinedRotation * joint.shapePosition);
|
||||
glm::vec3 worldPosition = extractTranslation(_jointStates[i]._transform) + jointToShapeOffset + _translation;
|
||||
Shape* shape = _jointShapes[i];
|
||||
shape->setPosition(worldPosition);
|
||||
shape->setRotation(_jointStates[i].combinedRotation * joint.shapeRotation);
|
||||
shape->setRotation(_jointStates[i]._combinedRotation * joint.shapeRotation);
|
||||
float distance = glm::distance(worldPosition, _translation) + shape->getBoundingRadius();
|
||||
if (distance > _boundingRadius) {
|
||||
_boundingRadius = distance;
|
||||
|
@ -884,12 +876,12 @@ bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direct
|
|||
float radiusScale = extractUniformScale(_scale);
|
||||
for (int i = 0; i < _jointStates.size(); i++) {
|
||||
const FBXJoint& joint = geometry.joints[i];
|
||||
glm::vec3 end = extractTranslation(_jointStates[i].transform);
|
||||
glm::vec3 end = extractTranslation(_jointStates[i]._transform);
|
||||
float endRadius = joint.boneRadius * radiusScale;
|
||||
glm::vec3 start = end;
|
||||
float startRadius = joint.boneRadius * radiusScale;
|
||||
if (joint.parentIndex != -1) {
|
||||
start = extractTranslation(_jointStates[joint.parentIndex].transform);
|
||||
start = extractTranslation(_jointStates[joint.parentIndex]._transform);
|
||||
startRadius = geometry.joints[joint.parentIndex].boneRadius * radiusScale;
|
||||
}
|
||||
// for now, use average of start and end radii
|
||||
|
@ -1115,7 +1107,7 @@ void Model::simulateInternal(float deltaTime) {
|
|||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||
state.clusterMatrices[j] = _jointStates[cluster.jointIndex].transform * cluster.inverseBindMatrix;
|
||||
state.clusterMatrices[j] = _jointStates[cluster.jointIndex]._transform * cluster.inverseBindMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1127,21 +1119,15 @@ void Model::simulateInternal(float deltaTime) {
|
|||
|
||||
void Model::updateJointState(int index) {
|
||||
JointState& state = _jointStates[index];
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = baseTransform * geometry.offset * glm::translate(state.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
state.combinedRotation = _rotation * combinedRotation;
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||
state.updateWorldTransform(baseTransform, _rotation);
|
||||
} else {
|
||||
const JointState& parentState = _jointStates.at(joint.parentIndex);
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = parentState.transform * glm::translate(state.translation) * joint.preTransform *
|
||||
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||
state.combinedRotation = parentState.combinedRotation * combinedRotation;
|
||||
state.updateWorldTransform(parentState._transform, parentState._combinedRotation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1174,17 +1160,17 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
|||
}
|
||||
|
||||
// then, we go from the joint upwards, rotating the end as close as possible to the target
|
||||
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].transform);
|
||||
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex]._transform);
|
||||
for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) {
|
||||
int index = freeLineage.at(j);
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
JointState& state = _jointStates[index];
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
if (!(joint.isFree || allIntermediatesFree)) {
|
||||
continue;
|
||||
}
|
||||
JointState& state = _jointStates[index];
|
||||
glm::vec3 jointPosition = extractTranslation(state.transform);
|
||||
glm::vec3 jointPosition = extractTranslation(state._transform);
|
||||
glm::vec3 jointVector = endPosition - jointPosition;
|
||||
glm::quat oldCombinedRotation = state.combinedRotation;
|
||||
glm::quat oldCombinedRotation = state._combinedRotation;
|
||||
glm::quat combinedDelta;
|
||||
float combinedWeight;
|
||||
if (useRotation) {
|
||||
|
@ -1202,7 +1188,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
|||
for (int k = j - 1; k > 0; k--) {
|
||||
int index = freeLineage.at(k);
|
||||
updateJointState(index);
|
||||
positionSum += extractTranslation(_jointStates.at(index).transform);
|
||||
positionSum += extractTranslation(_jointStates.at(index)._transform);
|
||||
}
|
||||
glm::vec3 projectedCenterOfMass = glm::cross(jointVector,
|
||||
glm::cross(positionSum / (j - 1.0f) - jointPosition, jointVector));
|
||||
|
@ -1214,7 +1200,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
|||
}
|
||||
}
|
||||
applyRotationDelta(index, combinedDelta, true, priority);
|
||||
glm::quat actualDelta = state.combinedRotation * glm::inverse(oldCombinedRotation);
|
||||
glm::quat actualDelta = state._combinedRotation * glm::inverse(oldCombinedRotation);
|
||||
endPosition = actualDelta * jointVector + jointPosition;
|
||||
if (useRotation) {
|
||||
endRotation = actualDelta * endRotation;
|
||||
|
@ -1231,35 +1217,34 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind, float priority) {
|
||||
bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, float priority) {
|
||||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
JointState& state = _jointStates[jointIndex];
|
||||
if (priority >= state.animationPriority) {
|
||||
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * rotation *
|
||||
glm::inverse(fromBind ? _geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation :
|
||||
_geometry->getFBXGeometry().joints.at(jointIndex).inverseDefaultRotation);
|
||||
state.animationPriority = priority;
|
||||
if (priority >= state._animationPriority) {
|
||||
state._rotation = state._rotation * glm::inverse(state._combinedRotation) * rotation *
|
||||
glm::inverse(_geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation);
|
||||
state._animationPriority = priority;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Model::setJointTranslation(int jointIndex, const glm::vec3& translation) {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const FBXJoint& joint = geometry.joints.at(jointIndex);
|
||||
JointState& state = _jointStates[jointIndex];
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
|
||||
glm::mat4 parentTransform;
|
||||
if (joint.parentIndex == -1) {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
parentTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||
|
||||
} else {
|
||||
parentTransform = _jointStates.at(joint.parentIndex).transform;
|
||||
parentTransform = _jointStates.at(joint.parentIndex)._transform;
|
||||
}
|
||||
JointState& state = _jointStates[jointIndex];
|
||||
glm::vec3 preTranslation = extractTranslation(joint.preTransform * glm::mat4_cast(joint.preRotation *
|
||||
state.rotation * joint.postRotation) * joint.postTransform);
|
||||
state.translation = glm::vec3(glm::inverse(parentTransform) * glm::vec4(translation, 1.0f)) - preTranslation;
|
||||
state._rotation * joint.postRotation) * joint.postTransform);
|
||||
state._translation = glm::vec3(glm::inverse(parentTransform) * glm::vec4(translation, 1.0f)) - preTranslation;
|
||||
}
|
||||
|
||||
bool Model::restoreJointPosition(int jointIndex, float percent, float priority) {
|
||||
|
@ -1271,11 +1256,11 @@ bool Model::restoreJointPosition(int jointIndex, float percent, float priority)
|
|||
|
||||
foreach (int index, freeLineage) {
|
||||
JointState& state = _jointStates[index];
|
||||
if (priority == state.animationPriority) {
|
||||
if (priority == state._animationPriority) {
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
state.rotation = safeMix(state.rotation, joint.rotation, percent);
|
||||
state.translation = glm::mix(state.translation, joint.translation, percent);
|
||||
state.animationPriority = 0.0f;
|
||||
state._rotation = safeMix(state._rotation, joint.rotation, percent);
|
||||
state._translation = glm::mix(state._translation, joint.translation, percent);
|
||||
state._animationPriority = 0.0f;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -1297,23 +1282,23 @@ float Model::getLimbLength(int jointIndex) const {
|
|||
|
||||
void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) {
|
||||
JointState& state = _jointStates[jointIndex];
|
||||
if (priority < state.animationPriority) {
|
||||
if (priority < state._animationPriority) {
|
||||
return;
|
||||
}
|
||||
state.animationPriority = priority;
|
||||
const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex];
|
||||
state._animationPriority = priority;
|
||||
const FBXJoint& joint = state.getFBXJoint();
|
||||
if (!constrain || (joint.rotationMin == glm::vec3(-PI, -PI, -PI) &&
|
||||
joint.rotationMax == glm::vec3(PI, PI, PI))) {
|
||||
// no constraints
|
||||
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * delta * state.combinedRotation;
|
||||
state.combinedRotation = delta * state.combinedRotation;
|
||||
state._rotation = state._rotation * glm::inverse(state._combinedRotation) * delta * state._combinedRotation;
|
||||
state._combinedRotation = delta * state._combinedRotation;
|
||||
return;
|
||||
}
|
||||
glm::quat targetRotation = delta * state.combinedRotation;
|
||||
glm::vec3 eulers = safeEulerAngles(state.rotation * glm::inverse(state.combinedRotation) * targetRotation);
|
||||
glm::quat targetRotation = delta * state._combinedRotation;
|
||||
glm::vec3 eulers = safeEulerAngles(state._rotation * glm::inverse(state._combinedRotation) * targetRotation);
|
||||
glm::quat newRotation = glm::quat(glm::clamp(eulers, joint.rotationMin, joint.rotationMax));
|
||||
state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation;
|
||||
state.rotation = newRotation;
|
||||
state._combinedRotation = state._combinedRotation * glm::inverse(state._rotation) * newRotation;
|
||||
state._rotation = newRotation;
|
||||
}
|
||||
|
||||
const int BALL_SUBDIVISIONS = 10;
|
||||
|
@ -1851,10 +1836,10 @@ void AnimationHandle::simulate(float deltaTime) {
|
|||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int mapping = _jointMappings.at(i);
|
||||
if (mapping != -1) {
|
||||
Model::JointState& state = _model->_jointStates[mapping];
|
||||
if (_priority >= state.animationPriority) {
|
||||
state.rotation = frame.rotations.at(i);
|
||||
state.animationPriority = _priority;
|
||||
JointState& state = _model->_jointStates[mapping];
|
||||
if (_priority >= state._animationPriority) {
|
||||
state._rotation = frame.rotations.at(i);
|
||||
state._animationPriority = _priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1875,10 +1860,10 @@ void AnimationHandle::simulate(float deltaTime) {
|
|||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int mapping = _jointMappings.at(i);
|
||||
if (mapping != -1) {
|
||||
Model::JointState& state = _model->_jointStates[mapping];
|
||||
if (_priority >= state.animationPriority) {
|
||||
state.rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||
state.animationPriority = _priority;
|
||||
JointState& state = _model->_jointStates[mapping];
|
||||
if (_priority >= state._animationPriority) {
|
||||
state._rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||
state._animationPriority = _priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1888,10 +1873,32 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) {
|
|||
for (int i = 0; i < _jointMappings.size(); i++) {
|
||||
int mapping = _jointMappings.at(i);
|
||||
if (mapping != -1) {
|
||||
Model::JointState& state = _model->_jointStates[mapping];
|
||||
if (_priority == state.animationPriority) {
|
||||
state.animationPriority = newPriority;
|
||||
JointState& state = _model->_jointStates[mapping];
|
||||
if (_priority == state._animationPriority) {
|
||||
state._animationPriority = newPriority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// JointState TODO: move this class to its own files
|
||||
// ----------------------------------------------------------------------------
|
||||
JointState::JointState() :
|
||||
_translation(0.0f),
|
||||
_animationPriority(0.0f),
|
||||
_fbxJoint(NULL) {
|
||||
}
|
||||
|
||||
void JointState::setFBXJoint(const FBXJoint& joint) {
|
||||
assert(&joint != NULL);
|
||||
_translation = joint.translation;
|
||||
_rotation = joint.rotation;
|
||||
_fbxJoint = &joint;
|
||||
}
|
||||
|
||||
void JointState::updateWorldTransform(const glm::mat4& baseTransform, const glm::quat& parentRotation) {
|
||||
glm::quat combinedRotation = _fbxJoint->preRotation * _rotation * _fbxJoint->postRotation;
|
||||
_transform = baseTransform * glm::translate(_translation) * _fbxJoint->preTransform * glm::mat4_cast(combinedRotation) * _fbxJoint->postTransform;
|
||||
_combinedRotation = parentRotation * combinedRotation;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,25 @@ class Shape;
|
|||
|
||||
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
||||
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||
|
||||
class JointState {
|
||||
public:
|
||||
JointState();
|
||||
|
||||
void setFBXJoint(const FBXJoint& joint);
|
||||
const FBXJoint& getFBXJoint() const { return *_fbxJoint; }
|
||||
|
||||
void updateWorldTransform(const glm::mat4& baseTransform, const glm::quat& parentRotation);
|
||||
|
||||
glm::vec3 _translation; // translation relative to parent
|
||||
glm::quat _rotation; // rotation relative to parent
|
||||
glm::mat4 _transform; // rotation to world frame + translation in model frame
|
||||
glm::quat _combinedRotation; // rotation from joint local to world frame
|
||||
float _animationPriority; // the priority of the animation affecting this joint
|
||||
|
||||
private:
|
||||
const FBXJoint* _fbxJoint; // JointState does not own its FBXJoint
|
||||
};
|
||||
|
||||
/// A generic 3D model displaying geometry loaded from a URL.
|
||||
class Model : public QObject {
|
||||
|
@ -182,15 +201,6 @@ protected:
|
|||
bool _snappedToCenter; /// are we currently snapped to center
|
||||
int _rootIndex;
|
||||
|
||||
class JointState {
|
||||
public:
|
||||
glm::vec3 translation; // translation relative to parent
|
||||
glm::quat rotation; // rotation relative to parent
|
||||
glm::mat4 transform; // rotation to world frame + translation in model frame
|
||||
glm::quat combinedRotation; // rotation from joint local to world frame
|
||||
float animationPriority; // the priority of the animation affecting this joint
|
||||
};
|
||||
|
||||
bool _shapesAreDirty;
|
||||
QVector<JointState> _jointStates;
|
||||
QVector<Shape*> _jointShapes;
|
||||
|
@ -221,7 +231,7 @@ protected:
|
|||
bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(),
|
||||
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
|
||||
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
|
||||
bool setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind = false, float priority = 1.0f);
|
||||
bool setJointRotation(int jointIndex, const glm::quat& rotation, float priority = 1.0f);
|
||||
|
||||
void setJointTranslation(int jointIndex, const glm::vec3& translation);
|
||||
|
||||
|
|
Loading…
Reference in a new issue