mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 18:10:37 +02:00
Smooth transition of hands from in-body to out-of-body modes.
This commit is contained in:
parent
27e6c0f872
commit
10c5da5728
3 changed files with 31 additions and 7 deletions
|
@ -164,16 +164,30 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
|
||||||
Rig::HandParameters handParams;
|
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();
|
auto leftPose = myAvatar->getLeftHandControllerPoseInAvatarFrame();
|
||||||
if (leftPose.isValid()) {
|
if (leftPose.isValid()) {
|
||||||
handParams.isLeftEnabled = true;
|
handParams.isLeftEnabled = true;
|
||||||
handParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation();
|
handParams.leftPosition = Quaternions::Y_180 * leftPose.getTranslation();
|
||||||
handParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation();
|
handParams.leftOrientation = Quaternions::Y_180 * leftPose.getRotation();
|
||||||
|
|
||||||
// truncate hand target
|
// adjust hand position if head is out of body.
|
||||||
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
if (qApp->isHMDMode()) {
|
||||||
|
|
||||||
|
// compute the out of body hand position.
|
||||||
glm::vec3 offset = handParams.leftPosition - hmdPositionInRigSpace;
|
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 {
|
} else {
|
||||||
handParams.isLeftEnabled = false;
|
handParams.isLeftEnabled = false;
|
||||||
|
@ -185,10 +199,15 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
handParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation();
|
handParams.rightPosition = Quaternions::Y_180 * rightPose.getTranslation();
|
||||||
handParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation();
|
handParams.rightOrientation = Quaternions::Y_180 * rightPose.getRotation();
|
||||||
|
|
||||||
// truncate hand target
|
// adjust hand position if head is out of body.
|
||||||
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
if (qApp->isHMDMode()) {
|
||||||
|
|
||||||
|
// compute the out of body hand position.
|
||||||
glm::vec3 offset = handParams.rightPosition - hmdPositionInRigSpace;
|
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 {
|
} else {
|
||||||
handParams.isRightEnabled = false;
|
handParams.isRightEnabled = false;
|
||||||
|
|
|
@ -596,6 +596,10 @@ float distanceFromLineSegment(const glm::vec3& point, const glm::vec3& segmentSt
|
||||||
return glm::length(point - nearestPointOnLineSegment(point, segmentStart, segmentEnd));
|
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) {
|
bool pointIsInsideCapsule(const glm::vec3& point, const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius) {
|
||||||
return distanceFromLineSegment(point, capsuleStart, capsuleEnd) < 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 nearestPoint = nearestPointOnLineSegment(point, capsuleStart, capsuleEnd);
|
||||||
glm::vec3 d = point - nearestPoint;
|
glm::vec3 d = point - nearestPoint;
|
||||||
float dLen = glm::length(d);
|
float dLen = glm::length(d);
|
||||||
if (dLen > EPSILON) {
|
if (dLen < EPSILON) {
|
||||||
return nearestPoint; // TODO: maybe we should pick a point actually on the surface...
|
return nearestPoint; // TODO: maybe we should pick a point actually on the surface...
|
||||||
} else {
|
} else {
|
||||||
return nearestPoint + d * (capsuleRadius / dLen);
|
return nearestPoint + d * (capsuleRadius / dLen);
|
||||||
|
|
|
@ -162,6 +162,7 @@ private:
|
||||||
|
|
||||||
glm::vec3 nearestPointOnLineSegment(const glm::vec3& point, const glm::vec3& segmentStart, const glm::vec3& segmentEnd);
|
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 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);
|
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);
|
glm::vec3 projectPointOntoCapsule(const glm::vec3& point, const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue