mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 16:36:54 +02:00
When out-of-body have your avatar face toward your HMD.
This commit is contained in:
parent
baee5180c1
commit
ffb1bae1f0
3 changed files with 82 additions and 39 deletions
|
@ -86,9 +86,9 @@ const float MyAvatar::ZOOM_DEFAULT = 1.5f;
|
||||||
extern bool OUTOFBODY_HACK_ENABLE_DEBUG_DRAW_IK_TARGETS;
|
extern bool OUTOFBODY_HACK_ENABLE_DEBUG_DRAW_IK_TARGETS;
|
||||||
|
|
||||||
// OUTOFBODY_HACK defined in SkeletonModel.cpp
|
// OUTOFBODY_HACK defined in SkeletonModel.cpp
|
||||||
extern const glm::vec3 TRUNCATE_IK_CAPSULE_POSITION;
|
extern glm::vec3 TRUNCATE_IK_CAPSULE_POSITION;
|
||||||
extern const float TRUNCATE_IK_CAPSULE_LENGTH;
|
extern float TRUNCATE_IK_CAPSULE_LENGTH;
|
||||||
extern const float TRUNCATE_IK_CAPSULE_RADIUS;
|
extern float TRUNCATE_IK_CAPSULE_RADIUS;
|
||||||
|
|
||||||
MyAvatar::MyAvatar(RigPointer rig) :
|
MyAvatar::MyAvatar(RigPointer rig) :
|
||||||
Avatar(rig),
|
Avatar(rig),
|
||||||
|
@ -2159,31 +2159,65 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
||||||
_desiredBodyMatrix = desiredBodyMatrix;
|
_desiredBodyMatrix = desiredBodyMatrix;
|
||||||
|
|
||||||
if (myAvatar.getHMDLeanRecenterEnabled()) {
|
if (myAvatar.getHMDLeanRecenterEnabled()) {
|
||||||
updateRotationActivation(myAvatar, desiredBodyMatrix, currentBodyMatrix);
|
|
||||||
updateHorizontalActivation(myAvatar, desiredBodyMatrix, currentBodyMatrix);
|
|
||||||
updateVerticalActivation(myAvatar, desiredBodyMatrix, currentBodyMatrix);
|
|
||||||
|
|
||||||
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix;
|
if (_isOutOfBody) {
|
||||||
glm::mat4 currentWorldMatrix = createMatFromQuatAndPos(myAvatar.getOrientation(), myAvatar.getPosition());
|
|
||||||
|
|
||||||
AnimPose followWorldPose(currentWorldMatrix);
|
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix;
|
||||||
if (isActive(Rotation)) {
|
glm::mat4 currentWorldMatrix = createMatFromQuatAndPos(myAvatar.getOrientation(), myAvatar.getPosition());
|
||||||
followWorldPose.rot = glmExtractRotation(desiredWorldMatrix);
|
AnimPose followWorldPose(currentWorldMatrix);
|
||||||
}
|
|
||||||
if (isActive(Horizontal)) {
|
// OUTOFBODY_HACK, only takes horizontal movement into account.
|
||||||
|
|
||||||
|
// horizontal follow
|
||||||
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
|
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
|
||||||
followWorldPose.trans.x = desiredTranslation.x;
|
followWorldPose.trans.x = desiredTranslation.x;
|
||||||
followWorldPose.trans.z = desiredTranslation.z;
|
followWorldPose.trans.z = desiredTranslation.z;
|
||||||
}
|
|
||||||
if (isActive(Vertical)) {
|
|
||||||
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
|
|
||||||
followWorldPose.trans.y = desiredTranslation.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isActive()) {
|
// rotation follow
|
||||||
|
// face the HMD
|
||||||
|
glm::vec3 hmdWorldPosition = extractTranslation(myAvatar.getSensorToWorldMatrix() * myAvatar.getHMDSensorMatrix());
|
||||||
|
glm::vec3 facing = myAvatar.getPosition() - hmdWorldPosition;
|
||||||
|
facing.y = 0.0f;
|
||||||
|
if (glm::length(facing) > EPSILON) {
|
||||||
|
// turn to face the hmd
|
||||||
|
followWorldPose.rot = glm::angleAxis(atan2(facing.x, facing.z), Vectors::UNIT_Y);
|
||||||
|
} else {
|
||||||
|
followWorldPose.rot = glmExtractRotation(desiredWorldMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
myAvatar.getCharacterController()->setFollowParameters(followWorldPose);
|
myAvatar.getCharacterController()->setFollowParameters(followWorldPose);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
myAvatar.getCharacterController()->disableFollow();
|
updateRotationActivation(myAvatar, desiredBodyMatrix, currentBodyMatrix);
|
||||||
|
updateHorizontalActivation(myAvatar, desiredBodyMatrix, currentBodyMatrix);
|
||||||
|
updateVerticalActivation(myAvatar, desiredBodyMatrix, currentBodyMatrix);
|
||||||
|
|
||||||
|
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix;
|
||||||
|
glm::mat4 currentWorldMatrix = createMatFromQuatAndPos(myAvatar.getOrientation(), myAvatar.getPosition());
|
||||||
|
|
||||||
|
AnimPose followWorldPose(currentWorldMatrix);
|
||||||
|
if (isActive(Rotation)) {
|
||||||
|
followWorldPose.rot = glmExtractRotation(desiredWorldMatrix);
|
||||||
|
}
|
||||||
|
if (isActive(Horizontal)) {
|
||||||
|
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
|
||||||
|
followWorldPose.trans.x = desiredTranslation.x;
|
||||||
|
followWorldPose.trans.z = desiredTranslation.z;
|
||||||
|
}
|
||||||
|
if (isActive(Vertical)) {
|
||||||
|
glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix);
|
||||||
|
followWorldPose.trans.y = desiredTranslation.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActive()) {
|
||||||
|
myAvatar.getCharacterController()->setFollowParameters(followWorldPose);
|
||||||
|
} else {
|
||||||
|
myAvatar.getCharacterController()->disableFollow();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 currentWorldMatrixY180 = createMatFromQuatAndPos(myAvatar.getOrientation() * Quaternions::Y_180, myAvatar.getPosition());
|
||||||
|
_prevInBodyHMDMatInAvatarSpace = _inBodyHMDMatInAvatarSpace;
|
||||||
|
_inBodyHMDMatInAvatarSpace = glm::inverse(currentWorldMatrixY180) * myAvatar.getSensorToWorldMatrix() * myAvatar.getHMDSensorMatrix();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
deactivate();
|
deactivate();
|
||||||
|
|
|
@ -279,6 +279,9 @@ public:
|
||||||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
|
||||||
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
|
||||||
|
|
||||||
|
bool isOutOfBody() const { return _follow._isOutOfBody; }
|
||||||
|
glm::mat4 getInBodyHMDMatInAvatarSpace() const { return _follow._prevInBodyHMDMatInAvatarSpace; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void increaseSize();
|
void increaseSize();
|
||||||
void decreaseSize();
|
void decreaseSize();
|
||||||
|
@ -315,8 +318,6 @@ public slots:
|
||||||
glm::vec3 getPositionForAudio();
|
glm::vec3 getPositionForAudio();
|
||||||
glm::quat getOrientationForAudio();
|
glm::quat getOrientationForAudio();
|
||||||
|
|
||||||
bool isOutOfBody() const { return _follow._isOutOfBody; }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void audioListenerModeChanged();
|
void audioListenerModeChanged();
|
||||||
void transformChanged();
|
void transformChanged();
|
||||||
|
@ -449,6 +450,8 @@ private:
|
||||||
glm::mat4 _desiredBodyMatrix;
|
glm::mat4 _desiredBodyMatrix;
|
||||||
uint8_t _activeBits { 0 };
|
uint8_t _activeBits { 0 };
|
||||||
bool _isOutOfBody { false };
|
bool _isOutOfBody { false };
|
||||||
|
glm::mat4 _prevInBodyHMDMatInAvatarSpace;
|
||||||
|
glm::mat4 _inBodyHMDMatInAvatarSpace;
|
||||||
|
|
||||||
void deactivate();
|
void deactivate();
|
||||||
void deactivate(FollowType type);
|
void deactivate(FollowType type);
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "AnimDebugDraw.h"
|
#include "AnimDebugDraw.h"
|
||||||
|
|
||||||
const glm::vec3 TRUNCATE_IK_CAPSULE_POSITION(0.0f, 0.0f, 0.0f);
|
glm::vec3 TRUNCATE_IK_CAPSULE_POSITION(0.0f, 0.0f, 0.0f);
|
||||||
const float TRUNCATE_IK_CAPSULE_LENGTH = 1000.0f;
|
float TRUNCATE_IK_CAPSULE_LENGTH = 1000.0f;
|
||||||
const float TRUNCATE_IK_CAPSULE_RADIUS = 0.5f;
|
float TRUNCATE_IK_CAPSULE_RADIUS = 0.5f;
|
||||||
|
|
||||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
||||||
Model(rig, parent),
|
Model(rig, parent),
|
||||||
|
@ -110,8 +110,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
|
||||||
Rig::HeadParameters headParams;
|
Rig::HeadParameters headParams;
|
||||||
|
|
||||||
glm::vec3 hmdPositionInRigSpace;
|
glm::mat4 desiredHMDMat; // rig space
|
||||||
glm::vec3 truncatedHMDPositionInRigSpace;
|
glm::mat4 actualHMDMat; // rig space
|
||||||
|
|
||||||
if (qApp->isHMDMode()) {
|
if (qApp->isHMDMode()) {
|
||||||
headParams.isInHMD = true;
|
headParams.isInHMD = true;
|
||||||
|
@ -120,20 +120,20 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||||
glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation());
|
glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation());
|
||||||
glm::mat4 worldToRig = glm::inverse(rigToWorld);
|
glm::mat4 worldToRig = glm::inverse(rigToWorld);
|
||||||
glm::mat4 rigHMDMat = worldToRig * worldHMDMat;
|
desiredHMDMat = worldToRig * worldHMDMat;
|
||||||
|
|
||||||
hmdPositionInRigSpace = extractTranslation(rigHMDMat);
|
|
||||||
|
|
||||||
// truncate head IK target if it's out of body
|
|
||||||
if (myAvatar->isOutOfBody()) {
|
if (myAvatar->isOutOfBody()) {
|
||||||
truncatedHMDPositionInRigSpace = projectPointOntoCapsule(hmdPositionInRigSpace, TRUNCATE_IK_CAPSULE_POSITION,
|
// use the last valid in-body hmd matrix for the head yaw.
|
||||||
TRUNCATE_IK_CAPSULE_LENGTH, TRUNCATE_IK_CAPSULE_RADIUS);
|
glm::mat4 hmdYaw = cancelOutRollAndPitch(myAvatar->getInBodyHMDMatInAvatarSpace());
|
||||||
|
glm::mat4 hmdPitchAndRoll = glm::inverse(cancelOutRollAndPitch(desiredHMDMat)) * desiredHMDMat;
|
||||||
|
actualHMDMat = hmdYaw * hmdPitchAndRoll;
|
||||||
} else {
|
} else {
|
||||||
truncatedHMDPositionInRigSpace = hmdPositionInRigSpace;
|
actualHMDMat = desiredHMDMat;
|
||||||
}
|
}
|
||||||
|
|
||||||
headParams.rigHeadPosition = truncatedHMDPositionInRigSpace;
|
headParams.rigHeadPosition = extractTranslation(actualHMDMat);
|
||||||
headParams.rigHeadOrientation = extractRotation(rigHMDMat);
|
headParams.rigHeadOrientation = extractRotation(actualHMDMat);
|
||||||
headParams.worldHeadOrientation = extractRotation(worldHMDMat);
|
headParams.worldHeadOrientation = extractRotation(worldHMDMat);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -159,8 +159,11 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
|
||||||
// truncate hand target
|
// truncate hand target
|
||||||
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
||||||
glm::vec3 offset = handParams.leftPosition - hmdPositionInRigSpace;
|
glm::mat4 handMat = createMatFromQuatAndPos(handParams.leftOrientation, handParams.leftPosition);
|
||||||
handParams.leftPosition = truncatedHMDPositionInRigSpace + offset;
|
glm::mat4 offset = glm::inverse(desiredHMDMat) * handMat;
|
||||||
|
handMat = actualHMDMat * offset;
|
||||||
|
handParams.leftPosition = extractTranslation(handMat);
|
||||||
|
handParams.leftOrientation = glmExtractRotation(handMat);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handParams.isLeftEnabled = false;
|
handParams.isLeftEnabled = false;
|
||||||
|
@ -174,8 +177,11 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
|
|
||||||
// truncate hand target
|
// truncate hand target
|
||||||
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
||||||
glm::vec3 offset = handParams.rightPosition - hmdPositionInRigSpace;
|
glm::mat4 handMat = createMatFromQuatAndPos(handParams.rightOrientation, handParams.rightPosition);
|
||||||
handParams.rightPosition = truncatedHMDPositionInRigSpace + offset;
|
glm::mat4 offset = glm::inverse(desiredHMDMat) * handMat;
|
||||||
|
handMat = actualHMDMat * offset;
|
||||||
|
handParams.rightPosition = extractTranslation(handMat);
|
||||||
|
handParams.rightOrientation = glmExtractRotation(handMat);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handParams.isRightEnabled = false;
|
handParams.isRightEnabled = false;
|
||||||
|
|
Loading…
Reference in a new issue