From e2a729b68b2edbd32d1e4e17cfab8e09101508c7 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 29 Jan 2019 17:25:25 -0800 Subject: [PATCH] got the spline working in myskeleton model, need to clean up --- interface/src/avatar/MySkeletonModel.cpp | 44 ++++++++++++++++++++++++ interface/src/avatar/MySkeletonModel.h | 1 + libraries/animation/src/AnimSplineIK.cpp | 36 ++++++++++++------- libraries/animation/src/AnimSplineIK.h | 4 +-- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 26d69841d0..352e7ce6b0 100755 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -33,6 +33,39 @@ Rig::CharacterControllerState convertCharacterControllerState(CharacterControlle }; } +static CubicHermiteSplineFunctorWithArcLength computeSplineFromTipAndBase(const AnimPose& tipPose, const AnimPose& basePose, float baseGain = 1.0f, float tipGain = 1.0f) { + float linearDistance = glm::length(basePose.trans() - tipPose.trans()); + glm::vec3 p0 = basePose.trans(); + glm::vec3 m0 = baseGain * linearDistance * (basePose.rot() * Vectors::UNIT_Y); + glm::vec3 p1 = tipPose.trans(); + glm::vec3 m1 = tipGain * linearDistance * (tipPose.rot() * Vectors::UNIT_Y); + + return CubicHermiteSplineFunctorWithArcLength(p0, m0, p1, m1); +} + +static glm::vec3 computeSpine2WithHeadHipsSpline(MyAvatar* myAvatar, AnimPose hipsIKTargetPose, AnimPose headIKTargetPose) { + glm::vec3 basePosition = myAvatar->getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar->getJointIndex("Hips")); + glm::vec3 tipPosition = myAvatar->getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar->getJointIndex("Head")); + glm::vec3 spine2Position = myAvatar->getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar->getJointIndex("Spine2")); + glm::vec3 baseToTip = tipPosition - basePosition; + float baseToTipLength = glm::length(baseToTip); + glm::vec3 baseToTipNormal = baseToTip / baseToTipLength; + glm::vec3 baseToSpine2 = spine2Position - basePosition; + float ratio = glm::dot(baseToSpine2, baseToTipNormal) / baseToTipLength; + + // the the ik targets to compute the spline with + CubicHermiteSplineFunctorWithArcLength spline = computeSplineFromTipAndBase(headIKTargetPose, hipsIKTargetPose); + + // measure the total arc length along the spline + float totalArcLength = spline.arcLength(1.0f); + float t = spline.arcLengthInverse(ratio * totalArcLength); + + glm::vec3 spine2Translation = spline(t); + + return spine2Translation; + +} + static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) { glm::mat4 worldToSensorMat = glm::inverse(myAvatar->getSensorToWorldMatrix()); @@ -233,6 +266,12 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { myAvatar->getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND).isValid() && !(params.primaryControllerFlags[Rig::PrimaryControllerType_Spine2] & (uint8_t)Rig::ControllerFlags::Enabled)) { + controller::Pose headSplineControllerPose = myAvatar->getControllerPoseInSensorFrame(controller::Action::HEAD); + AnimPose headSplinePose(headSplineControllerPose.getRotation(), headSplineControllerPose.getTranslation()); + glm::vec3 spine2TargetTranslation = computeSpine2WithHeadHipsSpline(myAvatar, sensorHips, headSplinePose); + AnimPose sensorSpine2(Quaternions::IDENTITY, spine2TargetTranslation); + AnimPose rigSpine2 = sensorToRigPose * sensorSpine2; + const float SPINE2_ROTATION_FILTER = 0.5f; AnimPose currentSpine2Pose; AnimPose currentHeadPose; @@ -253,6 +292,11 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { } generateBasisVectors(up, fwd, u, v, w); AnimPose newSpinePose(glm::mat4(glm::vec4(w, 0.0f), glm::vec4(u, 0.0f), glm::vec4(v, 0.0f), glm::vec4(glm::vec3(0.0f, 0.0f, 0.0f), 1.0f))); + currentSpine2Pose.trans() = rigSpine2.trans(); + qCDebug(animation) << "my skeleton model spline spine2 " << rigSpine2.trans(); + qCDebug(animation) << "my skeleton model current spine2 " << currentSpine2Pose.trans(); + // qCDebug(animation) << "my skeleton model spline hips " << sensorToRigPose * sensorHips; + // qCDebug(animation) << "my skeleton model current hips " << currentHipsPose.trans(); currentSpine2Pose.rot() = safeLerp(currentSpine2Pose.rot(), newSpinePose.rot(), SPINE2_ROTATION_FILTER); params.primaryControllerPoses[Rig::PrimaryControllerType_Spine2] = currentSpine2Pose; params.primaryControllerFlags[Rig::PrimaryControllerType_Spine2] = (uint8_t)Rig::ControllerFlags::Enabled | (uint8_t)Rig::ControllerFlags::Estimated; diff --git a/interface/src/avatar/MySkeletonModel.h b/interface/src/avatar/MySkeletonModel.h index 9a3559ddf7..7ea142b011 100644 --- a/interface/src/avatar/MySkeletonModel.h +++ b/interface/src/avatar/MySkeletonModel.h @@ -12,6 +12,7 @@ #include #include #include "MyAvatar.h" +#include /// A skeleton loaded from a model. class MySkeletonModel : public SkeletonModel { diff --git a/libraries/animation/src/AnimSplineIK.cpp b/libraries/animation/src/AnimSplineIK.cpp index 220546f31e..3aca678fa3 100644 --- a/libraries/animation/src/AnimSplineIK.cpp +++ b/libraries/animation/src/AnimSplineIK.cpp @@ -147,7 +147,7 @@ const AnimPoseVec& AnimSplineIK::evaluate(const AnimVariantMap& animVars, const tipTarget.setWeight(1.0f); tipTarget.setFlexCoefficients(_numTipTargetFlexCoefficients, _tipTargetFlexCoefficients); - + /* AnimChain jointChain; AnimPoseVec absolutePoses; absolutePoses.resize(_poses.size()); @@ -156,6 +156,7 @@ const AnimPoseVec& AnimSplineIK::evaluate(const AnimVariantMap& animVars, const solveTargetWithSpline(context, _baseJointIndex, tipTarget, absolutePoses, context.getEnableDebugDrawIKChains(), jointChain); jointChain.buildDirtyAbsolutePoses(); jointChain.outputRelativePoses(_poses); + */ IKTarget midTarget; if (_midJointIndex != -1) { @@ -167,7 +168,9 @@ const AnimPoseVec& AnimSplineIK::evaluate(const AnimVariantMap& animVars, const AnimPose afterSolveMidTarget = _skeleton->getAbsolutePose(_midJointIndex, _poses); // use the rotation from the ik target value, if there is one. glm::quat midTargetRotation = animVars.lookupRigToGeometry(_midRotationVar, afterSolveMidTarget.rot()); - AnimPose updatedMidTarget = AnimPose(midTargetRotation, afterSolveMidTarget.trans()); + glm::vec3 midTargetPosition = animVars.lookupRigToGeometry(_midPositionVar, afterSolveMidTarget.trans()); + AnimPose updatedMidTarget = AnimPose(midTargetRotation, midTargetPosition); + //qCDebug(animation) << "spine2 in AnimSpline " << updatedMidTarget.trans(); midTarget.setPose(updatedMidTarget.rot(), updatedMidTarget.trans()); midTarget.setWeight(1.0f); midTarget.setFlexCoefficients(_numMidTargetFlexCoefficients, _midTargetFlexCoefficients); @@ -194,9 +197,10 @@ const AnimPoseVec& AnimSplineIK::evaluate(const AnimVariantMap& animVars, const // set the mid to tip segment to match the absolute rotation of the tip target. AnimPose midTargetPose(midTarget.getRotation(), midTarget.getTranslation()); - _poses[childOfMiddleJointIndex] = midTargetPose.inverse() * childOfMiddleJointAbsolutePoseAfterBaseTipSpline; + //_poses[childOfMiddleJointIndex] = midTargetPose.inverse() * childOfMiddleJointAbsolutePoseAfterBaseTipSpline; } + _splineJointInfoMap.clear(); AnimChain upperJointChain; AnimPoseVec finalAbsolutePoses; @@ -206,7 +210,7 @@ const AnimPoseVec& AnimSplineIK::evaluate(const AnimVariantMap& animVars, const solveTargetWithSpline(context, _midJointIndex, tipTarget, finalAbsolutePoses, context.getEnableDebugDrawIKChains(), upperJointChain); upperJointChain.buildDirtyAbsolutePoses(); upperJointChain.outputRelativePoses(_poses); - + } @@ -370,8 +374,10 @@ void AnimSplineIK::solveTargetWithSpline(const AnimContext& context, int base, c tipPose.rot() = -tipPose.rot(); } // find or create splineJointInfo for this target - const std::vector* splineJointInfoVec = findOrCreateSplineJointInfo(context, target); + const std::vector* splineJointInfoVec = findOrCreateSplineJointInfo(context, base, target); + //qCDebug(animation) << "the size of the splineJointInfo is " << splineJointInfoVec->size() << " and the base index is "<size() > 0) { const int baseParentIndex = _skeleton->getParentIndex(baseIndex); AnimPose parentAbsPose = (baseParentIndex >= 0) ? absolutePoses[baseParentIndex] : AnimPose(); @@ -403,9 +409,9 @@ void AnimSplineIK::solveTargetWithSpline(const AnimContext& context, int base, c ::blend(1, &absolutePoses[splineJointInfo.jointIndex], &desiredAbsPose, target.getFlexCoefficient(i), &flexedAbsPose); AnimPose relPose = parentAbsPose.inverse() * flexedAbsPose; - + /* bool constrained = false; - if (splineJointInfo.jointIndex != _baseJointIndex) { + if (splineJointInfo.jointIndex != base) { // constrain the amount the spine can stretch or compress float length = glm::length(relPose.trans()); const float EPSILON = 0.0001f; @@ -425,6 +431,7 @@ void AnimSplineIK::solveTargetWithSpline(const AnimContext& context, int base, c relPose.trans() = glm::vec3(0.0f); } } + */ if (!chainInfoOut.setRelativePoseAtJointIndex(splineJointInfo.jointIndex, relPose)) { qCDebug(animation) << "we didn't find the joint index for the spline!!!!"; } @@ -439,13 +446,13 @@ void AnimSplineIK::solveTargetWithSpline(const AnimContext& context, int base, c } } -const std::vector* AnimSplineIK::findOrCreateSplineJointInfo(const AnimContext& context, const IKTarget& target) const { +const std::vector* AnimSplineIK::findOrCreateSplineJointInfo(const AnimContext& context, int base, const IKTarget& target) const { // find or create splineJointInfo for this target auto iter = _splineJointInfoMap.find(target.getIndex()); if (iter != _splineJointInfoMap.end()) { return &(iter->second); } else { - computeAndCacheSplineJointInfosForIKTarget(context, target); + computeAndCacheSplineJointInfosForIKTarget(context, base, target); auto iter = _splineJointInfoMap.find(target.getIndex()); if (iter != _splineJointInfoMap.end()) { return &(iter->second); @@ -455,12 +462,14 @@ const std::vector* AnimSplineIK::findOrCreateSpli } // pre-compute information about each joint influenced by this spline IK target. -void AnimSplineIK::computeAndCacheSplineJointInfosForIKTarget(const AnimContext& context, const IKTarget& target) const { +void AnimSplineIK::computeAndCacheSplineJointInfosForIKTarget(const AnimContext& context, int base, const IKTarget& target) const { std::vector splineJointInfoVec; + //qCDebug(animation) << "the base in compute cache is " << base; + // build spline between the default poses. AnimPose tipPose = _skeleton->getAbsoluteDefaultPose(target.getIndex()); - AnimPose basePose = _skeleton->getAbsoluteDefaultPose(_baseJointIndex); + AnimPose basePose = _skeleton->getAbsoluteDefaultPose(base); CubicHermiteSplineFunctorWithArcLength spline; if (target.getIndex() == _tipJointIndex) { @@ -481,10 +490,11 @@ void AnimSplineIK::computeAndCacheSplineJointInfosForIKTarget(const AnimContext& int index = target.getIndex(); int endIndex; + // fix this statement. AA if (target.getIndex() == _tipJointIndex) { - endIndex = _skeleton->getParentIndex(_baseJointIndex); + endIndex = _skeleton->getParentIndex(base); } else { - endIndex = _skeleton->getParentIndex(_baseJointIndex); + endIndex = _skeleton->getParentIndex(base); } while (index != endIndex) { AnimPose defaultPose = _skeleton->getAbsoluteDefaultPose(index); diff --git a/libraries/animation/src/AnimSplineIK.h b/libraries/animation/src/AnimSplineIK.h index 5d45d9528f..d664cf37a4 100644 --- a/libraries/animation/src/AnimSplineIK.h +++ b/libraries/animation/src/AnimSplineIK.h @@ -95,8 +95,8 @@ protected: bool _lastEnableDebugDrawIKTargets { false }; void AnimSplineIK::solveTargetWithSpline(const AnimContext& context, int base, const IKTarget& target, const AnimPoseVec& absolutePoses, bool debug, AnimChain& chainInfoOut) const; - void computeAndCacheSplineJointInfosForIKTarget(const AnimContext& context, const IKTarget& target) const; - const std::vector* findOrCreateSplineJointInfo(const AnimContext& context, const IKTarget& target) const; + void computeAndCacheSplineJointInfosForIKTarget(const AnimContext& context, int base, const IKTarget& target) const; + const std::vector* findOrCreateSplineJointInfo(const AnimContext& context, int base, const IKTarget& target) const; mutable std::map> _splineJointInfoMap; // no copies