From 00715f1906d95d4a56450bb12b3c20c7c6316522 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Jan 2016 10:14:37 -0800 Subject: [PATCH 1/3] apply "hips offset" to root of state graph (Somemtimes the hips are not the root. I'm looking at YOU blender!) --- libraries/animation/src/AnimInverseKinematics.cpp | 13 +++++++++++-- libraries/animation/src/AnimInverseKinematics.h | 9 +++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index e47a12960e..d7c604fff1 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -376,13 +376,13 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars ++constraintItr; } } else { - // shift the hips according to the offset from the previous frame + // shift the everything according to the _hipsOffset from the previous frame float offsetLength = glm::length(_hipsOffset); const float MIN_HIPS_OFFSET_LENGTH = 0.03f; if (offsetLength > MIN_HIPS_OFFSET_LENGTH) { // but only if offset is long enough float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); - _relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + scaleFactor * _hipsOffset; + _relativePoses[_rootIndex].trans = underPoses[_rootIndex].trans + scaleFactor * _hipsOffset; } solveWithCyclicCoordinateDescent(targets); @@ -775,9 +775,18 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele initConstraints(); _headIndex = _skeleton->nameToJointIndex("Head"); _hipsIndex = _skeleton->nameToJointIndex("Hips"); + + // walk up the hierarchy until we find the root and cache its index + _rootIndex = _hipsIndex; + int parentIndex = _skeleton->getParentIndex(_hipsIndex); + while (parentIndex != -1) { + _rootIndex = parentIndex; + parentIndex = _skeleton->getParentIndex(_rootIndex); + } } else { clearConstraints(); _headIndex = -1; _hipsIndex = -1; + _rootIndex = -1; } } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 971d2d5ff1..52dd4b5863 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -79,13 +79,14 @@ protected: AnimPoseVec _relativePoses; // current relative poses // experimental data for moving hips during IK - int _headIndex = -1; - int _hipsIndex = -1; - glm::vec3 _hipsOffset = Vectors::ZERO; + glm::vec3 _hipsOffset { Vectors::ZERO }; + int _headIndex { -1 }; + int _hipsIndex { -1 }; + int _rootIndex { -1 }; // _maxTargetIndex is tracked to help optimize the recalculation of absolute poses // during the the cyclic coordinate descent algorithm - int _maxTargetIndex = 0; + int _maxTargetIndex { 0 }; }; #endif // hifi_AnimInverseKinematics_h From f67a20ee68522aec79fc306c5a066180855e2e3e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Jan 2016 14:22:50 -0800 Subject: [PATCH 2/3] apply _hipsOffset in hips local-frame --- .../animation/src/AnimInverseKinematics.cpp | 26 ++++++++++++------- .../animation/src/AnimInverseKinematics.h | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index d7c604fff1..897b5b3858 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -382,7 +382,20 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars if (offsetLength > MIN_HIPS_OFFSET_LENGTH) { // but only if offset is long enough float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); - _relativePoses[_rootIndex].trans = underPoses[_rootIndex].trans + scaleFactor * _hipsOffset; + if (_hipsParentIndex == -1) { + // the hips are the root so _hipsOffset is in the correct frame + _relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + scaleFactor * _hipsOffset; + } else { + // the hips are NOT the root so we need to transform _hipsOffset into hips local-frame + glm::quat hipsFrameRotation = _relativePoses[_hipsParentIndex].rot; + int index = _skeleton->getParentIndex(_hipsParentIndex); + while (index != -1) { + hipsFrameRotation *= _relativePoses[index].rot; + index = _skeleton->getParentIndex(index); + } + _relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + + glm::inverse(glm::normalize(hipsFrameRotation)) * (scaleFactor * _hipsOffset); + } } solveWithCyclicCoordinateDescent(targets); @@ -776,17 +789,12 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele _headIndex = _skeleton->nameToJointIndex("Head"); _hipsIndex = _skeleton->nameToJointIndex("Hips"); - // walk up the hierarchy until we find the root and cache its index - _rootIndex = _hipsIndex; - int parentIndex = _skeleton->getParentIndex(_hipsIndex); - while (parentIndex != -1) { - _rootIndex = parentIndex; - parentIndex = _skeleton->getParentIndex(_rootIndex); - } + // also cache the _hipsParentIndex for later + _hipsParentIndex = _skeleton->getParentIndex(_hipsIndex); } else { clearConstraints(); _headIndex = -1; _hipsIndex = -1; - _rootIndex = -1; + _hipsParentIndex = -1; } } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 52dd4b5863..825577b1ae 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -82,7 +82,7 @@ protected: glm::vec3 _hipsOffset { Vectors::ZERO }; int _headIndex { -1 }; int _hipsIndex { -1 }; - int _rootIndex { -1 }; + int _hipsParentIndex { -1 }; // _maxTargetIndex is tracked to help optimize the recalculation of absolute poses // during the the cyclic coordinate descent algorithm From 1b45f5cc0c21f6997bd3e87aa86e67c4ef38908e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Jan 2016 14:44:02 -0800 Subject: [PATCH 3/3] tweaks to neck and spine constraints --- libraries/animation/src/AnimInverseKinematics.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 897b5b3858..f9c8873779 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -246,7 +246,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vectorsetReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_SPINE_TWIST = PI / 8.0f; + const float MAX_SPINE_TWIST = PI / 12.0f; stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST); std::vector minDots; @@ -658,11 +658,11 @@ void AnimInverseKinematics::initConstraints() { } else if (0 == baseName.compare("Neck", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_NECK_TWIST = PI / 6.0f; + const float MAX_NECK_TWIST = PI / 9.0f; stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST); std::vector minDots; - const float MAX_NECK_SWING = PI / 4.0f; + const float MAX_NECK_SWING = PI / 8.0f; minDots.push_back(cosf(MAX_NECK_SWING)); stConstraint->setSwingLimits(minDots); @@ -670,11 +670,11 @@ void AnimInverseKinematics::initConstraints() { } else if (0 == baseName.compare("Head", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_HEAD_TWIST = PI / 8.0f; + const float MAX_HEAD_TWIST = PI / 9.0f; stConstraint->setTwistLimits(-MAX_HEAD_TWIST, MAX_HEAD_TWIST); std::vector minDots; - const float MAX_HEAD_SWING = PI / 6.0f; + const float MAX_HEAD_SWING = PI / 10.0f; minDots.push_back(cosf(MAX_HEAD_SWING)); stConstraint->setSwingLimits(minDots);