Smooth transition of hands from in-body to out-of-body modes.

This commit is contained in:
Anthony Thibault 2016-09-24 14:28:56 -07:00
parent 27e6c0f872
commit 10c5da5728
3 changed files with 31 additions and 7 deletions

View file

@ -164,16 +164,30 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
Rig::HandParameters handParams;
// compute interp factor between in body and out of body hand positions.
const float MIN_OUT_OF_BODY_DISTANCE = TRUNCATE_IK_CAPSULE_RADIUS - 0.1f;
const float MAX_OUT_OF_BODY_DISTANCE = TRUNCATE_IK_CAPSULE_RADIUS + 0.1f;
glm::vec3 capsuleStart = Vectors::UNIT_Y * (TRUNCATE_IK_CAPSULE_LENGTH / 2.0f);
glm::vec3 capsuleEnd = -Vectors::UNIT_Y * (TRUNCATE_IK_CAPSULE_LENGTH / 2.0f);
float outOfBodyAlpha = distanceFromCapsule(hmdPositionInRigSpace, capsuleStart, capsuleEnd, TRUNCATE_IK_CAPSULE_RADIUS);
outOfBodyAlpha = (glm::clamp(outOfBodyAlpha, MIN_OUT_OF_BODY_DISTANCE, MAX_OUT_OF_BODY_DISTANCE) - MIN_OUT_OF_BODY_DISTANCE) /
(MAX_OUT_OF_BODY_DISTANCE - MIN_OUT_OF_BODY_DISTANCE);
auto leftPose = myAvatar->getLeftHandControllerPoseInAvatarFrame();
if (leftPose.isValid()) {
handParams.isLeftEnabled = true;
handParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation();
handParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation();
// truncate hand target
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
// adjust hand position if head is out of body.
if (qApp->isHMDMode()) {
// compute the out of body hand position.
glm::vec3 offset = handParams.leftPosition - hmdPositionInRigSpace;
handParams.leftPosition = truncatedHMDPositionInRigSpace + offset;
glm::vec3 outOfBodyLeftPosition = truncatedHMDPositionInRigSpace + offset;
// interpolate between in body and out of body hand position.
handParams.leftPosition = lerp(handParams.leftPosition, outOfBodyLeftPosition, outOfBodyAlpha);
}
} else {
handParams.isLeftEnabled = false;
@ -185,10 +199,15 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
handParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation();
handParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation();
// truncate hand target
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
// adjust hand position if head is out of body.
if (qApp->isHMDMode()) {
// compute the out of body hand position.
glm::vec3 offset = handParams.rightPosition - hmdPositionInRigSpace;
handParams.rightPosition = truncatedHMDPositionInRigSpace + offset;
glm::vec3 outOfBodyRightPosition = truncatedHMDPositionInRigSpace + offset;
// interpolate between in body and out of body hand position.
handParams.rightPosition = lerp(handParams.rightPosition, outOfBodyRightPosition, outOfBodyAlpha);
}
} else {
handParams.isRightEnabled = false;

View file

@ -596,6 +596,10 @@ float distanceFromLineSegment(const glm::vec3& point, const glm::vec3& segmentSt
return glm::length(point - nearestPointOnLineSegment(point, segmentStart, segmentEnd));
}
float distanceFromCapsule(const glm::vec3& point, const glm::vec3& segmentStart, const glm::vec3& segmentEnd, float capsuleRadius) {
return distanceFromLineSegment(point, segmentStart, segmentEnd) - capsuleRadius;
}
bool pointIsInsideCapsule(const glm::vec3& point, const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius) {
return distanceFromLineSegment(point, capsuleStart, capsuleEnd) < capsuleRadius;
}
@ -604,7 +608,7 @@ glm::vec3 projectPointOntoCapsule(const glm::vec3& point, const glm::vec3& capsu
glm::vec3 nearestPoint = nearestPointOnLineSegment(point, capsuleStart, capsuleEnd);
glm::vec3 d = point - nearestPoint;
float dLen = glm::length(d);
if (dLen > EPSILON) {
if (dLen < EPSILON) {
return nearestPoint; // TODO: maybe we should pick a point actually on the surface...
} else {
return nearestPoint + d * (capsuleRadius / dLen);

View file

@ -162,6 +162,7 @@ private:
glm::vec3 nearestPointOnLineSegment(const glm::vec3& point, const glm::vec3& segmentStart, const glm::vec3& segmentEnd);
float distanceFromLineSegment(const glm::vec3& point, const glm::vec3& segmentStart, const glm::vec3& segmentEnd);
float distanceFromCapsule(const glm::vec3& point, const glm::vec3& segmentStart, const glm::vec3& segmentEnd, float capsuleRadius);
bool pointIsInsideCapsule(const glm::vec3& point, const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius);
glm::vec3 projectPointOntoCapsule(const glm::vec3& point, const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius);