From 2e1a4545c6dde3b4586a160e95132ae8c8405f01 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 30 Jan 2019 14:47:03 -0800 Subject: [PATCH] cache the spine2 spline default offset and ratio --- interface/src/avatar/MySkeletonModel.cpp | 52 ++++++++++++++----- .../src/avatars-renderer/Avatar.cpp | 46 ++++++++++++++++ .../src/avatars-renderer/Avatar.h | 9 ++++ libraries/shared/src/AvatarConstants.h | 1 + 4 files changed, 94 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 38f18d2ac9..e77f74de47 100755 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -44,25 +44,46 @@ static CubicHermiteSplineFunctorWithArcLength computeSplineFromTipAndBase(const } 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")); + /* + AnimPose avatarToRigPose(glm::vec3(1.0f), Quaternions::Y_180, glm::vec3(0.0f)); + + AnimPose hipsDefaultPoseAvatarSpace(myAvatar->getAbsoluteDefaultJointRotationInObjectFrame(myAvatar->getJointIndex("Hips")), myAvatar->getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar->getJointIndex("Hips"))); + AnimPose headDefaultPoseAvatarSpace(myAvatar->getAbsoluteDefaultJointRotationInObjectFrame(myAvatar->getJointIndex("Head")), myAvatar->getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar->getJointIndex("Head"))); + AnimPose spine2DefaultPoseAvatarSpace(myAvatar->getAbsoluteDefaultJointRotationInObjectFrame(myAvatar->getJointIndex("Spine2")), myAvatar->getAbsoluteDefaultJointTranslationInObjectFrame(myAvatar->getJointIndex("Spine2"))); + AnimPose hipsDefaultPoseRigSpace = avatarToRigPose * hipsDefaultPoseAvatarSpace; + AnimPose headDefaultPoseRigSpace = avatarToRigPose * headDefaultPoseAvatarSpace; + AnimPose spine2DefaultPoseRigSpace = avatarToRigPose * spine2DefaultPoseAvatarSpace; + + + glm::vec3 basePosition = hipsDefaultPoseRigSpace.trans(); + glm::vec3 tipPosition = headDefaultPoseRigSpace.trans(); + glm::vec3 spine2Position = spine2DefaultPoseRigSpace.trans(); 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; + CubicHermiteSplineFunctorWithArcLength defaultSpline = computeSplineFromTipAndBase(headDefaultPoseRigSpace, hipsDefaultPoseRigSpace); + // measure the total arc length along the spline + float totalDefaultArcLength = defaultSpline.arcLength(1.0f); + float t = defaultSpline.arcLengthInverse(ratio * totalDefaultArcLength); + glm::vec3 defaultSplineSpine2Translation = defaultSpline(t); + + glm::vec3 offset = spine2Position - defaultSplineSpine2Translation; + + qCDebug(animation) << "the my skeleton model numbers are " << ratio << " and " << offset; + */ // the the ik targets to compute the spline with - CubicHermiteSplineFunctorWithArcLength spline = computeSplineFromTipAndBase(headIKTargetPose, hipsIKTargetPose); + CubicHermiteSplineFunctorWithArcLength splineFinal = computeSplineFromTipAndBase(headIKTargetPose, hipsIKTargetPose); // measure the total arc length along the spline - float totalArcLength = spline.arcLength(1.0f); - float t = spline.arcLengthInverse(ratio * totalArcLength); + float totalArcLength = splineFinal.arcLength(1.0f); + float tFinal = splineFinal.arcLengthInverse(myAvatar->getSpine2SplineRatio() * totalArcLength); - glm::vec3 spine2Translation = spline(t); + glm::vec3 spine2Translation = splineFinal(tFinal); - return spine2Translation; + return spine2Translation + myAvatar->getSpine2SplineOffset(); } @@ -266,11 +287,14 @@ 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; + // if (avatarHeadPose.isValid()) { + + AnimPose headAvatarSpace(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation()); + AnimPose headRigSpace = avatarToRigPose * headAvatarSpace; + AnimPose hipsRigSpace = sensorToRigPose * sensorHips; + glm::vec3 spine2TargetTranslation = computeSpine2WithHeadHipsSpline(myAvatar, hipsRigSpace, headRigSpace); + //AnimPose rigSpine2(Quaternions::IDENTITY, spine2TargetTranslation); + //AnimPose rigSpine2 = sensorToRigPose * sensorSpine2; const float SPINE2_ROTATION_FILTER = 0.5f; AnimPose currentSpine2Pose; @@ -292,7 +316,7 @@ 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(); + currentSpine2Pose.trans() = spine2TargetTranslation; 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/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 17d10cdf49..1ae53e2023 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1420,11 +1420,13 @@ void Avatar::setModelURLFinished(bool success) { // rig is ready void Avatar::rigReady() { buildUnscaledEyeHeightCache(); + buildSpine2SplineRatioCache(); } // rig has been reset. void Avatar::rigReset() { clearUnscaledEyeHeightCache(); + clearSpine2SplineRatioCache(); } // create new model, can return an instance of a SoftAttachmentModel rather then Model @@ -1821,10 +1823,54 @@ void Avatar::buildUnscaledEyeHeightCache() { } } +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); +} + +void Avatar::buildSpine2SplineRatioCache() { + if (_skeletonModel) { + auto& rig = _skeletonModel->getRig(); + AnimPose hipsRigDefaultPose = rig.getAbsoluteDefaultPose(rig.indexOfJoint("Hips")); + AnimPose headRigDefaultPose(rig.getAbsoluteDefaultPose(rig.indexOfJoint("Head"))); + glm::vec3 basePosition = hipsRigDefaultPose.trans(); + glm::vec3 tipPosition = headRigDefaultPose.trans(); + glm::vec3 spine2Position = rig.getAbsoluteDefaultPose(rig.indexOfJoint("Spine2")).trans(); + + glm::vec3 baseToTip = tipPosition - basePosition; + float baseToTipLength = glm::length(baseToTip); + glm::vec3 baseToTipNormal = baseToTip / baseToTipLength; + glm::vec3 baseToSpine2 = spine2Position - basePosition; + + _spine2SplineRatio = glm::dot(baseToSpine2, baseToTipNormal) / baseToTipLength; + + CubicHermiteSplineFunctorWithArcLength defaultSpline = computeSplineFromTipAndBase(headRigDefaultPose, hipsRigDefaultPose); + // measure the total arc length along the spline + float totalDefaultArcLength = defaultSpline.arcLength(1.0f); + float t = defaultSpline.arcLengthInverse(_spine2SplineRatio * totalDefaultArcLength); + glm::vec3 defaultSplineSpine2Translation = defaultSpline(t); + + _spine2SplineOffset = spine2Position - defaultSplineSpine2Translation; + + qCDebug(avatars_renderer) << "the avatar spline numbers are " << _spine2SplineRatio << " and " << _spine2SplineOffset; + } + +} + void Avatar::clearUnscaledEyeHeightCache() { _unscaledEyeHeightCache.set(DEFAULT_AVATAR_EYE_HEIGHT); } +void Avatar::clearSpine2SplineRatioCache() { + _spine2SplineRatio = DEFAULT_AVATAR_EYE_HEIGHT; + _spine2SplineOffset = glm::vec3(); +} + float Avatar::getUnscaledEyeHeightFromSkeleton() const { // TODO: if performance becomes a concern we can cache this value rather then computing it everytime. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index d5431ad2d2..acfcdc4ee4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "Head.h" #include "SkeletonModel.h" @@ -228,6 +229,9 @@ public: virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } + virtual glm::vec3 getSpine2SplineOffset() const { return _spine2SplineOffset; } + virtual float getSpine2SplineRatio() const { return _spine2SplineRatio; } + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void setAttachmentData(const QVector& attachmentData) override; @@ -499,7 +503,9 @@ public slots: protected: float getUnscaledEyeHeightFromSkeleton() const; void buildUnscaledEyeHeightCache(); + void buildSpine2SplineRatioCache(); void clearUnscaledEyeHeightCache(); + void clearSpine2SplineRatioCache(); virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send. QString _empty{}; virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter! @@ -552,6 +558,7 @@ protected: float getHeadHeight() const; float getPelvisFloatingHeight() const; glm::vec3 getDisplayNamePosition() const; + Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const; void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const; @@ -607,6 +614,8 @@ protected: float _displayNameAlpha { 1.0f }; ThreadSafeValueCache _unscaledEyeHeightCache { DEFAULT_AVATAR_EYE_HEIGHT }; + float _spine2SplineRatio { DEFAULT_SPINE2_SPLINE_PROPORTION }; + glm::vec3 _spine2SplineOffset; std::unordered_map _materials; std::mutex _materialsLock; diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 87da47a27a..9b0ff678e6 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -20,6 +20,7 @@ const float DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD = 0.11f; // meters const float DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD = 0.185f; // meters const float DEFAULT_AVATAR_NECK_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_NECK_TO_TOP_OF_HEAD; const float DEFAULT_AVATAR_EYE_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_EYE_TO_TOP_OF_HEAD; +const float DEFAULT_SPINE2_SPLINE_PROPORTION = 0.75f; const float DEFAULT_AVATAR_SUPPORT_BASE_LEFT = -0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_RIGHT = 0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_FRONT = -0.20f;