mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +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;
|
||||
|
||||
// OUTOFBODY_HACK defined in SkeletonModel.cpp
|
||||
extern const glm::vec3 TRUNCATE_IK_CAPSULE_POSITION;
|
||||
extern const float TRUNCATE_IK_CAPSULE_LENGTH;
|
||||
extern const float TRUNCATE_IK_CAPSULE_RADIUS;
|
||||
extern glm::vec3 TRUNCATE_IK_CAPSULE_POSITION;
|
||||
extern float TRUNCATE_IK_CAPSULE_LENGTH;
|
||||
extern float TRUNCATE_IK_CAPSULE_RADIUS;
|
||||
|
||||
MyAvatar::MyAvatar(RigPointer rig) :
|
||||
Avatar(rig),
|
||||
|
@ -2159,31 +2159,65 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
|
|||
_desiredBodyMatrix = desiredBodyMatrix;
|
||||
|
||||
if (myAvatar.getHMDLeanRecenterEnabled()) {
|
||||
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());
|
||||
if (_isOutOfBody) {
|
||||
|
||||
AnimPose followWorldPose(currentWorldMatrix);
|
||||
if (isActive(Rotation)) {
|
||||
followWorldPose.rot = glmExtractRotation(desiredWorldMatrix);
|
||||
}
|
||||
if (isActive(Horizontal)) {
|
||||
glm::mat4 desiredWorldMatrix = myAvatar.getSensorToWorldMatrix() * _desiredBodyMatrix;
|
||||
glm::mat4 currentWorldMatrix = createMatFromQuatAndPos(myAvatar.getOrientation(), myAvatar.getPosition());
|
||||
AnimPose followWorldPose(currentWorldMatrix);
|
||||
|
||||
// OUTOFBODY_HACK, only takes horizontal movement into account.
|
||||
|
||||
// horizontal follow
|
||||
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()) {
|
||||
// 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);
|
||||
|
||||
} 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 {
|
||||
deactivate();
|
||||
|
|
|
@ -279,6 +279,9 @@ public:
|
|||
virtual glm::quat getAbsoluteJointRotationInObjectFrame(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:
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
|
@ -315,8 +318,6 @@ public slots:
|
|||
glm::vec3 getPositionForAudio();
|
||||
glm::quat getOrientationForAudio();
|
||||
|
||||
bool isOutOfBody() const { return _follow._isOutOfBody; }
|
||||
|
||||
signals:
|
||||
void audioListenerModeChanged();
|
||||
void transformChanged();
|
||||
|
@ -449,6 +450,8 @@ private:
|
|||
glm::mat4 _desiredBodyMatrix;
|
||||
uint8_t _activeBits { 0 };
|
||||
bool _isOutOfBody { false };
|
||||
glm::mat4 _prevInBodyHMDMatInAvatarSpace;
|
||||
glm::mat4 _inBodyHMDMatInAvatarSpace;
|
||||
|
||||
void deactivate();
|
||||
void deactivate(FollowType type);
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
#include "InterfaceLogging.h"
|
||||
#include "AnimDebugDraw.h"
|
||||
|
||||
const glm::vec3 TRUNCATE_IK_CAPSULE_POSITION(0.0f, 0.0f, 0.0f);
|
||||
const float TRUNCATE_IK_CAPSULE_LENGTH = 1000.0f;
|
||||
const float TRUNCATE_IK_CAPSULE_RADIUS = 0.5f;
|
||||
glm::vec3 TRUNCATE_IK_CAPSULE_POSITION(0.0f, 0.0f, 0.0f);
|
||||
float TRUNCATE_IK_CAPSULE_LENGTH = 1000.0f;
|
||||
float TRUNCATE_IK_CAPSULE_RADIUS = 0.5f;
|
||||
|
||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer rig) :
|
||||
Model(rig, parent),
|
||||
|
@ -110,8 +110,8 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
Rig::HeadParameters headParams;
|
||||
|
||||
glm::vec3 hmdPositionInRigSpace;
|
||||
glm::vec3 truncatedHMDPositionInRigSpace;
|
||||
glm::mat4 desiredHMDMat; // rig space
|
||||
glm::mat4 actualHMDMat; // rig space
|
||||
|
||||
if (qApp->isHMDMode()) {
|
||||
headParams.isInHMD = true;
|
||||
|
@ -120,20 +120,20 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix();
|
||||
glm::mat4 rigToWorld = createMatFromQuatAndPos(getRotation(), getTranslation());
|
||||
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()) {
|
||||
truncatedHMDPositionInRigSpace = projectPointOntoCapsule(hmdPositionInRigSpace, TRUNCATE_IK_CAPSULE_POSITION,
|
||||
TRUNCATE_IK_CAPSULE_LENGTH, TRUNCATE_IK_CAPSULE_RADIUS);
|
||||
// use the last valid in-body hmd matrix for the head yaw.
|
||||
glm::mat4 hmdYaw = cancelOutRollAndPitch(myAvatar->getInBodyHMDMatInAvatarSpace());
|
||||
glm::mat4 hmdPitchAndRoll = glm::inverse(cancelOutRollAndPitch(desiredHMDMat)) * desiredHMDMat;
|
||||
actualHMDMat = hmdYaw * hmdPitchAndRoll;
|
||||
} else {
|
||||
truncatedHMDPositionInRigSpace = hmdPositionInRigSpace;
|
||||
actualHMDMat = desiredHMDMat;
|
||||
}
|
||||
|
||||
headParams.rigHeadPosition = truncatedHMDPositionInRigSpace;
|
||||
headParams.rigHeadOrientation = extractRotation(rigHMDMat);
|
||||
headParams.rigHeadPosition = extractTranslation(actualHMDMat);
|
||||
headParams.rigHeadOrientation = extractRotation(actualHMDMat);
|
||||
headParams.worldHeadOrientation = extractRotation(worldHMDMat);
|
||||
|
||||
} else {
|
||||
|
@ -159,8 +159,11 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
// truncate hand target
|
||||
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
||||
glm::vec3 offset = handParams.leftPosition - hmdPositionInRigSpace;
|
||||
handParams.leftPosition = truncatedHMDPositionInRigSpace + offset;
|
||||
glm::mat4 handMat = createMatFromQuatAndPos(handParams.leftOrientation, handParams.leftPosition);
|
||||
glm::mat4 offset = glm::inverse(desiredHMDMat) * handMat;
|
||||
handMat = actualHMDMat * offset;
|
||||
handParams.leftPosition = extractTranslation(handMat);
|
||||
handParams.leftOrientation = glmExtractRotation(handMat);
|
||||
}
|
||||
} else {
|
||||
handParams.isLeftEnabled = false;
|
||||
|
@ -174,8 +177,11 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|||
|
||||
// truncate hand target
|
||||
if (myAvatar->isOutOfBody() && qApp->isHMDMode()) {
|
||||
glm::vec3 offset = handParams.rightPosition - hmdPositionInRigSpace;
|
||||
handParams.rightPosition = truncatedHMDPositionInRigSpace + offset;
|
||||
glm::mat4 handMat = createMatFromQuatAndPos(handParams.rightOrientation, handParams.rightPosition);
|
||||
glm::mat4 offset = glm::inverse(desiredHMDMat) * handMat;
|
||||
handMat = actualHMDMat * offset;
|
||||
handParams.rightPosition = extractTranslation(handMat);
|
||||
handParams.rightOrientation = glmExtractRotation(handMat);
|
||||
}
|
||||
} else {
|
||||
handParams.isRightEnabled = false;
|
||||
|
|
Loading…
Reference in a new issue