From e32f9f387a21298f733cab3ea4c74c817c8c4bba Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 13:50:56 -0700 Subject: [PATCH 1/8] 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/8] 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/8] 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/8] 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 466c062bc1ada71ffaa35db102e0bad0fb76ab59 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Jun 2013 14:41:06 -0700 Subject: [PATCH 5/8] Use a bound texture for the iris, load it with Qt rather than lodepng (we can probably just remove the lodepng dependency). --- interface/src/Avatar.cpp | 1 + interface/src/Head.cpp | 36 +++++++++++++++++++++--------------- interface/src/Head.h | 3 +++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index a2ff33ca52..4d1eca808d 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -271,6 +271,7 @@ Avatar::~Avatar() { } void Avatar::init() { + _head.init(); _voxels.init(); _initialized = true; } diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index c7fac99d8b..b8f89fbde6 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -5,6 +5,9 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. #include + +#include + #include "Application.h" #include "Avatar.h" #include "Head.h" @@ -36,9 +39,7 @@ const float IRIS_RADIUS = 0.007; const float IRIS_PROTRUSION = 0.0145f; const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png"; -unsigned int IRIS_TEXTURE_WIDTH = 768; -unsigned int IRIS_TEXTURE_HEIGHT = 498; -vector irisTexture; +GLuint Head::_irisTextureID = 0; Head::Head(Avatar* owningAvatar) : HeadData((AvatarData*)owningAvatar), @@ -74,6 +75,19 @@ Head::Head(Avatar* owningAvatar) : } } +void Head::init() { + if (_irisTextureID == 0) { + switchToResourcesParentIfRequired(); + QImage image = QImage(IRIS_TEXTURE_FILENAME).convertToFormat(QImage::Format_RGB888); + + glGenTextures(1, &_irisTextureID); + glBindTexture(GL_TEXTURE_2D, _irisTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + } +} + void Head::reset() { _yaw = _pitch = _roll = 0.0f; _leanForward = _leanSideways = 0.0f; @@ -469,22 +483,12 @@ void Head::renderEyeBrows() { void Head::renderEyeBalls() { - if (::irisTexture.size() == 0) { - switchToResourcesParentIfRequired(); - unsigned error = lodepng::decode(::irisTexture, IRIS_TEXTURE_WIDTH, IRIS_TEXTURE_HEIGHT, IRIS_TEXTURE_FILENAME); - if (error != 0) { - printLog("error %u: %s\n", error, lodepng_error_text(error)); - } - } - // setup the texutre to be used on each iris GLUquadric* irisQuadric = gluNewQuadric(); gluQuadricTexture(irisQuadric, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluQuadricOrientation(irisQuadric, GLU_OUTSIDE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, IRIS_TEXTURE_WIDTH, IRIS_TEXTURE_HEIGHT, - 0, GL_RGBA, GL_UNSIGNED_BYTE, &::irisTexture[0]); + glBindTexture(GL_TEXTURE_2D, _irisTextureID); // render white ball of left eyeball glPushMatrix(); @@ -579,6 +583,8 @@ void Head::renderEyeBalls() { // delete the iris quadric now that we're done with it gluDeleteQuadric(irisQuadric); glPopMatrix(); + + glBindTexture(GL_TEXTURE_2D, 0); } void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { diff --git a/interface/src/Head.h b/interface/src/Head.h index d331b98efc..2deb638eff 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -31,6 +31,7 @@ class Head : public HeadData { public: Head(Avatar* owningAvatar); + void init(); void reset(); void simulate(float deltaTime, bool isMine); void render(bool lookingInMirror, float alpha); @@ -104,6 +105,8 @@ private: glm::vec3* _mohawkTriangleFan; glm::vec3* _mohawkColors; + static GLuint _irisTextureID; + // private methods void createMohawk(); void renderHeadSphere(); From f6e6ceddfe957a7c2ce4db6155b7f04d9deecff9 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 14:53:10 -0700 Subject: [PATCH 6/8] 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 e401663459e9f49d57fa66917b1b5cbd386f6732 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Jun 2013 15:58:49 -0700 Subject: [PATCH 7/8] Added per-pixel specular highlight to irises. --- interface/resources/shaders/iris.frag | 21 ++++++++++++ interface/resources/shaders/iris.vert | 20 +++++++++++ interface/src/Head.cpp | 49 ++++++++++++++++----------- interface/src/Head.h | 2 ++ 4 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 interface/resources/shaders/iris.frag create mode 100644 interface/resources/shaders/iris.vert diff --git a/interface/resources/shaders/iris.frag b/interface/resources/shaders/iris.frag new file mode 100644 index 0000000000..2f5b06d6c6 --- /dev/null +++ b/interface/resources/shaders/iris.frag @@ -0,0 +1,21 @@ +#version 120 + +// +// iris.frag +// fragment shader +// +// Created by Andrzej Kapolka on 6/13/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the iris texture +uniform sampler2D texture; + +// the interpolated normal +varying vec4 normal; + +void main(void) { + float specular = max(0.0, dot(normalize(gl_LightSource[0].position + vec4(0.0, 0.0, 1.0, 0.0)), normalize(normal))); + gl_FragColor = vec4(gl_Color.rgb * texture2D(texture, gl_TexCoord[0].st).rgb + + pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 1.0); +} diff --git a/interface/resources/shaders/iris.vert b/interface/resources/shaders/iris.vert new file mode 100644 index 0000000000..83602f3e99 --- /dev/null +++ b/interface/resources/shaders/iris.vert @@ -0,0 +1,20 @@ +#version 120 + +// +// iris.vert +// vertex shader +// +// Created by Andrzej Kapolka on 6/13/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +// the interpolated normal +varying vec4 normal; + +void main(void) { + normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + gl_FrontColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient + + gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index b8f89fbde6..bba9269b73 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -8,13 +8,13 @@ #include +#include + #include "Application.h" #include "Avatar.h" #include "Head.h" #include "Util.h" -#include -#include -#include +#include "renderer/ProgramObject.h" using namespace std; @@ -39,7 +39,8 @@ const float IRIS_RADIUS = 0.007; const float IRIS_PROTRUSION = 0.0145f; const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png"; -GLuint Head::_irisTextureID = 0; +ProgramObject* Head::_irisProgram = 0; +GLuint Head::_irisTextureID; Head::Head(Avatar* owningAvatar) : HeadData((AvatarData*)owningAvatar), @@ -76,8 +77,15 @@ Head::Head(Avatar* owningAvatar) : } void Head::init() { - if (_irisTextureID == 0) { + if (_irisProgram == 0) { switchToResourcesParentIfRequired(); + _irisProgram = new ProgramObject(); + _irisProgram->addShaderFromSourceFile(QGLShader::Vertex, "resources/shaders/iris.vert"); + _irisProgram->addShaderFromSourceFile(QGLShader::Fragment, "resources/shaders/iris.frag"); + _irisProgram->link(); + + _irisProgram->setUniformValue("texture", 0); + QImage image = QImage(IRIS_TEXTURE_FILENAME).convertToFormat(QImage::Format_RGB888); glGenTextures(1, &_irisTextureID); @@ -483,12 +491,11 @@ void Head::renderEyeBrows() { void Head::renderEyeBalls() { - // setup the texutre to be used on each iris + // setup the texture to be used on each iris GLUquadric* irisQuadric = gluNewQuadric(); gluQuadricTexture(irisQuadric, GL_TRUE); gluQuadricOrientation(irisQuadric, GLU_OUTSIDE); - glBindTexture(GL_TEXTURE_2D, _irisTextureID); // render white ball of left eyeball glPushMatrix(); @@ -497,6 +504,17 @@ void Head::renderEyeBalls() { gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30); glPopMatrix(); + //render white ball of right eyeball + glPushMatrix(); + glColor3fv(EYEBALL_COLOR); + glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); + gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30); + glPopMatrix(); + + _irisProgram->bind(); + glBindTexture(GL_TEXTURE_2D, _irisTextureID); + glEnable(GL_TEXTURE_2D); + glm::vec3 front = getFrontDirection(); // render left iris @@ -529,20 +547,11 @@ void Head::renderEyeBalls() { 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 - glEnable(GL_TEXTURE_2D); gluSphere(irisQuadric, IRIS_RADIUS, 15, 15); - glDisable(GL_TEXTURE_2D); glPopMatrix(); } glPopMatrix(); - //render white ball of right eyeball - glPushMatrix(); - glColor3fv(EYEBALL_COLOR); - glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); - gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30); - glPopMatrix(); - // render right iris glPushMatrix(); { glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); //translate to eyeball position @@ -574,17 +583,17 @@ void Head::renderEyeBalls() { 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 - glEnable(GL_TEXTURE_2D); gluSphere(irisQuadric, IRIS_RADIUS, 15, 15); - glDisable(GL_TEXTURE_2D); glPopMatrix(); } + _irisProgram->release(); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + // delete the iris quadric now that we're done with it gluDeleteQuadric(irisQuadric); glPopMatrix(); - - glBindTexture(GL_TEXTURE_2D, 0); } void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { diff --git a/interface/src/Head.h b/interface/src/Head.h index 2deb638eff..6d0f7819e4 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -26,6 +26,7 @@ enum eyeContactTargets const int NUM_HAIR_TUFTS = 4; class Avatar; +class ProgramObject; class Head : public HeadData { public: @@ -105,6 +106,7 @@ private: glm::vec3* _mohawkTriangleFan; glm::vec3* _mohawkColors; + static ProgramObject* _irisProgram; static GLuint _irisTextureID; // private methods From dd1df47c71262da6653546a8f9888df248c519e4 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 13 Jun 2013 16:20:28 -0700 Subject: [PATCH 8/8] 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(); }