When out-of-body have your avatar face toward your HMD.

This commit is contained in:
Anthony J. Thibault 2016-09-12 16:20:13 -07:00
parent baee5180c1
commit ffb1bae1f0
3 changed files with 82 additions and 39 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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;