diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index cc48308f17..844ad5aef4 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -76,7 +76,7 @@ int AnimSkeleton::getChainDepth(int jointIndex) const { int index = jointIndex; do { chainDepth++; - index = _joints[index].parentIndex; + index = _parentIndices[index]; } while (index != -1); return chainDepth; } else { @@ -102,17 +102,12 @@ const AnimPose& AnimSkeleton::getPostRotationPose(int jointIndex) const { return _relativePostRotationPoses[jointIndex]; } -int AnimSkeleton::getParentIndex(int jointIndex) const { - return _joints[jointIndex].parentIndex; -} - std::vector AnimSkeleton::getChildrenOfJoint(int jointIndex) const { // Children and grandchildren, etc. std::vector result; if (jointIndex != -1) { - for (int i = jointIndex + 1; i < (int)_joints.size(); i++) { - if (_joints[i].parentIndex == jointIndex - || (std::find(result.begin(), result.end(), _joints[i].parentIndex) != result.end())) { + for (int i = jointIndex + 1; i < (int)_parentIndices.size(); i++) { + if (_parentIndices[i] == jointIndex || (std::find(result.begin(), result.end(), _parentIndices[i]) != result.end())) { result.push_back(i); } } @@ -128,7 +123,7 @@ AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relati if (jointIndex < 0 || jointIndex >= (int)relativePoses.size() || jointIndex >= _jointsSize) { return AnimPose::identity; } else { - return getAbsolutePose(_joints[jointIndex].parentIndex, relativePoses) * relativePoses[jointIndex]; + return getAbsolutePose(_parentIndices[jointIndex], relativePoses) * relativePoses[jointIndex]; } } @@ -136,7 +131,7 @@ void AnimSkeleton::convertRelativePosesToAbsolute(AnimPoseVec& poses) const { // poses start off relative and leave in absolute frame int lastIndex = std::min((int)poses.size(), _jointsSize); for (int i = 0; i < lastIndex; ++i) { - int parentIndex = _joints[i].parentIndex; + int parentIndex = _parentIndices[i]; if (parentIndex != -1) { poses[i] = poses[parentIndex] * poses[i]; } @@ -147,7 +142,7 @@ void AnimSkeleton::convertAbsolutePosesToRelative(AnimPoseVec& poses) const { // poses start off absolute and leave in relative frame int lastIndex = std::min((int)poses.size(), _jointsSize); for (int i = lastIndex - 1; i >= 0; --i) { - int parentIndex = _joints[i].parentIndex; + int parentIndex = _parentIndices[i]; if (parentIndex != -1) { poses[i] = poses[parentIndex].inverse() * poses[i]; } @@ -158,7 +153,7 @@ void AnimSkeleton::convertAbsoluteRotationsToRelative(std::vector& ro // poses start off absolute and leave in relative frame int lastIndex = std::min((int)rotations.size(), _jointsSize); for (int i = lastIndex - 1; i >= 0; --i) { - int parentIndex = _joints[i].parentIndex; + int parentIndex = _parentIndices[i]; if (parentIndex != -1) { rotations[i] = glm::inverse(rotations[parentIndex]) * rotations[i]; } @@ -197,6 +192,14 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets) { _joints = joints; + + // build a seperate vector of parentIndices for cache coherency + // AnimSkeleton::getParentIndex is called very frequently in tight loops. + _parentIndices.reserve(_joints.size()); + for (auto& joint : _joints) { + _parentIndices.push_back(joint.parentIndex); + } + _jointsSize = (int)joints.size(); // build a cache of bind poses diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 14f39eedbc..0eefbf973e 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -43,7 +43,10 @@ public: // get post transform which might include FBX offset transformations const AnimPose& getPostRotationPose(int jointIndex) const; - int getParentIndex(int jointIndex) const; + int getParentIndex(int jointIndex) const { + return _parentIndices[jointIndex]; + } + std::vector getChildrenOfJoint(int jointIndex) const; AnimPose getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const; @@ -69,6 +72,7 @@ protected: void buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets); std::vector _joints; + std::vector _parentIndices; int _jointsSize { 0 }; AnimPoseVec _relativeDefaultPoses; AnimPoseVec _absoluteDefaultPoses;