From 49c9d41dd5727d1b246bad83a6e9c8a76562f69b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 8 Nov 2013 14:49:38 -0800 Subject: [PATCH] Read and enforce angle constraints (untested). --- interface/src/renderer/FBXReader.cpp | 15 +++++++- interface/src/renderer/FBXReader.h | 2 + interface/src/renderer/Model.cpp | 57 +++++++++++++++++----------- interface/src/renderer/Model.h | 1 + 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index f0ed4f87b1..894ff24204 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -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& 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; diff --git a/interface/src/renderer/FBXReader.h b/interface/src/renderer/FBXReader.h index 48366c09b9..a806d1006b 100644 --- a/interface/src/renderer/FBXReader.h +++ b/interface/src/renderer/FBXReader.h @@ -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; diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 6eeca5cfd4..cadffe448d 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -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; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 3a22045b6c..c99788b03f 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -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();