Merge pull request #1233 from ey6es/master

Read and enforce angle constraints on joints, use incremental rotations for Leap palms.
This commit is contained in:
Philip Rosedale 2013-11-08 17:25:40 -08:00
commit 26e1e8a283
5 changed files with 58 additions and 26 deletions

View file

@ -139,8 +139,9 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector<int>& fingerJoin
const FBXGeometry& geometry = _geometry->getFBXGeometry();
setJointPosition(jointIndex, palm.getPosition());
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
glm::quat palmRotation = rotationBetween(_rotation * IDENTITY_UP, -palm.getNormal()) * _rotation *
glm::angleAxis(90.0f, 0.0f, sign, 0.0f); // ninety degree rotation to face fingers forward from bind pose
glm::quat palmRotation;
getJointRotation(jointIndex, palmRotation, true);
palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation;
// sort the finger indices by raw x, get the average direction
QVector<IndexValue> fingerIndices;

View file

@ -488,6 +488,9 @@ public:
glm::quat rotation;
glm::quat postRotation;
glm::mat4 postTransform;
glm::vec3 rotationMin;
glm::vec3 rotationMax;
};
glm::mat4 getGlobalTransform(const QMultiHash<QString, QString>& parentMap,
@ -873,6 +876,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f);
glm::vec3 scalePivot, rotationPivot;
FBXModel model = { name, -1 };
model.rotationMin = glm::vec3(-180.0f, -180.0f, -180.0f);
model.rotationMax = glm::vec3(180.0f, 180.0f, 180.0f);
foreach (const FBXNode& subobject, object.children) {
bool properties = false;
QByteArray propertyName;
@ -912,7 +917,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
scalePivot = getVec3(property.properties, index);
} else if (property.properties.at(0) == "Lcl Scaling") {
scale = getVec3(property.properties, index);
scale = getVec3(property.properties, index);
} else if (property.properties.at(0) == "RotationMin") {
model.rotationMin = getVec3(property.properties, index);
} else if (property.properties.at(0) == "RotationMax") {
model.rotationMax = getVec3(property.properties, index);
}
}
}
@ -1092,6 +1103,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
joint.rotation = model.rotation;
joint.postRotation = model.postRotation;
joint.postTransform = model.postTransform;
joint.rotationMin = model.rotationMin;
joint.rotationMax = model.rotationMax;
glm::quat combinedRotation = model.preRotation * model.rotation * model.postRotation;
if (joint.parentIndex == -1) {
joint.transform = geometry.offset * model.preTransform * glm::mat4_cast(combinedRotation) * model.postTransform;
@ -1314,6 +1327,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
geometry.meshes.append(extracted.mesh);
}
geometry.palmDirection = parseVec3(mapping.value("palmDirection", "0, -1, 0").toString());
// process attachments
QVariantHash attachments = mapping.value("attach").toHash();
for (QVariantHash::const_iterator it = attachments.constBegin(); it != attachments.constEnd(); it++) {

View file

@ -53,6 +53,8 @@ public:
glm::quat postRotation;
glm::mat4 postTransform;
glm::mat4 transform;
glm::vec3 rotationMin;
glm::vec3 rotationMax;
glm::quat inverseDefaultRotation;
glm::quat inverseBindRotation;
glm::mat4 bindTransform;
@ -143,6 +145,8 @@ public:
QVector<int> leftFingertipJointIndices;
QVector<int> rightFingertipJointIndices;
glm::vec3 palmDirection;
glm::vec3 neckPivot;
QVector<FBXAttachment> attachments;

View file

@ -584,29 +584,6 @@ bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind)
return true;
}
void Model::setJointTranslation(int jointIndex, int parentIndex, int childIndex, const glm::vec3& translation) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
JointState& state = _jointStates[jointIndex];
if (childIndex != -1 && geometry.joints.at(jointIndex).isFree) {
// if there's a child, then I must adjust *my* rotation
glm::vec3 childTranslation = extractTranslation(_jointStates.at(childIndex).transform);
glm::quat delta = rotationBetween(childTranslation - extractTranslation(state.transform),
childTranslation - translation);
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * delta * state.combinedRotation;
state.combinedRotation = delta * state.combinedRotation;
}
if (parentIndex != -1 && geometry.joints.at(parentIndex).isFree) {
// if there's a parent, then I must adjust *its* rotation
JointState& parent = _jointStates[parentIndex];
glm::vec3 parentTranslation = extractTranslation(parent.transform);
glm::quat delta = rotationBetween(extractTranslation(state.transform) - parentTranslation,
translation - parentTranslation);
parent.rotation = parent.rotation * glm::inverse(parent.combinedRotation) * delta * parent.combinedRotation;
parent.combinedRotation = delta * parent.combinedRotation;
}
::setTranslation(state.transform, translation);
}
bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int lastFreeIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return false;
@ -709,6 +686,40 @@ float Model::getLimbLength(int jointIndex) const {
return length;
}
void Model::setJointTranslation(int jointIndex, int parentIndex, int childIndex, const glm::vec3& translation) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
JointState& state = _jointStates[jointIndex];
if (childIndex != -1 && geometry.joints.at(jointIndex).isFree) {
// if there's a child, then I must adjust *my* rotation
glm::vec3 childTranslation = extractTranslation(_jointStates.at(childIndex).transform);
applyRotationDelta(jointIndex, rotationBetween(childTranslation - extractTranslation(state.transform),
childTranslation - translation));
}
if (parentIndex != -1 && geometry.joints.at(parentIndex).isFree) {
// if there's a parent, then I must adjust *its* rotation
JointState& parent = _jointStates[parentIndex];
glm::vec3 parentTranslation = extractTranslation(parent.transform);
applyRotationDelta(parentIndex, rotationBetween(extractTranslation(state.transform) - parentTranslation,
translation - parentTranslation));
}
::setTranslation(state.transform, translation);
}
void Model::applyRotationDelta(int jointIndex, const glm::quat& delta) {
JointState& state = _jointStates[jointIndex];
const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex];
if (joint.rotationMin == glm::vec3(-180.0f, -180.0f, -180.0f) && joint.rotationMax == glm::vec3(180.0f, 180.0f, 180.0f)) {
// no constraints
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * delta * state.combinedRotation;
state.combinedRotation = delta * state.combinedRotation;
return;
}
glm::quat newRotation = glm::quat(glm::radians(glm::clamp(safeEulerAngles(state.rotation *
glm::inverse(state.combinedRotation) * delta * state.combinedRotation), joint.rotationMin, joint.rotationMax)));
state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation;
state.rotation = newRotation;
}
void Model::deleteGeometry() {
foreach (Model* attachment, _attachments) {
delete attachment;

View file

@ -159,6 +159,7 @@ protected:
private:
void setJointTranslation(int jointIndex, int parentIndex, int childIndex, const glm::vec3& translation);
void applyRotationDelta(int jointIndex, const glm::quat& delta);
void deleteGeometry();