From efbccc3a4e883e20a3010466186de83eb38b2fc2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 29 Jun 2015 15:30:51 -0700 Subject: [PATCH 01/10] Fix storing Oculus eye positions --- interface/src/devices/OculusManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 9d7146cbe7..e5c00a3699 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -692,13 +692,13 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const _eyeRenderPoses[eye] = eyePoses[eye]; // Set the camera rotation for this eye - vec3 eyePosition = toGlm(_eyeRenderPoses[eye].Position); - eyePosition = whichCamera.getRotation() * eyePosition; + _eyePositions[eye] = toGlm(_eyeRenderPoses[eye].Position); + _eyePositions[eye] = whichCamera.getRotation() * _eyePositions[eye]; quat eyeRotation = toGlm(_eyeRenderPoses[eye].Orientation); // Update our camera to what the application camera is doing _camera->setRotation(whichCamera.getRotation() * eyeRotation); - _camera->setPosition(whichCamera.getPosition() + eyePosition); + _camera->setPosition(whichCamera.getPosition() + _eyePositions[eye]); configureCamera(*_camera); _camera->update(1.0f / Application::getInstance()->getFps()); From 6a48b56e0f48381030fe51c333c6d808e49d6cf3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 29 Jun 2015 15:31:15 -0700 Subject: [PATCH 02/10] In mirror mode look directly at the camera in both normal and HMD view --- interface/src/Application.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2e2722aec2..6975f13291 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2282,17 +2282,14 @@ void Application::updateMyAvatarLookAtPosition() { bool isLookingAtSomeone = false; glm::vec3 lookAtSpot; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - // When I am in mirror mode, just look right at the camera (myself) + // When I am in mirror mode, just look right at the camera (myself); don't switch gaze points because when physically + // looking in a mirror one's eyes appear steady. if (!OculusManager::isConnected()) { lookAtSpot = _myCamera.getPosition(); } else { - if (_myAvatar->isLookingAtLeftEye()) { - lookAtSpot = OculusManager::getLeftEyePosition(); - } else { - lookAtSpot = OculusManager::getRightEyePosition(); - } + lookAtSpot = _myCamera.getPosition() + + (OculusManager::getLeftEyePosition() + OculusManager::getRightEyePosition()) / 2.0f; } - } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock(); if (lookingAt && _myAvatar != lookingAt.get()) { From bc4c6351068e81c8d4171ac7e7f5c6a0aa260089 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Jul 2015 18:31:16 -0700 Subject: [PATCH 03/10] Fix gazing at avatar (when no head tracking or HMD) Randomly look at avatar's left and right eyes if the face is visible. Otherwise just look at their head. --- interface/src/Application.cpp | 28 ++++++++++++++++++++-------- interface/src/avatar/FaceModel.cpp | 2 +- interface/src/avatar/Head.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 16 ---------------- 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6975f13291..acc34cbc19 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2294,22 +2294,34 @@ void Application::updateMyAvatarLookAtPosition() { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock(); if (lookingAt && _myAvatar != lookingAt.get()) { isLookingAtSomeone = true; + Head* lookingAtHead = static_cast(lookingAt.get())->getHead(); + // If I am looking at someone else, look directly at one of their eyes if (tracker && !tracker->isMuted()) { // If a face tracker is active, look at the eye for the side my gaze is biased toward if (tracker->getEstimatedEyeYaw() > _myAvatar->getHead()->getFinalYaw()) { - // Look at their right eye - lookAtSpot = static_cast(lookingAt.get())->getHead()->getRightEyePosition(); + lookAtSpot = lookingAtHead->getRightEyePosition(); } else { - // Look at their left eye - lookAtSpot = static_cast(lookingAt.get())->getHead()->getLeftEyePosition(); + lookAtSpot = lookingAtHead->getLeftEyePosition(); } } else { - // Need to add randomly looking back and forth between left and right eye for case with no tracker - if (_myAvatar->isLookingAtLeftEye()) { - lookAtSpot = static_cast(lookingAt.get())->getHead()->getLeftEyePosition(); + + const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE; + glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT; + glm::vec3 fromLookingAtToMe = glm::normalize(_myAvatar->getHead()->getEyePosition() + - lookingAtHead->getEyePosition()); + float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe); + + if (faceAngle < MAXIMUM_FACE_ANGLE) { + // Randomly look back and forth between left and right eyes + if (_myAvatar->isLookingAtLeftEye()) { + lookAtSpot = lookingAtHead->getLeftEyePosition(); + } else { + lookAtSpot = lookingAtHead->getRightEyePosition(); + } } else { - lookAtSpot = static_cast(lookingAt.get())->getHead()->getRightEyePosition(); + // Just look at their head (mid point between eyes) + lookAtSpot = lookingAtHead->getEyePosition(); } } } else { diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 1501c52de5..7a582406a4 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -77,7 +77,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta glm::translate(state.getDefaultTranslationInConstrainedFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); - glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getCorrectedLookAtPosition() + + glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + _owningHead->getSaccade() - model->getTranslation(), 1.0f)); glm::quat between = rotationBetween(front, lookAt); const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 02d16a1ca4..61f378c536 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -256,7 +256,7 @@ void Head::calculateMouthShapes() { void Head::applyEyelidOffset(glm::quat headOrientation) { // Adjusts the eyelid blendshape coefficients so that the eyelid follows the iris as the head pitches. - glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FRONT, getCorrectedLookAtPosition() - _eyePosition); + glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FRONT, getLookAtPosition() - _eyePosition); eyeRotation = eyeRotation * glm::angleAxis(safeEulerAngles(headOrientation).y, IDENTITY_UP); // Rotation w.r.t. head float eyePitch = safeEulerAngles(eyeRotation).x; @@ -295,7 +295,7 @@ void Head::relaxLean(float deltaTime) { void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting) { if (postLighting) { if (_renderLookatVectors) { - renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); + renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getLookAtPosition()); } } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e4ed55601a..f0bba200fe 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -880,7 +880,6 @@ void MyAvatar::updateLookAtTargetAvatar() { const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f; const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; - int howManyLookingAtMe = 0; foreach (const AvatarSharedPointer& avatarPointer, DependencyManager::get()->getAvatarHash()) { Avatar* avatar = static_cast(avatarPointer.get()); bool isCurrentTarget = avatar->getIsLookAtTarget(); @@ -893,21 +892,6 @@ void MyAvatar::updateLookAtTargetAvatar() { _targetAvatarPosition = avatarPointer->getPosition(); smallestAngleTo = angleTo; } - // Check if this avatar is looking at me, and fix their gaze on my camera if so - if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { - howManyLookingAtMe++; - // Have that avatar look directly at my camera - // Philip TODO: correct to look at left/right eye - if (qApp->isHMDMode()) { - avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); - // FIXME what is the point of this? - // avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition()); - } else { - avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); - } - } else { - avatar->getHead()->clearCorrectedLookAtPosition(); - } } } auto avatarPointer = _lookAtTargetAvatar.lock(); From fada70fe02f48358bb435935373cd431768ba673 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Jul 2015 18:32:33 -0700 Subject: [PATCH 04/10] Remove redundant code --- interface/src/Application.cpp | 9 --------- interface/src/Application.h | 2 -- interface/src/avatar/Head.cpp | 13 ------------- interface/src/avatar/Head.h | 5 ----- 4 files changed, 29 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index acc34cbc19..f8fb2bb9a6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2229,15 +2229,6 @@ void Application::shrinkMirrorView() { const float HEAD_SPHERE_RADIUS = 0.1f; -bool Application::isLookingAtMyAvatar(Avatar* avatar) { - glm::vec3 theirLookAt = avatar->getHead()->getLookAtPosition(); - glm::vec3 myEyePosition = _myAvatar->getHead()->getEyePosition(); - if (pointInSphere(theirLookAt, myEyePosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { - return true; - } - return false; -} - void Application::updateLOD() { PerformanceTimer perfTimer("LOD"); // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode diff --git a/interface/src/Application.h b/interface/src/Application.h index 0787cffbdc..375aded8ac 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -322,8 +322,6 @@ public: QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } - bool isLookingAtMyAvatar(Avatar* avatar); - float getRenderResolutionScale() const; int getRenderAmbientLight() const; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 61f378c536..27888b9d4e 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -315,19 +315,6 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { return glm::quat(glm::radians(glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); } -glm::vec3 Head::getCorrectedLookAtPosition() { - if (_isLookingAtMe) { - return _correctedLookAtPosition; - } else { - return getLookAtPosition(); - } -} - -void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { - _isLookingAtMe = true; - _correctedLookAtPosition = correctedLookAtPosition; -} - glm::quat Head::getCameraOrientation() const { // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so // you may wonder why this code is here. This method will be called while in Oculus mode to determine how diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index a208574c26..0b216e4a2e 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -56,9 +56,6 @@ public: /// \return orientationBody * orientationBasePitch glm::quat getCameraOrientation () const; - void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition); - glm::vec3 getCorrectedLookAtPosition(); - void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } bool getIsLookingAtMe() { return _isLookingAtMe; } float getScale() const { return _scale; } @@ -147,8 +144,6 @@ private: bool _isLookingAtMe; FaceModel _faceModel; - glm::vec3 _correctedLookAtPosition; - int _leftEyeLookAtID; int _rightEyeLookAtID; From 26cbb14f45c91f788d5f7ce89a6435bcd4e9c6bb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Jul 2015 20:09:36 -0700 Subject: [PATCH 05/10] Alternative look-at gaze left/right with face trackers too Instead of looking at one or other eye depending on look direction. --- interface/src/Application.cpp | 38 +++++++++++++---------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f8fb2bb9a6..29bc9a4f9c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2284,36 +2284,26 @@ void Application::updateMyAvatarLookAtPosition() { } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock(); if (lookingAt && _myAvatar != lookingAt.get()) { + // If I am looking at someone else, look directly at one of their eyes isLookingAtSomeone = true; Head* lookingAtHead = static_cast(lookingAt.get())->getHead(); - // If I am looking at someone else, look directly at one of their eyes - if (tracker && !tracker->isMuted()) { - // If a face tracker is active, look at the eye for the side my gaze is biased toward - if (tracker->getEstimatedEyeYaw() > _myAvatar->getHead()->getFinalYaw()) { - lookAtSpot = lookingAtHead->getRightEyePosition(); - } else { + const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE; + glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT; + glm::vec3 fromLookingAtToMe = glm::normalize(_myAvatar->getHead()->getEyePosition() + - lookingAtHead->getEyePosition()); + float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe); + + if (faceAngle < MAXIMUM_FACE_ANGLE) { + // Randomly look back and forth between left and right eyes + if (_myAvatar->isLookingAtLeftEye()) { lookAtSpot = lookingAtHead->getLeftEyePosition(); + } else { + lookAtSpot = lookingAtHead->getRightEyePosition(); } } else { - - const float MAXIMUM_FACE_ANGLE = 65.0f * RADIANS_PER_DEGREE; - glm::vec3 lookingAtFaceOrientation = lookingAtHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT; - glm::vec3 fromLookingAtToMe = glm::normalize(_myAvatar->getHead()->getEyePosition() - - lookingAtHead->getEyePosition()); - float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe); - - if (faceAngle < MAXIMUM_FACE_ANGLE) { - // Randomly look back and forth between left and right eyes - if (_myAvatar->isLookingAtLeftEye()) { - lookAtSpot = lookingAtHead->getLeftEyePosition(); - } else { - lookAtSpot = lookingAtHead->getRightEyePosition(); - } - } else { - // Just look at their head (mid point between eyes) - lookAtSpot = lookingAtHead->getEyePosition(); - } + // Just look at their head (mid point between eyes) + lookAtSpot = lookingAtHead->getEyePosition(); } } else { // I am not looking at anyone else, so just look forward From 4ced0dc6c441f926a7bb31e0d762bc69d87387e0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Jul 2015 20:24:47 -0700 Subject: [PATCH 06/10] Only deflect eyes for Faceshift; DDE doesn't provide eye pitch or yaw --- interface/src/Application.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 29bc9a4f9c..48ea822efc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2311,14 +2311,13 @@ void Application::updateMyAvatarLookAtPosition() { (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } } - // - // Deflect the eyes a bit to match the detected Gaze from 3D camera if active - // - if (tracker && !tracker->isMuted()) { + + // Deflect the eyes a bit to match the detected gaze from Faceshift if active. + // DDE doesn't track eyes. + if (tracker && typeid(*tracker) == typeid(Faceshift) && !tracker->isMuted()) { float eyePitch = tracker->getEstimatedEyePitch(); float eyeYaw = tracker->getEstimatedEyeYaw(); const float GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT = 0.1f; - // deflect using Faceshift gaze data glm::vec3 origin = _myAvatar->getHead()->getEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; float deflection = DependencyManager::get()->getEyeDeflection(); From 026f6d3690165c1adca62a722cf158b6c533590c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Jul 2015 21:22:30 -0700 Subject: [PATCH 07/10] Add mouth as third gaze target in addition to left and right eyes --- interface/src/Application.cpp | 16 +++++++++++----- interface/src/avatar/Head.h | 6 +----- interface/src/avatar/MyAvatar.cpp | 24 ++++++++++++++++++------ interface/src/avatar/MyAvatar.h | 10 ++++++++-- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 48ea822efc..d68a3813a9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2295,11 +2295,17 @@ void Application::updateMyAvatarLookAtPosition() { float faceAngle = glm::angle(lookingAtFaceOrientation, fromLookingAtToMe); if (faceAngle < MAXIMUM_FACE_ANGLE) { - // Randomly look back and forth between left and right eyes - if (_myAvatar->isLookingAtLeftEye()) { - lookAtSpot = lookingAtHead->getLeftEyePosition(); - } else { - lookAtSpot = lookingAtHead->getRightEyePosition(); + // Randomly look back and forth between look targets + switch (_myAvatar->getEyeContactTarget()) { + case LEFT_EYE: + lookAtSpot = lookingAtHead->getLeftEyePosition(); + break; + case RIGHT_EYE: + lookAtSpot = lookingAtHead->getRightEyePosition(); + break; + case MOUTH: + lookAtSpot = lookingAtHead->getMouthPosition(); + break; } } else { // Just look at their head (mid point between eyes) diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 0b216e4a2e..a053a5bd44 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -22,11 +22,6 @@ #include "InterfaceConfig.h" #include "world.h" -enum eyeContactTargets { - LEFT_EYE, - RIGHT_EYE, - MOUTH -}; const float EYE_EAR_GAP = 0.08f; @@ -74,6 +69,7 @@ public: const glm::vec3& getLeftEyePosition() const { return _leftEyePosition; } glm::vec3 getRightEarPosition() const { return _rightEyePosition + (getRightDirection() * EYE_EAR_GAP) + (getFrontDirection() * -EYE_EAR_GAP); } glm::vec3 getLeftEarPosition() const { return _leftEyePosition + (getRightDirection() * -EYE_EAR_GAP) + (getFrontDirection() * -EYE_EAR_GAP); } + glm::vec3 getMouthPosition() const { return _eyePosition - getUpDirection() * glm::length(_rightEyePosition - _leftEyePosition); } FaceModel& getFaceModel() { return _faceModel; } const FaceModel& getFaceModel() const { return _faceModel; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f0bba200fe..170fc03d17 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -95,7 +95,7 @@ MyAvatar::MyAvatar() : _shouldRender(true), _billboardValid(false), _feetTouchFloor(true), - _isLookingAtLeftEye(true), + _eyeContactTarget(LEFT_EYE), _realWorldFieldOfView("realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), _firstPersonSkeletonModel(this), @@ -904,12 +904,24 @@ void MyAvatar::clearLookAtTargetAvatar() { _lookAtTargetAvatar.reset(); } -bool MyAvatar::isLookingAtLeftEye() { - float const CHANCE_OF_CHANGING_EYE = 0.01f; - if (randFloat() < CHANCE_OF_CHANGING_EYE) { - _isLookingAtLeftEye = !_isLookingAtLeftEye; +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 _isLookingAtLeftEye; + + return _eyeContactTarget; } glm::vec3 MyAvatar::getDefaultEyePosition() const { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2fea09ee27..daec7d3457 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -19,6 +19,12 @@ class ModelItemID; +enum eyeContactTarget { + LEFT_EYE, + RIGHT_EYE, + MOUTH +}; + class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) @@ -93,7 +99,7 @@ public: bool isMyAvatar() const { return true; } - bool isLookingAtLeftEye(); + eyeContactTarget getEyeContactTarget(); virtual int parseDataAtOffset(const QByteArray& packet, int offset); @@ -245,7 +251,7 @@ private: QList _animationHandles; bool _feetTouchFloor; - bool _isLookingAtLeftEye; + eyeContactTarget _eyeContactTarget; RecorderPointer _recorder; From 3a92878544669199e2239188ae1080adb7b8e223 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 2 Jul 2015 13:47:52 -0700 Subject: [PATCH 08/10] Reinstate making someone looking at me look at my camera instead of face --- interface/src/Application.cpp | 9 +++++++++ interface/src/Application.h | 2 ++ interface/src/avatar/FaceModel.cpp | 2 +- interface/src/avatar/Head.cpp | 19 ++++++++++++++++--- interface/src/avatar/Head.h | 5 +++++ interface/src/avatar/MyAvatar.cpp | 6 ++++++ 6 files changed, 39 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca264fd42f..01323d3e1d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2248,6 +2248,15 @@ void Application::shrinkMirrorView() { const float HEAD_SPHERE_RADIUS = 0.1f; +bool Application::isLookingAtMyAvatar(Avatar* avatar) { + glm::vec3 theirLookAt = avatar->getHead()->getLookAtPosition(); + glm::vec3 myEyePosition = _myAvatar->getHead()->getEyePosition(); + if (pointInSphere(theirLookAt, myEyePosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { + return true; + } + return false; +} + void Application::updateLOD() { PerformanceTimer perfTimer("LOD"); // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode diff --git a/interface/src/Application.h b/interface/src/Application.h index 1d3c0dcc70..8dd987fbcd 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -322,6 +322,8 @@ public: QStringList getRunningScripts() { return _scriptEnginesHash.keys(); } ScriptEngine* getScriptEngine(QString scriptHash) { return _scriptEnginesHash.contains(scriptHash) ? _scriptEnginesHash[scriptHash] : NULL; } + bool isLookingAtMyAvatar(Avatar* avatar); + float getRenderResolutionScale() const; int getRenderAmbientLight() const; diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 7a582406a4..1501c52de5 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -77,7 +77,7 @@ void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentSta glm::translate(state.getDefaultTranslationInConstrainedFrame()) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); - glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + + glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getCorrectedLookAtPosition() + _owningHead->getSaccade() - model->getTranslation(), 1.0f)); glm::quat between = rotationBetween(front, lookAt); const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 911bd4f4a4..e5201a8923 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -258,7 +258,7 @@ void Head::calculateMouthShapes() { void Head::applyEyelidOffset(glm::quat headOrientation) { // Adjusts the eyelid blendshape coefficients so that the eyelid follows the iris as the head pitches. - glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FRONT, getLookAtPosition() - _eyePosition); + glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FRONT, getCorrectedLookAtPosition() - _eyePosition); eyeRotation = eyeRotation * glm::angleAxis(safeEulerAngles(headOrientation).y, IDENTITY_UP); // Rotation w.r.t. head float eyePitch = safeEulerAngles(eyeRotation).x; @@ -295,8 +295,8 @@ void Head::relaxLean(float deltaTime) { } void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting) { - if (_renderLookatVectors) { - renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getLookAtPosition()); + if (_renderLookatVectors && _isLookingAtMe) { + renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); } } @@ -315,6 +315,19 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { return glm::quat(glm::radians(glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); } +glm::vec3 Head::getCorrectedLookAtPosition() { + if (_isLookingAtMe) { + return _correctedLookAtPosition; + } else { + return getLookAtPosition(); + } +} + +void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { + _isLookingAtMe = true; + _correctedLookAtPosition = correctedLookAtPosition; +} + glm::quat Head::getCameraOrientation() const { // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so // you may wonder why this code is here. This method will be called while in Oculus mode to determine how diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index a053a5bd44..3f839d53bc 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -51,6 +51,9 @@ public: /// \return orientationBody * orientationBasePitch glm::quat getCameraOrientation () const; + void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition); + glm::vec3 getCorrectedLookAtPosition(); + void clearCorrectedLookAtPosition() { _isLookingAtMe = false; } bool getIsLookingAtMe() { return _isLookingAtMe; } float getScale() const { return _scale; } @@ -140,6 +143,8 @@ private: bool _isLookingAtMe; FaceModel _faceModel; + glm::vec3 _correctedLookAtPosition; + int _leftEyeLookAtID; int _rightEyeLookAtID; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 03b8a56526..9c46edc2d8 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -892,6 +892,12 @@ void MyAvatar::updateLookAtTargetAvatar() { _targetAvatarPosition = avatarPointer->getPosition(); smallestAngleTo = angleTo; } + if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { + // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face + avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); + } else { + avatar->getHead()->clearCorrectedLookAtPosition(); + } } } auto avatarPointer = _lookAtTargetAvatar.lock(); From 9efeda9716d68513cb26e1b203a3cae184577ada Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 2 Jul 2015 15:43:23 -0700 Subject: [PATCH 09/10] Adjust gaze target for someone looking at me --- interface/src/Application.cpp | 3 +-- interface/src/avatar/MyAvatar.cpp | 22 +++++++++++++++++++--- interface/src/devices/OculusManager.cpp | 1 + interface/src/devices/OculusManager.h | 1 + 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 01323d3e1d..1a39999301 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2306,8 +2306,7 @@ void Application::updateMyAvatarLookAtPosition() { if (!OculusManager::isConnected()) { lookAtSpot = _myCamera.getPosition(); } else { - lookAtSpot = _myCamera.getPosition() - + (OculusManager::getLeftEyePosition() + OculusManager::getRightEyePosition()) / 2.0f; + lookAtSpot = _myCamera.getPosition() + OculusManager::getMidEyePosition(); } } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().lock(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9c46edc2d8..c3c8ddcd25 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -34,6 +34,9 @@ #include #include +#include "devices/Faceshift.h" +#include "devices/OculusManager.h" + #include "Application.h" #include "AvatarManager.h" #include "Environment.h" @@ -42,7 +45,6 @@ #include "MyAvatar.h" #include "Physics.h" #include "Recorder.h" -#include "devices/Faceshift.h" #include "Util.h" #include "InterfaceLogging.h" @@ -893,8 +895,22 @@ void MyAvatar::updateLookAtTargetAvatar() { smallestAngleTo = angleTo; } if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { - // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face - avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); + // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. + // Offset their gaze according to whether they're looking at one of my eyes or my mouth. + glm::vec3 gazeOffset = avatar->getHead()->getLookAtPosition() - getHead()->getEyePosition(); + const float HUMAN_EYE_SEPARATION = 0.065f; + float myEyeSeparation = glm::length(getHead()->getLeftEyePosition() - getHead()->getRightEyePosition()); + gazeOffset = gazeOffset * HUMAN_EYE_SEPARATION / myEyeSeparation; + + if (Application::getInstance()->isHMDMode()) { + //avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getCamera()->getPosition() + // + OculusManager::getMidEyePosition() + gazeOffset); + avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition() + + OculusManager::getMidEyePosition() + gazeOffset); + } else { + avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition() + + gazeOffset); + } } else { avatar->getHead()->clearCorrectedLookAtPosition(); } diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index e5c00a3699..eb19031156 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -283,6 +283,7 @@ static ovrVector3f _eyeOffsets[ovrEye_Count]; glm::vec3 OculusManager::getLeftEyePosition() { return _eyePositions[ovrEye_Left]; } glm::vec3 OculusManager::getRightEyePosition() { return _eyePositions[ovrEye_Right]; } +glm::vec3 OculusManager::getMidEyePosition() { return (_eyePositions[ovrEye_Left] + _eyePositions[ovrEye_Right]) / 2.0f; } void OculusManager::connect(QOpenGLContext* shareContext) { qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING; diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 9d9f091296..83ecbf0fb7 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -47,6 +47,7 @@ public: static glm::vec3 getLeftEyePosition(); static glm::vec3 getRightEyePosition(); + static glm::vec3 getMidEyePosition(); static int getHMDScreen(); From 3f38a835d830a0adab8d444190ef1801c4176b65 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 3 Jul 2015 13:49:10 -0700 Subject: [PATCH 10/10] Fix look-at vectors not rendering if not looking at me --- interface/src/avatar/Head.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index e5201a8923..98126c3a22 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -295,7 +295,7 @@ void Head::relaxLean(float deltaTime) { } void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum, bool postLighting) { - if (_renderLookatVectors && _isLookingAtMe) { + if (_renderLookatVectors) { renderLookatVectors(renderArgs, _leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); } }