From e32f9f387a21298f733cab3ea4c74c817c8c4bba Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 13:50:56 -0700 Subject: [PATCH 1/6] Basic random eye movements added, and fixation on camera in mirror mode. --- interface/src/Application.cpp | 7 +++++- interface/src/Avatar.cpp | 3 ++- interface/src/Head.cpp | 42 +++++++++++++---------------------- interface/src/Head.h | 2 ++ interface/src/Util.cpp | 5 +++++ interface/src/Util.h | 2 ++ 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 40f7de7e85..1faec3fb51 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2042,7 +2042,12 @@ void Application::displaySide(Camera& whichCamera) { } agentList->unlock(); - // Render my own Avatar + // Render my own Avatar + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + _myAvatar.getHead().setLookAtPosition(_myCamera.getPosition()); + } else { + _myAvatar.getHead().setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); + } _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); } diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index a2ff33ca52..0a1ff22ce6 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -616,13 +616,14 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { } // set head lookat position + /* if (!_owningAgent) { if (_interactingOther) { _head.setLookAtPosition(_interactingOther->calculateAverageEyePosition()); } else { _head.setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); // 0,0,0 represents NOT looking at anything } - } + }*/ _head.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index c7fac99d8b..a3bf63293a 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -67,7 +67,9 @@ Head::Head(Avatar* owningAvatar) : _lookingInMirror(false), _renderLookatVectors(false), _mohawkTriangleFan(NULL), - _mohawkColors(NULL) + _mohawkColors(NULL), + _saccade(0.0f, 0.0f, 0.0f), + _saccadeTarget(0.0f, 0.0f, 0.0f) { if (USING_PHYSICAL_MOHAWK) { resetHairPhysics(); @@ -102,32 +104,19 @@ void Head::resetHairPhysics() { void Head::simulate(float deltaTime, bool isMine) { - - const float HEAD_MOTION_DECAY = 0.00; - /* - // Decay head back to center if turned on - if (isMine && _returnHeadToCenter) { + // Update eye saccades + const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; + const float AVERAGE_SACCADE_INTERVAL = 4.0f; + const float MICROSACCADE_MAGNITUDE = 0.002f; + const float SACCADE_MAGNITUDE = 0.04; - // Decay rotation back toward center - _pitch *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * deltaTime); - _yaw *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * deltaTime); - _roll *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * deltaTime); + if (randFloat() < deltaTime / AVERAGE_MICROSACCADE_INTERVAL) { + _saccadeTarget = MICROSACCADE_MAGNITUDE * randVector(); + } else if (randFloat() < deltaTime / AVERAGE_SACCADE_INTERVAL) { + _saccadeTarget = SACCADE_MAGNITUDE * randVector(); } - - // For invensense gyro, decay only slightly when near center (until we add fusion) - if (isMine) { - const float RETURN_RANGE = 15.0; - const float RETURN_STRENGTH = 0.5; - if (fabs(_pitch) < RETURN_RANGE) { _pitch *= (1.0f - RETURN_STRENGTH * deltaTime); } - if (fabs(_yaw ) < RETURN_RANGE) { _yaw *= (1.0f - RETURN_STRENGTH * deltaTime); } - if (fabs(_roll ) < RETURN_RANGE) { _roll *= (1.0f - RETURN_STRENGTH * deltaTime); } - } - */ - - // decay lean - _leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime); - _leanSideways *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime); + _saccade += (_saccadeTarget - _saccade) * 0.50f; // Update audio trailing average for rendering facial animations const float AUDIO_AVERAGING_SECS = 0.05; @@ -504,8 +493,7 @@ void Head::renderEyeBalls() { if (_lookingAtSomething) { //rotate the eyeball to aim towards the lookat position - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction - glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); + glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _leftEyePosition); glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations @@ -548,7 +536,7 @@ void Head::renderEyeBalls() { if (_lookingAtSomething) { //rotate the eyeball to aim towards the lookat position - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition); + glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _rightEyePosition); glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); diff --git a/interface/src/Head.h b/interface/src/Head.h index d331b98efc..6f492a6d1d 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -103,6 +103,8 @@ private: HairTuft _hairTuft[NUM_HAIR_TUFTS]; glm::vec3* _mohawkTriangleFan; glm::vec3* _mohawkColors; + glm::vec3 _saccade; + glm::vec3 _saccadeTarget; // private methods void createMohawk(); diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index cc566dd6fb..93596e1c1d 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -267,6 +267,11 @@ double diffclock(timeval *clock1,timeval *clock2) return diffms; } +// Return a random vector of average length 1 +const glm::vec3 randVector() { + return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.f; +} + static TextRenderer* textRenderer(int mono) { static TextRenderer* monoRenderer = new TextRenderer(MONO_FONT_FAMILY); static TextRenderer* proportionalRenderer = new TextRenderer(SANS_FONT_FAMILY, -1, -1, false, TextRenderer::SHADOW_EFFECT); diff --git a/interface/src/Util.h b/interface/src/Util.h index 6cac785956..24cbad9e68 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -32,6 +32,8 @@ float azimuth_to(glm::vec3 head_pos, glm::vec3 source_pos); float angle_to(glm::vec3 head_pos, glm::vec3 source_pos, float render_yaw, float head_yaw); float randFloat(); +const glm::vec3 randVector(); + void render_world_box(); int widthText(float scale, int mono, char const* string); float widthChar(float scale, int mono, char ch); From 687966c48648221e2618a7ba8f467e564349954f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 14:04:51 -0700 Subject: [PATCH 2/6] Other people's avatar's look where they are mousing --- interface/src/Application.cpp | 8 +++++--- interface/src/Avatar.cpp | 10 ---------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1faec3fb51..f2ee4fcff1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1449,6 +1449,10 @@ void Application::update(float deltaTime) { // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); + + // Set where I am looking based on my mouse ray (so that other people can see) + glm::vec3 myLookAtFromMouse(mouseRayOrigin - mouseRayDirection); + _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); // If we are dragging on a voxel, add thrust according to the amount the mouse is dragging const float VOXEL_GRAB_THRUST = 5.0f; @@ -2045,9 +2049,7 @@ void Application::displaySide(Camera& whichCamera) { // Render my own Avatar if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myAvatar.getHead().setLookAtPosition(_myCamera.getPosition()); - } else { - _myAvatar.getHead().setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); - } + } _myAvatar.render(_lookingInMirror->isChecked(), _renderAvatarBalls->isChecked()); _myAvatar.setDisplayingLookatVectors(_renderLookatOn->isChecked()); } diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 0a1ff22ce6..a3618b1726 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -615,16 +615,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { } } - // set head lookat position - /* - if (!_owningAgent) { - if (_interactingOther) { - _head.setLookAtPosition(_interactingOther->calculateAverageEyePosition()); - } else { - _head.setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); // 0,0,0 represents NOT looking at anything - } - }*/ - _head.setBodyRotation (glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll)); _head.setPosition(_bodyBall[ BODY_BALL_HEAD_BASE ].position); _head.setScale (_bodyBall[ BODY_BALL_HEAD_BASE ].radius); From 8af0da754f704e8ea6f46e77f793d981328ab3b7 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 14:21:14 -0700 Subject: [PATCH 3/6] we are always looking at something --- interface/src/Head.cpp | 28 +++++----------------------- interface/src/Head.h | 2 -- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index a3bf63293a..e2b9fdb3ad 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -57,7 +57,6 @@ Head::Head(Avatar* owningAvatar) : _mouthPosition(0.0f, 0.0f, 0.0f), _scale(1.0f), _browAudioLift(0.0f), - _lookingAtSomething(false), _gravity(0.0f, -1.0f, 0.0f), _lastLoudness(0.0f), _averageLoudness(0.0f), @@ -137,30 +136,13 @@ void Head::simulate(float deltaTime, bool isMine) { _browAudioLift *= 0.7f; - // based on the nature of the lookat position, determine if the eyes can look / are looking at it. - determineIfLookingAtSomething(); - + // based on the nature of the lookat position, determine if the eyes can look / are looking at it. if (USING_PHYSICAL_MOHAWK) { updateHairPhysics(deltaTime); } } -void Head::determineIfLookingAtSomething() { - - if ( fabs(_lookAtPosition.x + _lookAtPosition.y + _lookAtPosition.z) == 0.0 ) { // a lookatPosition of 0,0,0 signifies NOT looking - _lookingAtSomething = false; - } else { - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - calculateAverageEyePosition()); - float dot = glm::dot(targetLookatAxis, getFrontDirection()); - if (dot < MINIMUM_EYE_ROTATION_DOT) { // too far off from center for the eyes to rotate - _lookingAtSomething = false; - } else { - _lookingAtSomething = true; - } - } -} - void Head::calculateGeometry() { //generate orientation directions glm::quat orientation = getOrientation(); @@ -207,9 +189,9 @@ void Head::render(bool lookingInMirror, float alpha) { renderEyeBalls(); renderEars(); renderMouth(); - renderEyeBrows(); + renderEyeBrows(); - if (_renderLookatVectors && _lookingAtSomething) { + if (_renderLookatVectors) { renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition); } } @@ -490,7 +472,7 @@ void Head::renderEyeBalls() { glPushMatrix(); - if (_lookingAtSomething) { + if (1) { //rotate the eyeball to aim towards the lookat position glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _leftEyePosition); glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); @@ -533,7 +515,7 @@ void Head::renderEyeBalls() { glPushMatrix(); - if (_lookingAtSomething) { + if (1) { //rotate the eyeball to aim towards the lookat position glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _rightEyePosition); diff --git a/interface/src/Head.h b/interface/src/Head.h index 6f492a6d1d..a46571a99d 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -91,7 +91,6 @@ private: glm::vec3 _mouthPosition; float _scale; float _browAudioLift; - bool _lookingAtSomething; glm::vec3 _gravity; float _lastLoudness; float _averageLoudness; @@ -115,7 +114,6 @@ private: void renderMouth(); void renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); void calculateGeometry(); - void determineIfLookingAtSomething(); void resetHairPhysics(); void updateHairPhysics(float deltaTime); }; From 1556886a647256d2d02288614faf0b8501dc4a2e Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 14:33:09 -0700 Subject: [PATCH 4/6] fixing reversed lookat, rendering for all avatars --- interface/src/Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f2ee4fcff1..c23901da79 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1451,7 +1451,7 @@ void Application::update(float deltaTime) { _myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection); // Set where I am looking based on my mouse ray (so that other people can see) - glm::vec3 myLookAtFromMouse(mouseRayOrigin - mouseRayDirection); + glm::vec3 myLookAtFromMouse(mouseRayOrigin + mouseRayDirection); _myAvatar.getHead().setLookAtPosition(myLookAtFromMouse); // If we are dragging on a voxel, add thrust according to the amount the mouse is dragging @@ -2042,6 +2042,7 @@ void Application::displaySide(Camera& whichCamera) { avatar->init(); } avatar->render(false, _renderAvatarBalls->isChecked()); + avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked()); } } agentList->unlock(); From f6e6ceddfe957a7c2ce4db6155b7f04d9deecff9 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 14:53:10 -0700 Subject: [PATCH 5/6] Head camera scaling always one if gyros off so that mouse look works. --- interface/src/Application.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c23901da79..4ed6d270c0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -303,6 +303,8 @@ void Application::paintGL() { glEnable(GL_LINE_SMOOTH); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + float headCameraScale = _serialHeadSensor.active ? _headCameraPitchYawScale : 1.0f; + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setTightness (100.0f); _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); @@ -318,11 +320,11 @@ void Application::paintGL() { } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { _myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); - _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(_headCameraPitchYawScale)); + _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(headCameraScale)); } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); - _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(_headCameraPitchYawScale)); + _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(headCameraScale)); } // Update camera position From dd1df47c71262da6653546a8f9888df248c519e4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 16:20:28 -0700 Subject: [PATCH 6/6] fixes per review --- interface/src/Head.cpp | 67 ++++++++++-------------------------------- 1 file changed, 16 insertions(+), 51 deletions(-) diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 790b88ef6e..63fc6d6c25 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -491,32 +491,15 @@ void Head::renderEyeBalls() { // render left iris glPushMatrix(); { glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); //translate to eyeball position - glPushMatrix(); - - if (1) { - - //rotate the eyeball to aim towards the lookat position - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _leftEyePosition); glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); - float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); - glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); - glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations - } else { - - //rotate the eyeball to aim straight ahead - glm::vec3 rotationAxisToHeadFront = glm::cross(front, IDENTITY_UP); - float angleToHeadFront = 180.0f - angleBetween(front, IDENTITY_UP); - glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z); - - //set the amount of roll (for correction after previous rotations) - float rollRotation = angleBetween(front, IDENTITY_FRONT); - float dot = glm::dot(front, -IDENTITY_RIGHT); - if ( dot < 0.0f ) { rollRotation = -rollRotation; } - glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector - } - - glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!) - glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris + //rotate the eyeball to aim towards the lookat position + glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _leftEyePosition); + glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); + float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); + glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); + glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations + glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f); + glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris gluSphere(irisQuadric, IRIS_RADIUS, 15, 15); glPopMatrix(); } @@ -525,34 +508,16 @@ void Head::renderEyeBalls() { // render right iris glPushMatrix(); { glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); //translate to eyeball position - glPushMatrix(); - - if (1) { - - //rotate the eyeball to aim towards the lookat position - glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _rightEyePosition); - glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); - float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); - glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); - glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations - } else { - - //rotate the eyeball to aim straight ahead - glm::vec3 rotationAxisToHeadFront = glm::cross(front, IDENTITY_UP); - float angleToHeadFront = 180.0f - angleBetween(front, IDENTITY_UP); - glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z); - - //set the amount of roll (for correction after previous rotations) - float rollRotation = angleBetween(front, IDENTITY_FRONT); - float dot = glm::dot(front, -IDENTITY_RIGHT); - if ( dot < 0.0f ) { rollRotation = -rollRotation; } - glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector - } - - glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!) - glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris + //rotate the eyeball to aim towards the lookat position + glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition + _saccade - _rightEyePosition); + glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); + float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); + glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); + glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations + glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f); + glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris gluSphere(irisQuadric, IRIS_RADIUS, 15, 15); glPopMatrix(); }