Smoothly ease hands from uncontrolled to controlled positions

This commit is contained in:
David Rowe 2017-06-12 17:14:13 +12:00
parent 92fe8145be
commit 3e126c0517
2 changed files with 54 additions and 9 deletions

View file

@ -1164,9 +1164,32 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
bool bodySensorTrackingEnabled = params.isLeftFootEnabled || params.isRightFootEnabled;
const float RELAX_DURATION = 0.6f;
const float CONTROL_DURATION = 0.4f;
if (params.isLeftEnabled) {
if (!_isLeftHandControlled) {
_leftHandControlDuration = CONTROL_DURATION;
_isLeftHandControlled = true;
}
glm::vec3 handPosition = params.leftPosition;
glm::quat handRotation = params.leftOrientation;
if (_leftHandControlDuration > 0.0f) {
// Move hand from non-controlled position to controlled position.
_leftHandControlDuration = std::max(_leftHandControlDuration - dt, 0.0f);
auto ikNode = getAnimInverseKinematicsNode();
if (ikNode) {
AnimPose handPose(Vectors::ONE, handRotation, handPosition);
float alpha = 1.0f - _leftHandControlDuration / CONTROL_DURATION;
const AnimPose geometryToRigTransform(_geometryToRigTransform);
AnimPose uncontrolledHandPose = geometryToRigTransform * ikNode->getUncontrolledLeftHandPose();
::blend(1, &uncontrolledHandPose, &handPose, alpha, &handPose);
handPosition = handPose.trans();
handRotation = handPose.rot();
}
}
if (!bodySensorTrackingEnabled) {
// prevent the hand IK targets from intersecting the body capsule
glm::vec3 displacement;
@ -1176,18 +1199,17 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
}
_animVars.set("leftHandPosition", handPosition);
_animVars.set("leftHandRotation", params.leftOrientation);
_animVars.set("leftHandRotation", handRotation);
_animVars.set("leftHandType", (int)IKTarget::Type::RotationAndPosition);
_isLeftHandControlled = true;
_lastLeftHandControlledPose = AnimPose(glm::vec3(1.0f), params.leftOrientation, handPosition);
_lastLeftHandControlledPose = AnimPose(Vectors::ONE, handRotation, handPosition);
} else {
if (_isLeftHandControlled) {
_leftHandRelaxDuration = RELAX_DURATION;
_isLeftHandControlled = false;
}
if (_leftHandRelaxDuration > 0) {
if (_leftHandRelaxDuration > 0.0f) {
// Move hand from controlled position to non-controlled position.
_leftHandRelaxDuration = std::max(_leftHandRelaxDuration - dt, 0.0f);
auto ikNode = getAnimInverseKinematicsNode();
@ -1209,7 +1231,29 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
}
if (params.isRightEnabled) {
if (!_isRightHandControlled) {
_rightHandControlDuration = CONTROL_DURATION;
_isRightHandControlled = true;
}
glm::vec3 handPosition = params.rightPosition;
glm::quat handRotation = params.rightOrientation;
if (_rightHandControlDuration > 0.0f) {
// Move hand from non-controlled position to controlled position.
_rightHandControlDuration = std::max(_rightHandControlDuration - dt, 0.0f);
auto ikNode = getAnimInverseKinematicsNode();
if (ikNode) {
AnimPose handPose(Vectors::ONE, handRotation, handPosition);
float alpha = 1.0f - _rightHandControlDuration / CONTROL_DURATION;
const AnimPose geometryToRigTransform(_geometryToRigTransform);
AnimPose uncontrolledHandPose = geometryToRigTransform * ikNode->getUncontrolledRightHandPose();
::blend(1, &uncontrolledHandPose, &handPose, alpha, &handPose);
handPosition = handPose.trans();
handRotation = handPose.rot();
}
}
if (!bodySensorTrackingEnabled) {
// prevent the hand IK targets from intersecting the body capsule
glm::vec3 displacement;
@ -1219,18 +1263,17 @@ void Rig::updateFromHandAndFeetParameters(const HandAndFeetParameters& params, f
}
_animVars.set("rightHandPosition", handPosition);
_animVars.set("rightHandRotation", params.rightOrientation);
_animVars.set("rightHandRotation", handRotation);
_animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition);
_isRightHandControlled = true;
_lastRightHandControlledPose = AnimPose(glm::vec3(1.0f), params.rightOrientation, handPosition);
_lastRightHandControlledPose = AnimPose(Vectors::ONE, handRotation, handPosition);
} else {
if (_isRightHandControlled) {
_rightHandRelaxDuration = RELAX_DURATION;
_isRightHandControlled = false;
}
if (_rightHandRelaxDuration > 0) {
if (_rightHandRelaxDuration > 0.0f) {
// Move hand from controlled position to non-controlled position.
_rightHandRelaxDuration = std::max(_rightHandRelaxDuration - dt, 0.0f);
auto ikNode = getAnimInverseKinematicsNode();

View file

@ -354,7 +354,9 @@ private:
bool _isLeftHandControlled { false };
bool _isRightHandControlled { false };
float _leftHandRelaxDuration { 0.0f };
float _leftHandControlDuration{ 0.0f };
float _rightHandControlDuration{ 0.0f };
float _leftHandRelaxDuration{ 0.0f };
float _rightHandRelaxDuration { 0.0f };
AnimPose _lastLeftHandControlledPose;
AnimPose _lastRightHandControlledPose;