From 460582239a804a2a4dc069e30e7ebf5a50217537 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 29 Feb 2016 18:02:50 -0800 Subject: [PATCH] Avatar eye look at fixes for HMDs There were three things that were causing issues with eye look at vectors while wearing an HMD. 1) The matrix returned by AvatarUpdate->getHeadPose() was in the wrong space, it should be in avatar space. it was actually returning a matrix in sensor/room space. 2) The lookAtPosition was incorrect while wearing an HMD and with no avatars to look at. 3) The eye rotation limits in Rig::updateEyeJoint were relative to the model's zero orientation, NOT relative to the head. this was causing the eyes to hit limits when the avatar head turned. --- interface/src/Application.cpp | 4 ++-- interface/src/avatar/AvatarUpdate.cpp | 9 ++++++++- libraries/animation/src/Rig.cpp | 13 ++++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 21377fa945..586e7ee8e5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2946,9 +2946,9 @@ void Application::updateMyAvatarLookAtPosition() { } else { // I am not looking at anyone else, so just look forward if (isHMD) { - glm::mat4 headPose = _avatarUpdate->getHeadPose() ; + glm::mat4 headPose = _avatarUpdate->getHeadPose(); glm::quat headRotation = glm::quat_cast(headPose); - lookAtSpot = _myCamera.getPosition() + + lookAtSpot = myAvatar->getPosition() + myAvatar->getOrientation() * (headRotation * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + diff --git a/interface/src/avatar/AvatarUpdate.cpp b/interface/src/avatar/AvatarUpdate.cpp index 68a13ba227..4881e3eaec 100644 --- a/interface/src/avatar/AvatarUpdate.cpp +++ b/interface/src/avatar/AvatarUpdate.cpp @@ -31,7 +31,14 @@ void AvatarUpdate::synchronousProcess() { // Keep our own updated value, so that our asynchronous code can consult it. _isHMDMode = qApp->isHMDMode(); auto frameCount = qApp->getFrameCount(); - _headPose = qApp->getActiveDisplayPlugin()->getHeadPose(frameCount); + + QSharedPointer manager = DependencyManager::get(); + MyAvatar* myAvatar = manager->getMyAvatar(); + assert(myAvatar); + + // transform the head pose from the displayPlugin into avatar coordinates. + glm::mat4 invAvatarMat = glm::inverse(createMatFromQuatAndPos(myAvatar->getOrientation(), myAvatar->getPosition())); + _headPose = invAvatarMat * (myAvatar->getSensorToWorldMatrix() * qApp->getActiveDisplayPlugin()->getHeadPose(frameCount)); if (!isThreaded()) { process(); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 3952dc5b40..7bab4dfc1d 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1067,14 +1067,21 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm glm::mat4 rigToWorld = createMatFromQuatAndPos(modelRotation, modelTranslation); glm::mat4 worldToRig = glm::inverse(rigToWorld); glm::vec3 zAxis = glm::normalize(_internalPoseSet._absolutePoses[index].trans - transformPoint(worldToRig, lookAtSpot)); - glm::quat q = rotationBetween(IDENTITY_FRONT, zAxis); + + glm::quat desiredQuat = rotationBetween(IDENTITY_FRONT, zAxis); + glm::quat headQuat; + int headIndex = _animSkeleton->nameToJointIndex("Head"); + if (headIndex >= 0) { + headQuat = _internalPoseSet._absolutePoses[headIndex].rot; + } + glm::quat deltaQuat = desiredQuat * glm::inverse(headQuat); // limit rotation const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; - q = glm::angleAxis(glm::clamp(glm::angle(q), -MAX_ANGLE, MAX_ANGLE), glm::axis(q)); + deltaQuat = glm::angleAxis(glm::clamp(glm::angle(deltaQuat), -MAX_ANGLE, MAX_ANGLE), glm::axis(deltaQuat)); // directly set absolutePose rotation - _internalPoseSet._absolutePoses[index].rot = q; + _internalPoseSet._absolutePoses[index].rot = deltaQuat * headQuat; } }