mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 20:44:14 +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;
|
||||
|
||||
// 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue