From 4089d5438956694cd598a25f2d9a498047ae9e2b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 2 May 2014 00:21:14 -0700 Subject: [PATCH] Avatar makes eye contact with the person nearest to gaze direction --- interface/src/Application.cpp | 40 ++++++++++++++++++++++++++----- interface/src/avatar/MyAvatar.cpp | 26 ++++++++++---------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 51000e4815..a83cb5abf0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1807,35 +1807,64 @@ void Application::updateMyAvatarLookAtPosition() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()"); + FaceTracker* tracker = getActiveFaceTracker(); + + 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) lookAtSpot = _myCamera.getPosition(); } else { - // look in direction of the mouse ray, but use distance from intersection, if any - float distance = TREE_SCALE; if (_myAvatar->getLookAtTargetAvatar() && _myAvatar != _myAvatar->getLookAtTargetAvatar()) { - distance = glm::distance(_mouseRayOrigin, - static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->calculateAverageEyePosition()); + isLookingAtSomeone = true; + // If I am looking at someone else, look directly at one of their eyes + if (tracker) { + // If tracker active, look at the eye for the side my gaze is biased toward + if (tracker->getEstimatedEyeYaw() > _myAvatar->getHead()->getFinalYaw()) { + // Look at their left eye + lookAtSpot = static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->getLeftEyePosition(); + } else { + // Look at their right eye + lookAtSpot = static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->getRightEyePosition(); + } + } else { + // Need to add randomly looking back and forth between left and right eye for case with no tracker + lookAtSpot = static_cast(_myAvatar->getLookAtTargetAvatar())->getHead()->getEyePosition(); + } + } else { + // I am not looking at anyone else, so just look forward + lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() + (_myAvatar->getHead()->getFinalOrientation() * glm::vec3(0.f, 0.f, -TREE_SCALE)); } + // TODO: Add saccade to mouse pointer when stable, IF not looking at someone (since we know we are looking at it) + /* const float FIXED_MIN_EYE_DISTANCE = 0.3f; float minEyeDistance = FIXED_MIN_EYE_DISTANCE + (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON ? 0.0f : glm::distance(_mouseRayOrigin, _myAvatar->getHead()->calculateAverageEyePosition())); lookAtSpot = _mouseRayOrigin + _mouseRayDirection * qMax(minEyeDistance, distance); + */ + } - FaceTracker* tracker = getActiveFaceTracker(); + // + // Deflect the eyes a bit to match the detected Gaze from 3D camera if active + // if (tracker) { 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()->calculateAverageEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; float deflection = Menu::getInstance()->getFaceshiftEyeDeflection(); + if (isLookingAtSomeone) { + deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT; + } lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3( eyePitch * pitchSign * deflection, eyeYaw * deflection, 0.0f))) * glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin); } + _myAvatar->getHead()->setLookAtPosition(lookAtSpot); } @@ -2455,7 +2484,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { "Application::displaySide() ... atmosphere..."); _environment.renderAtmospheres(whichCamera); } - glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 23cee8b452..7a70439607 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -555,24 +555,26 @@ void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { } void MyAvatar::updateLookAtTargetAvatar() { - Application* applicationInstance = Application::getInstance(); - - if (!applicationInstance->isMousePressed()) { - glm::vec3 mouseOrigin = applicationInstance->getMouseRayOrigin(); - glm::vec3 mouseDirection = applicationInstance->getMouseRayDirection(); - - foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { - Avatar* avatar = static_cast(avatarPointer.data()); - float distance; - if (avatar->findRayIntersection(mouseOrigin, mouseDirection, distance)) { + // + // Look at the avatar whose eyes are closest to the ray in direction of my avatar's head + // + const float MIN_LOOKAT_ANGLE = PI / 4.0f; // Smallest angle between face and person where we will look at someone + float smallestAngleTo = MIN_LOOKAT_ANGLE; + foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) { + Avatar* avatar = static_cast(avatarPointer.data()); + if (!avatar->isMyAvatar()) { + float angleTo = glm::angle(getHead()->getFinalOrientation() * glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(avatar->getHead()->getEyePosition() - getHead()->getEyePosition())); + if (angleTo < smallestAngleTo) { _lookAtTargetAvatar = avatarPointer; _targetAvatarPosition = avatarPointer->getPosition(); + smallestAngleTo = angleTo; return; } } - _lookAtTargetAvatar.clear(); - _targetAvatarPosition = glm::vec3(0, 0, 0); } + _lookAtTargetAvatar.clear(); + _targetAvatarPosition = glm::vec3(0, 0, 0); } void MyAvatar::clearLookAtTargetAvatar() {