From d8a32c8329208c1ad9d689caf1766068578d16c1 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Sun, 24 Apr 2016 17:59:51 -0700 Subject: [PATCH 1/3] Avatar eye gaze fix for HMDs When no avatars are chosen for more detailed eye gaze tracking the eyes should look straight ahead. Before this fix, if you were in room scale or not aligned with the camera sensor your gaze could drift to the left or to the right of your head's forward direction. Now it should follow your head more closely. --- interface/src/Application.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4071043c87..fcf1425287 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3104,10 +3104,8 @@ void Application::updateMyAvatarLookAtPosition() { } else { // I am not looking at anyone else, so just look forward if (isHMD) { - glm::mat4 headPose = myAvatar->getHMDSensorMatrix(); - glm::quat headRotation = glm::quat_cast(headPose); - lookAtSpot = myAvatar->getPosition() + - myAvatar->getOrientation() * (headRotation * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); + glm::mat4 worldHMDMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + lookAtSpot = transformPoint(worldHMDMat, glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); From 0da3fb8eeea646fa55bf674837f8423169dbbc58 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Sun, 24 Apr 2016 18:50:14 -0700 Subject: [PATCH 2/3] Eye contact improvements * After eyes change targets there is now a minimum 1/3rd second delay before they will again. * Changing gaze from eye to mouth is less likely then switching between eyes. --- interface/src/avatar/MyAvatar.cpp | 46 ++++++++++++++++++++----------- interface/src/avatar/MyAvatar.h | 3 ++ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b1107896a9..f61f64412c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -317,6 +317,36 @@ void MyAvatar::update(float deltaTime) { } currentEnergy = max(0.0f, min(currentEnergy,1.0f)); emit energyChanged(currentEnergy); + + updateEyeContactTarget(deltaTime); +} + +void MyAvatar::updateEyeContactTarget(float deltaTime) { + + _eyeContactTargetTimer -= deltaTime; + if (_eyeContactTargetTimer < 0.0f) { + + const float CHANCE_OF_CHANGING_TARGET = 0.01f; + if (randFloat() < CHANCE_OF_CHANGING_TARGET) { + + float const FIFTY_FIFTY_CHANCE = 0.5f; + float const EYE_TO_MOUTH_CHANCE = 0.25f; + switch (_eyeContactTarget) { + case LEFT_EYE: + _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : RIGHT_EYE; + break; + case RIGHT_EYE: + _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : LEFT_EYE; + break; + case MOUTH: + _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? RIGHT_EYE : LEFT_EYE; + break; + } + + const float EYE_TARGET_DELAY_TIME = 0.33f; + _eyeContactTargetTimer = EYE_TARGET_DELAY_TIME; + } + } } extern QByteArray avatarStateToFrame(const AvatarData* _avatar); @@ -944,22 +974,6 @@ void MyAvatar::clearLookAtTargetAvatar() { } eyeContactTarget MyAvatar::getEyeContactTarget() { - float const CHANCE_OF_CHANGING_TARGET = 0.01f; - if (randFloat() < CHANCE_OF_CHANGING_TARGET) { - float const FIFTY_FIFTY_CHANCE = 0.5f; - switch (_eyeContactTarget) { - case LEFT_EYE: - _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? MOUTH : RIGHT_EYE; - break; - case RIGHT_EYE: - _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? LEFT_EYE : MOUTH; - break; - case MOUTH: - _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? RIGHT_EYE : LEFT_EYE; - break; - } - } - return _eyeContactTarget; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 35caabe0f7..69bb7ea4c2 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -331,6 +331,8 @@ private: bool cameraInsideHead() const; + void updateEyeContactTarget(float deltaTime); + // These are made private for MyAvatar so that you will use the "use" methods instead virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; @@ -371,6 +373,7 @@ private: float _oculusYawOffset; eyeContactTarget _eyeContactTarget; + float _eyeContactTargetTimer { 0.0f }; glm::vec3 _trackedHeadPosition; From 0c200e8c004719f1018b2e2f378468fba6fb820d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 25 Apr 2016 09:27:43 -0700 Subject: [PATCH 3/3] MyAvatar: coding convention fix for updateEyeContactTarget() --- interface/src/avatar/MyAvatar.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f61f64412c..9a61c00712 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -332,15 +332,16 @@ void MyAvatar::updateEyeContactTarget(float deltaTime) { float const FIFTY_FIFTY_CHANCE = 0.5f; float const EYE_TO_MOUTH_CHANCE = 0.25f; switch (_eyeContactTarget) { - case LEFT_EYE: - _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : RIGHT_EYE; - break; - case RIGHT_EYE: - _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : LEFT_EYE; - break; - case MOUTH: - _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? RIGHT_EYE : LEFT_EYE; - break; + case LEFT_EYE: + _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : RIGHT_EYE; + break; + case RIGHT_EYE: + _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : LEFT_EYE; + break; + case MOUTH: + default: + _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? RIGHT_EYE : LEFT_EYE; + break; } const float EYE_TARGET_DELAY_TIME = 0.33f;