void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) { _joints = joints; // build a cache of bind poses _absoluteBindPoses.reserve(joints.size()); _relativeBindPoses.reserve(joints.size()); // build a chache of default poses _absoluteDefaultPoses.reserve(joints.size()); _relativeDefaultPoses.reserve(joints.size()); _relativePreRotationPoses.reserve(joints.size()); _relativePostRotationPoses.reserve(joints.size()); // iterate over FBXJoints and extract the bind pose information. for (int i = 0; i < (int)joints.size(); i++) { // build pre and post transforms glm::mat4 preRotationTransform = _joints[i].preTransform * glm::mat4_cast(_joints[i].preRotation); glm::mat4 postRotationTransform = glm::mat4_cast(_joints[i].postRotation) * _joints[i].postTransform; _relativePreRotationPoses.push_back(AnimPose(preRotationTransform)); _relativePostRotationPoses.push_back(AnimPose(postRotationTransform)); // build relative and absolute default poses glm::mat4 relDefaultMat = glm::translate(_joints[i].translation) * preRotationTransform * glm::mat4_cast(_joints[i].rotation) * postRotationTransform; AnimPose relDefaultPose(relDefaultMat); _relativeDefaultPoses.push_back(relDefaultPose); int parentIndex = getParentIndex(i); if (parentIndex >= 0) { _absoluteDefaultPoses.push_back(_absoluteDefaultPoses[parentIndex] * relDefaultPose); } else { _absoluteDefaultPoses.push_back(relDefaultPose); } // build relative and absolute bind poses if (_joints[i].bindTransformFoundInCluster) { // Use the FBXJoint::bindTransform, which is absolute model coordinates // i.e. not relative to it's parent. AnimPose absoluteBindPose(_joints[i].bindTransform); _absoluteBindPoses.push_back(absoluteBindPose); if (parentIndex >= 0) { AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse(); _relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose); } else { _relativeBindPoses.push_back(absoluteBindPose); } } else { // use default transform instead _relativeBindPoses.push_back(relDefaultPose); if (parentIndex >= 0) { _absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relDefaultPose); } else { _absoluteBindPoses.push_back(relDefaultPose); } } } }
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints, const AnimPose& geometryOffset) { _joints = joints; // build a cache of bind poses _absoluteBindPoses.reserve(joints.size()); _relativeBindPoses.reserve(joints.size()); // iterate over FBXJoints and extract the bind pose information. for (size_t i = 0; i < joints.size(); i++) { if (_joints[i].bindTransformFoundInCluster) { // Use the FBXJoint::bindTransform, which is absolute model coordinates // i.e. not relative to it's parent. AnimPose absoluteBindPose(_joints[i].bindTransform); _absoluteBindPoses.push_back(absoluteBindPose); int parentIndex = getParentIndex(i); if (parentIndex >= 0) { AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse(); _relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose); } else { _relativeBindPoses.push_back(absoluteBindPose); } } else { // use FBXJoint's local transform, instead glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation); glm::mat4 relBindMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform; AnimPose relBindPose(relBindMat); _relativeBindPoses.push_back(relBindPose); int parentIndex = getParentIndex(i); if (parentIndex >= 0) { _absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relBindPose); } else { _absoluteBindPoses.push_back(relBindPose); } } } // 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. for (auto& absPose : _absoluteBindPoses) { absPose.trans = (geometryOffset * absPose).trans; absPose.scale = vec3(1, 1, 1); } // re-compute relative poses based on the modified absolute poses. for (size_t i = 0; i < _relativeBindPoses.size(); i++) { int parentIndex = getParentIndex(i); if (parentIndex >= 0) { _relativeBindPoses[i] = _absoluteBindPoses[parentIndex].inverse() * _absoluteBindPoses[i]; } else { _relativeBindPoses[i] = _absoluteBindPoses[i]; } } }
void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints) { _joints = joints; // build a cache of bind poses _absoluteBindPoses.reserve(joints.size()); _relativeBindPoses.reserve(joints.size()); // build a chache of default poses _absoluteDefaultPoses.reserve(joints.size()); _relativeDefaultPoses.reserve(joints.size()); _relativePreRotationPoses.reserve(joints.size()); _relativePostRotationPoses.reserve(joints.size()); // iterate over FBXJoints and extract the bind pose information. for (int i = 0; i < (int)joints.size(); i++) { // build pre and post transforms glm::mat4 preRotationTransform = _joints[i].preTransform * glm::mat4_cast(_joints[i].preRotation); glm::mat4 postRotationTransform = glm::mat4_cast(_joints[i].postRotation) * _joints[i].postTransform; _relativePreRotationPoses.push_back(AnimPose(preRotationTransform)); _relativePostRotationPoses.push_back(AnimPose(postRotationTransform)); // build relative and absolute default poses glm::mat4 relDefaultMat = glm::translate(_joints[i].translation) * preRotationTransform * glm::mat4_cast(_joints[i].rotation) * postRotationTransform; AnimPose relDefaultPose(relDefaultMat); _relativeDefaultPoses.push_back(relDefaultPose); int parentIndex = getParentIndex(i); if (parentIndex >= 0) { _absoluteDefaultPoses.push_back(_absoluteDefaultPoses[parentIndex] * relDefaultPose); } else { _absoluteDefaultPoses.push_back(relDefaultPose); } // build relative and absolute bind poses if (_joints[i].bindTransformFoundInCluster) { // Use the FBXJoint::bindTransform, which is absolute model coordinates // i.e. not relative to it's parent. AnimPose absoluteBindPose(_joints[i].bindTransform); _absoluteBindPoses.push_back(absoluteBindPose); if (parentIndex >= 0) { AnimPose inverseParentAbsoluteBindPose = _absoluteBindPoses[parentIndex].inverse(); _relativeBindPoses.push_back(inverseParentAbsoluteBindPose * absoluteBindPose); } else { _relativeBindPoses.push_back(absoluteBindPose); } } else { // use default transform instead _relativeBindPoses.push_back(relDefaultPose); if (parentIndex >= 0) { _absoluteBindPoses.push_back(_absoluteBindPoses[parentIndex] * relDefaultPose); } else { _absoluteBindPoses.push_back(relDefaultPose); } } } // build mirror map. _nonMirroredIndices.clear(); _mirrorMap.reserve(_joints.size()); for (int i = 0; i < (int)joints.size(); i++) { if (_joints[i].name.endsWith("tEye")) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; if (_joints[i].name.startsWith("Left")) { QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } else if (_joints[i].name.startsWith("Right")) { QString mirrorJointName = QString(_joints[i].name).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } if (mirrorJointIndex >= 0) { _mirrorMap.push_back(mirrorJointIndex); } else { _mirrorMap.push_back(i); } } }