From 00fdc3782233a9746ea2bdb12f432db1158c315f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 23 Jul 2014 22:45:50 -0700 Subject: [PATCH 1/3] add velocity filtering to eyePosition to reduce camera jitter from faceshift --- interface/src/Application.cpp | 2 +- interface/src/avatar/Head.cpp | 4 ++++ interface/src/avatar/Head.h | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8b00bface7..1dc2c15031 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -592,7 +592,7 @@ void Application::paintGL() { if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay - _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); + _myCamera.setTargetPosition(_myAvatar->getHead()->getFilteredEyePosition()); _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index ee242d179a..d3d1e74fc8 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -159,6 +159,10 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { } } _eyePosition = calculateAverageEyePosition(); + + float velocityFilter = glm::clamp(1.0f - glm::length(_filteredEyePosition - _eyePosition), 0.0f, 1.0f); + _filteredEyePosition = velocityFilter * _filteredEyePosition + (1.0f - velocityFilter) * _eyePosition; + } void Head::relaxLean(float deltaTime) { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 36df51fa6f..63667914ac 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -89,7 +89,7 @@ public: const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected) float getAverageLoudness() const { return _averageLoudness; } glm::vec3 calculateAverageEyePosition() const { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } - + glm::vec3 getFilteredEyePosition() const { return _filteredEyePosition; } /// \return the point about which scaling occurs. glm::vec3 getScalePivot() const; @@ -120,6 +120,8 @@ private: glm::vec3 _leftEyePosition; glm::vec3 _rightEyePosition; glm::vec3 _eyePosition; + glm::vec3 _filteredEyePosition; // velocity filtered world space eye position + float _scale; float _lastLoudness; float _audioAttack; From 5aecbe690dcf8ac7c06c87780ff456048041077e Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 23 Jul 2014 22:56:59 -0700 Subject: [PATCH 2/3] made calculateAverageEyePosition private, changed to getEyePosition() where used outside head --- interface/src/Application.cpp | 14 +++++++------- interface/src/avatar/Head.h | 3 ++- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 10 +++++----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1dc2c15031..aa362b790b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -611,10 +611,10 @@ void Application::paintGL() { if (OculusManager::isConnected()) { _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - _myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0)); + _myCamera.setTargetPosition(_myAvatar->getHead()->getEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0)); } else { _myCamera.setTightness(0.0f); - glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition(); + glm::vec3 eyePosition = _myAvatar->getHead()->getFilteredEyePosition(); float headHeight = eyePosition.y - _myAvatar->getPosition().y; _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0)); @@ -1910,14 +1910,14 @@ void Application::updateMyAvatarLookAtPosition() { } } else { // I am not looking at anyone else, so just look forward - lookAtSpot = _myAvatar->getHead()->calculateAverageEyePosition() + + lookAtSpot = _myAvatar->getHead()->getEyePosition() + (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * 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())); + glm::distance(_mouseRayOrigin, _myAvatar->getHead()->getAverageEyePosition())); lookAtSpot = _mouseRayOrigin + _mouseRayDirection * qMax(minEyeDistance, distance); */ @@ -1930,7 +1930,7 @@ void Application::updateMyAvatarLookAtPosition() { 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(); + glm::vec3 origin = _myAvatar->getHead()->getEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; float deflection = Menu::getInstance()->getFaceshiftEyeDeflection(); if (isLookingAtSomeone) { @@ -2934,7 +2934,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _mirrorCamera.setTargetPosition(glm::vec3()); } else { - _mirrorCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition()); + _mirrorCamera.setTargetPosition(_myAvatar->getHead()->getEyePosition()); } } _mirrorCamera.setAspectRatio((float)region.width() / region.height()); @@ -2963,7 +2963,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _myAvatar->getSkeletonModel().getNeckPosition(neckPosition); // get the eye position relative to the body - glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition(); + glm::vec3 eyePosition = _myAvatar->getHead()->getEyePosition(); float eyeHeight = eyePosition.y - _myAvatar->getPosition().y; // set the translation of the face relative to the neck position diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 63667914ac..6d1e82b97f 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -88,7 +88,6 @@ public: const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected) float getAverageLoudness() const { return _averageLoudness; } - glm::vec3 calculateAverageEyePosition() const { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } glm::vec3 getFilteredEyePosition() const { return _filteredEyePosition; } /// \return the point about which scaling occurs. glm::vec3 getScalePivot() const; @@ -110,6 +109,8 @@ public: void addLeanDeltas(float sideways, float forward); private: + glm::vec3 calculateAverageEyePosition() const { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } + // disallow copies of the Head, copy of owning Avatar is disallowed too Head(const Head&); Head& operator= (const Head&); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 556f9dfc68..8cf6cd69a3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -908,7 +908,7 @@ const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const { const Head* head = getHead(); return (renderMode != NORMAL_RENDER_MODE) || - (glm::length(cameraPosition - head->calculateAverageEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale); + (glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale); } float MyAvatar::computeDistanceToFloor(const glm::vec3& startPoint) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 89ae2fbb46..990e4e5c95 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -178,7 +178,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc float dist = sqrt(x * x + y * y); float z = -sqrt(1.0f - dist * dist); - glm::vec3 relativePosition = myAvatar->getHead()->calculateAverageEyePosition() + + glm::vec3 relativePosition = myAvatar->getHead()->getEyePosition() + glm::normalize(myAvatar->getOrientation() * glm::vec3(x, y, z)); //Rotate the UI pick ray by the avatar orientation @@ -274,7 +274,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { MyAvatar* myAvatar = application->getAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); - glm::vec3 eyePos = myAvatar->getHead()->calculateAverageEyePosition(); + glm::vec3 eyePos = myAvatar->getHead()->getEyePosition(); glm::quat orientation = glm::inverse(myAvatar->getOrientation()); glm::vec3 dir = orientation * glm::normalize(application->getCamera()->getPosition() - tip); //direction of ray goes towards camera glm::vec3 tipPos = orientation * (tip - eyePos); @@ -331,7 +331,7 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, glm::quat orientation = myAvatar->getOrientation(); - glm::vec3 relativePosition = orientation * (position - myAvatar->getHead()->calculateAverageEyePosition()); + glm::vec3 relativePosition = orientation * (position - myAvatar->getHead()->getEyePosition()); glm::vec3 relativeDirection = orientation * direction; float t; @@ -375,7 +375,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { glPushMatrix(); const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getHead()->calculateAverageEyePosition(); + const glm::vec3& position = myAvatar->getHead()->getEyePosition(); glm::mat4 rotation = glm::toMat4(orientation); @@ -1210,7 +1210,7 @@ void ApplicationOverlay::renderTexturedHemisphere() { Application* application = Application::getInstance(); MyAvatar* myAvatar = application->getAvatar(); const glm::quat& orientation = myAvatar->getOrientation(); - const glm::vec3& position = myAvatar->getHead()->calculateAverageEyePosition(); + const glm::vec3& position = myAvatar->getHead()->getEyePosition(); glm::mat4 rotation = glm::toMat4(orientation); From a1b74c5272b8faaff31cb361a606226a1a437032 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 23 Jul 2014 23:07:37 -0700 Subject: [PATCH 3/3] remove unused code --- interface/src/Application.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aa362b790b..d2a91c9480 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1913,14 +1913,6 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = _myAvatar->getHead()->getEyePosition() + (_myAvatar->getHead()->getFinalOrientationInWorldFrame() * 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()->getAverageEyePosition())); - lookAtSpot = _mouseRayOrigin + _mouseRayDirection * qMax(minEyeDistance, distance); - */ - } // // Deflect the eyes a bit to match the detected Gaze from 3D camera if active