mirror of
https://github.com/lubosz/overte.git
synced 2025-04-12 09:42:28 +02:00
Merge pull request #10586 from ctrlaltdavid/21202
Relax hands to default position/rotation when controller tracking is lost
This commit is contained in:
commit
73a88236a0
4 changed files with 97 additions and 15 deletions
libraries/animation/src
|
@ -453,7 +453,6 @@ const AnimPoseVec& AnimInverseKinematics::evaluate(const AnimVariantMap& animVar
|
|||
|
||||
//virtual
|
||||
const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut, const AnimPoseVec& underPoses) {
|
||||
|
||||
// allows solutionSource to be overridden by an animVar
|
||||
auto solutionSource = animVars.lookup(_solutionSourceVar, (int)_solutionSource);
|
||||
|
||||
|
@ -581,6 +580,16 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
|||
}
|
||||
}
|
||||
|
||||
if (_leftHandIndex > -1) {
|
||||
_uncontrolledLeftHandPose = _skeleton->getAbsolutePose(_leftHandIndex, underPoses);
|
||||
}
|
||||
if (_rightHandIndex > -1) {
|
||||
_uncontrolledRightHandPose = _skeleton->getAbsolutePose(_rightHandIndex, underPoses);
|
||||
}
|
||||
if (_hipsIndex > -1) {
|
||||
_uncontrolledHipsPose = _skeleton->getAbsolutePose(_hipsIndex, underPoses);
|
||||
}
|
||||
|
||||
return _relativePoses;
|
||||
}
|
||||
|
||||
|
@ -722,8 +731,10 @@ void AnimInverseKinematics::initConstraints() {
|
|||
|
||||
loadDefaultPoses(_skeleton->getRelativeBindPoses());
|
||||
|
||||
// compute corresponding absolute poses
|
||||
int numJoints = (int)_defaultRelativePoses.size();
|
||||
|
||||
/* KEEP THIS CODE for future experimentation
|
||||
// compute corresponding absolute poses
|
||||
AnimPoseVec absolutePoses;
|
||||
absolutePoses.resize(numJoints);
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
|
@ -734,6 +745,7 @@ void AnimInverseKinematics::initConstraints() {
|
|||
absolutePoses[i] = absolutePoses[parentIndex] * _defaultRelativePoses[i];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
clearConstraints();
|
||||
for (int i = 0; i < numJoints; ++i) {
|
||||
|
@ -1061,12 +1073,21 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele
|
|||
} else {
|
||||
_hipsParentIndex = -1;
|
||||
}
|
||||
|
||||
_leftHandIndex = _skeleton->nameToJointIndex("LeftHand");
|
||||
_rightHandIndex = _skeleton->nameToJointIndex("RightHand");
|
||||
} else {
|
||||
clearConstraints();
|
||||
_headIndex = -1;
|
||||
_hipsIndex = -1;
|
||||
_hipsParentIndex = -1;
|
||||
_leftHandIndex = -1;
|
||||
_rightHandIndex = -1;
|
||||
}
|
||||
|
||||
_uncontrolledLeftHandPose = AnimPose();
|
||||
_uncontrolledRightHandPose = AnimPose();
|
||||
_uncontrolledHipsPose = AnimPose();
|
||||
}
|
||||
|
||||
static glm::vec3 sphericalToCartesian(float phi, float theta) {
|
||||
|
|
|
@ -56,6 +56,10 @@ public:
|
|||
void setSolutionSource(SolutionSource solutionSource) { _solutionSource = solutionSource; }
|
||||
void setSolutionSourceVar(const QString& solutionSourceVar) { _solutionSourceVar = solutionSourceVar; }
|
||||
|
||||
const AnimPose& getUncontrolledLeftHandPose() { return _uncontrolledLeftHandPose; }
|
||||
const AnimPose& getUncontrolledRightHandPose() { return _uncontrolledRightHandPose; }
|
||||
const AnimPose& getUncontrolledHipPose() { return _uncontrolledHipsPose; }
|
||||
|
||||
protected:
|
||||
void computeTargets(const AnimVariantMap& animVars, std::vector<IKTarget>& targets, const AnimPoseVec& underPoses);
|
||||
void solveWithCyclicCoordinateDescent(const AnimContext& context, const std::vector<IKTarget>& targets);
|
||||
|
@ -118,6 +122,8 @@ protected:
|
|||
int _hipsIndex { -1 };
|
||||
int _hipsParentIndex { -1 };
|
||||
int _hipsTargetIndex { -1 };
|
||||
int _leftHandIndex { -1 };
|
||||
int _rightHandIndex { -1 };
|
||||
|
||||
// _maxTargetIndex is tracked to help optimize the recalculation of absolute poses
|
||||
// during the the cyclic coordinate descent algorithm
|
||||
|
@ -127,6 +133,10 @@ protected:
|
|||
bool _previousEnableDebugIKTargets { false };
|
||||
SolutionSource _solutionSource { SolutionSource::RelaxToUnderPoses };
|
||||
QString _solutionSourceVar;
|
||||
|
||||
AnimPose _uncontrolledLeftHandPose { AnimPose() };
|
||||
AnimPose _uncontrolledRightHandPose { AnimPose() };
|
||||
AnimPose _uncontrolledHipsPose { AnimPose() };
|
||||
};
|
||||
|
||||
#endif // hifi_AnimInverseKinematics_h
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "AnimClip.h"
|
||||
#include "AnimInverseKinematics.h"
|
||||
#include "AnimSkeleton.h"
|
||||
#include "AnimUtil.h"
|
||||
#include "IKTarget.h"
|
||||
|
||||
static bool isEqual(const glm::vec3& u, const glm::vec3& v) {
|
||||
|
@ -1172,10 +1173,10 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
|
|||
// TODO: add isHipsEnabled
|
||||
bool bodySensorTrackingEnabled = params.isLeftFootEnabled || params.isRightFootEnabled;
|
||||
|
||||
const float RELAX_DURATION = 0.6f;
|
||||
|
||||
if (params.isLeftEnabled) {
|
||||
|
||||
glm::vec3 handPosition = params.leftPosition;
|
||||
|
||||
if (!bodySensorTrackingEnabled) {
|
||||
// prevent the hand IK targets from intersecting the body capsule
|
||||
glm::vec3 displacement;
|
||||
|
@ -1187,16 +1188,38 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
|
|||
_animVars.set("leftHandPosition", handPosition);
|
||||
_animVars.set("leftHandRotation", params.leftOrientation);
|
||||
_animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||
|
||||
_isLeftHandControlled = true;
|
||||
_lastLeftHandControlledPose = AnimPose(glm::vec3(1.0f), params.leftOrientation, handPosition);
|
||||
} else {
|
||||
_animVars.unset("leftHandPosition");
|
||||
_animVars.unset("leftHandRotation");
|
||||
_animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||
if (_isLeftHandControlled) {
|
||||
_leftHandRelaxDuration = RELAX_DURATION;
|
||||
_isLeftHandControlled = false;
|
||||
}
|
||||
|
||||
if (_leftHandRelaxDuration > 0) {
|
||||
// Move hand from controlled position to non-controlled position.
|
||||
_leftHandRelaxDuration = std::max(_leftHandRelaxDuration - dt, 0.0f);
|
||||
auto ikNode = getAnimInverseKinematicsNode();
|
||||
if (ikNode) {
|
||||
float alpha = 1.0f - _leftHandRelaxDuration / RELAX_DURATION;
|
||||
const AnimPose geometryToRigTransform(_geometryToRigTransform);
|
||||
AnimPose uncontrolledHandPose = geometryToRigTransform * ikNode->getUncontrolledLeftHandPose();
|
||||
AnimPose handPose;
|
||||
::blend(1, &_lastLeftHandControlledPose, &uncontrolledHandPose, alpha, &handPose);
|
||||
_animVars.set("leftHandPosition", handPose.trans());
|
||||
_animVars.set("leftHandRotation", handPose.rot());
|
||||
_animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||
}
|
||||
} else {
|
||||
_animVars.unset("leftHandPosition");
|
||||
_animVars.unset("leftHandRotation");
|
||||
_animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.isRightEnabled) {
|
||||
|
||||
glm::vec3 handPosition = params.rightPosition;
|
||||
|
||||
if (!bodySensorTrackingEnabled) {
|
||||
// prevent the hand IK targets from intersecting the body capsule
|
||||
glm::vec3 displacement;
|
||||
|
@ -1208,10 +1231,34 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
|
|||
_animVars.set("rightHandPosition", handPosition);
|
||||
_animVars.set("rightHandRotation", params.rightOrientation);
|
||||
_animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||
|
||||
_isRightHandControlled = true;
|
||||
_lastRightHandControlledPose = AnimPose(glm::vec3(1.0f), params.rightOrientation, handPosition);
|
||||
} else {
|
||||
_animVars.unset("rightHandPosition");
|
||||
_animVars.unset("rightHandRotation");
|
||||
_animVars.set("rightHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||
if (_isRightHandControlled) {
|
||||
_rightHandRelaxDuration = RELAX_DURATION;
|
||||
_isRightHandControlled = false;
|
||||
}
|
||||
|
||||
if (_rightHandRelaxDuration > 0) {
|
||||
// Move hand from controlled position to non-controlled position.
|
||||
_rightHandRelaxDuration = std::max(_rightHandRelaxDuration - dt, 0.0f);
|
||||
auto ikNode = getAnimInverseKinematicsNode();
|
||||
if (ikNode) {
|
||||
float alpha = 1.0f - _rightHandRelaxDuration / RELAX_DURATION;
|
||||
const AnimPose geometryToRigTransform(_geometryToRigTransform);
|
||||
AnimPose uncontrolledHandPose = geometryToRigTransform * ikNode->getUncontrolledRightHandPose();
|
||||
AnimPose handPose;
|
||||
::blend(1, &_lastRightHandControlledPose, &uncontrolledHandPose, alpha, &handPose);
|
||||
_animVars.set("rightHandPosition", handPose.trans());
|
||||
_animVars.set("rightHandRotation", handPose.rot());
|
||||
_animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
|
||||
}
|
||||
} else {
|
||||
_animVars.unset("rightHandPosition");
|
||||
_animVars.unset("rightHandRotation");
|
||||
_animVars.set("rightHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.isLeftFootEnabled) {
|
||||
|
@ -1233,7 +1280,6 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
|
|||
_animVars.unset("rightFootRotation");
|
||||
_animVars.set("rightFootType", (int)IKTarget::Type::RotationAndPosition);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1509,5 +1555,3 @@ void Rig::computeAvatarBoundingCapsule(
|
|||
glm::vec3 rigCenter = (geometryToRig * (0.5f * (totalExtents.maximum + totalExtents.minimum)));
|
||||
localOffsetOut = rigCenter - (geometryToRig * rootPosition);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -355,6 +355,13 @@ private:
|
|||
QMap<int, StateHandler> _stateHandlers;
|
||||
int _nextStateHandlerId { 0 };
|
||||
QMutex _stateMutex;
|
||||
|
||||
bool _isLeftHandControlled { false };
|
||||
bool _isRightHandControlled { false };
|
||||
float _leftHandRelaxDuration { 0.0f };
|
||||
float _rightHandRelaxDuration { 0.0f };
|
||||
AnimPose _lastLeftHandControlledPose;
|
||||
AnimPose _lastRightHandControlledPose;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__Rig__) */
|
||||
|
|
Loading…
Reference in a new issue