diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 658f07cbb7..4ddd7c928f 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -46,7 +46,7 @@ const float HEAD_MAX_PITCH = 45; const float HEAD_MIN_PITCH = -45; const float HEAD_MAX_YAW = 85; const float HEAD_MIN_YAW = -85; -const float AVATAR_BRAKING_RANGE = 1.3f; +const float PERIPERSONAL_RADIUS = 1.0f; const float AVATAR_BRAKING_STRENGTH = 40.0f; const float JOINT_TOUCH_RANGE = 0.0005f; @@ -104,14 +104,14 @@ Avatar::Avatar(bool isMine) { initializeSkeleton(); - _avatarTouch.setReachableRadius(1.0); + _avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS); if (BALLS_ON) { _balls = new Balls(100); } else { _balls = NULL; } } -Avatar::Avatar(const Avatar &otherAvatar) { - +Avatar::Avatar(const Avatar &otherAvatar) :_head(otherAvatar._head) { //include the copy constructor for head + _velocity = otherAvatar._velocity; _thrust = otherAvatar._thrust; _rotation = otherAvatar._rotation; @@ -145,6 +145,7 @@ Avatar::Avatar(const Avatar &otherAvatar) { for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = otherAvatar._driveKeys[i]; + /* _head.pupilSize = otherAvatar._head.pupilSize; _head.interPupilDistance = otherAvatar._head.interPupilDistance; _head.interBrowDistance = otherAvatar._head.interBrowDistance; @@ -181,19 +182,11 @@ Avatar::Avatar(const Avatar &otherAvatar) { _head.lastLoudness = otherAvatar._head.lastLoudness; _head.browAudioLift = otherAvatar._head.browAudioLift; _head.noise = otherAvatar._head.noise; + */ + _distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar; initializeSkeleton(); - -/* - if (iris_texture.size() == 0) { - switchToResourcesParentIfRequired(); - unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file); - if (error != 0) { - printLog("error %u: %s\n", error, lodepng_error_text(error)); - } - } -*/ } Avatar::~Avatar() { @@ -394,8 +387,8 @@ void Avatar::simulate(float deltaTime) { } // If another avatar is near, dampen velocity as a function of closeness - if (_isMine && (_distanceToNearestAvatar < AVATAR_BRAKING_RANGE)) { - float closeness = 1.0f - (_distanceToNearestAvatar / AVATAR_BRAKING_RANGE); + if (_isMine && (_distanceToNearestAvatar < PERIPERSONAL_RADIUS)) { + float closeness = 1.0f - (_distanceToNearestAvatar / PERIPERSONAL_RADIUS); float drag = 1.0f - closeness * AVATAR_BRAKING_STRENGTH * deltaTime; if ( drag > 0.0f ) { _velocity *= drag; @@ -443,16 +436,16 @@ void Avatar::simulate(float deltaTime) { _joint[ AVATAR_JOINT_HEAD_BASE ].radius ); + _head.setBodyYaw(_bodyYaw); + //the following is still being prototyped (making the eyes look at a specific location), it should be finished by 5/20/13 - _head.setLooking(false); - /* if (_interactingOther) { _head.setLooking(true); _head.setLookatPosition(_interactingOther->getSpringyHeadPosition()); +//_head.setLookatPosition(_interactingOther->getApproximateEyePosition()); } else { _head.setLooking(false); } - */ _head.setAudioLoudness(_audioLoudness); _head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2])); @@ -523,7 +516,10 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { float distance = glm::length(v); if (distance < closestDistance) { closestDistance = distance; - _interactingOther = otherAvatar; + + if (distance < PERIPERSONAL_RADIUS) { + _interactingOther = otherAvatar; + } } } } @@ -750,6 +746,7 @@ static TextRenderer* textRenderer() { void Avatar::setGravity(glm::vec3 gravity) { _gravity = gravity; + _head.setGravity(_gravity); } void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { @@ -1131,6 +1128,12 @@ const glm::vec3& Avatar::getHeadPosition() const { } +glm::vec3 Avatar::getApproximateEyePosition() { + return _head.getApproximateEyePosition(); +} + + + void Avatar::updateArmIKAndConstraints(float deltaTime) { @@ -1177,7 +1180,7 @@ void Avatar::renderBody(bool lookingInMirror) { if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case if (_displayingHead) { - _head.render(lookingInMirror, _bodyYaw); + _head.render(lookingInMirror); } } else { diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 06627adadf..a8aa40a955 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -100,6 +100,7 @@ public: void setLeanForward(float dist); void setLeanSideways(float dist); void addLean(float x, float z); + glm::vec3 getApproximateEyePosition(); const glm::vec3& getHeadPosition() const ; // get the position of the avatar's rigid body head const glm::vec3& getSpringyHeadPosition() const ; // get the springy position of the avatar's head const glm::vec3& getJointPosition(AvatarJointID j) const { return _joint[j].springyPosition; }; diff --git a/interface/src/Head.cpp b/interface/src/Head.cpp index 4c6f7df97a..89ffe8b6f9 100644 --- a/interface/src/Head.cpp +++ b/interface/src/Head.cpp @@ -13,6 +13,7 @@ using namespace std; const float HEAD_MOTION_DECAY = 0.1; +const float MINIMUM_EYE_ROTATION = 0.7f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; float _mouthColor[] = {1, 0, 0}; @@ -42,102 +43,229 @@ Head::Head() { } } +Head::Head(const Head &head) { + + yawRate = head.yawRate; + noise = head.noise; + leanForward = head.leanForward; + leanSideways = head.leanSideways; + + _sphere = NULL; + _returnHeadToCenter = head._returnHeadToCenter; + _audioLoudness = head._audioLoudness; + _skinColor = head._skinColor; + _position = head._position; + _rotation = head._rotation; + _lookatPosition = head._lookatPosition; + _leftEyePosition = head._leftEyePosition; + _rightEyePosition = head._rightEyePosition; + _yaw = head._yaw; + _pitch = head._pitch; + _roll = head._roll; + _pitchRate = head._pitchRate; + _rollRate = head._rollRate; + _eyeballPitch[0] = head._eyeballPitch[0]; + _eyeballYaw [0] = head._eyeballYaw [0]; + _eyebrowPitch[0] = head._eyebrowPitch[0]; + _eyebrowRoll [0] = head._eyebrowRoll [0]; + _eyeballPitch[1] = head._eyeballPitch[1]; + _eyeballYaw [1] = head._eyeballYaw [1]; + _eyebrowPitch[1] = head._eyebrowPitch[1]; + _eyebrowRoll [1] = head._eyebrowRoll [1]; + _eyeballScaleX = head._eyeballScaleX; + _eyeballScaleY = head._eyeballScaleY; + _eyeballScaleZ = head._eyeballScaleZ; + _interPupilDistance = head._interPupilDistance; + _interBrowDistance = head._interBrowDistance; + _nominalPupilSize = head._nominalPupilSize; + _pupilSize = head._pupilSize; + _mouthPitch = head._mouthPitch; + _mouthYaw = head._mouthYaw; + _mouthWidth = head._mouthWidth; + _mouthHeight = head._mouthHeight; + _pitchTarget = head._pitchTarget; + _yawTarget = head._yawTarget; + _noiseEnvelope = head._noiseEnvelope; + _pupilConverge = head._pupilConverge; + _scale = head._scale; + _eyeContact = head._eyeContact; + _browAudioLift = head._browAudioLift; + _eyeContactTarget = head._eyeContactTarget; + _orientation = head._orientation; + _bodyYaw = head._bodyYaw; + _lastLoudness = head._lastLoudness; + _averageLoudness = head._averageLoudness; + _audioAttack = head._audioAttack; + _looking = head._looking; + _gravity = head._gravity; + _returnSpringScale = head._returnSpringScale; +} + + + void Head::initialize() { - audioLoudness = 0.0; - skinColor = glm::vec3(0.0f, 0.0f, 0.0f); - position = glm::vec3(0.0f, 0.0f, 0.0f); - lookatPosition = glm::vec3(0.0f, 0.0f, 0.0f); - yaw = 0.0f; - pitch = 0.0f; - roll = 0.0f; - pupilSize = 0.10; - interPupilDistance = 0.6; - interBrowDistance = 0.75; - nominalPupilSize = 0.10; - pitchRate = 0.0; - yawRate = 0.0; - rollRate = 0.0; - eyebrowPitch[0] = -30; - eyebrowPitch[1] = -30; - eyebrowRoll [0] = 20; - eyebrowRoll [1] = -20; - mouthPitch = 0; - mouthYaw = 0; - mouthWidth = 1.0; - mouthHeight = 0.2; - eyeballPitch[0] = 0; - eyeballPitch[1] = 0; - eyeballScaleX = 1.2; - eyeballScaleY = 1.5; - eyeballScaleZ = 1.0; - eyeballYaw[0] = 0; - eyeballYaw[1] = 0; - pitchTarget = 0; - yawTarget = 0; - noiseEnvelope = 1.0; - pupilConverge = 10.0; - leanForward = 0.0; - leanSideways = 0.0; - eyeContact = 1; - eyeContactTarget = LEFT_EYE; - scale = 1.0; - audioAttack = 0.0; - averageLoudness = 0.0; - lastLoudness = 0.0; - browAudioLift = 0.0; - noise = 0; - returnSpringScale = 1.0; - sphere = NULL; + _bodyYaw = 0.0f; + _audioLoudness = 0.0; + _skinColor = glm::vec3(0.0f, 0.0f, 0.0f); + _position = glm::vec3(0.0f, 0.0f, 0.0f); + _lookatPosition = glm::vec3(0.0f, 0.0f, 0.0f); + _gravity = glm::vec3(0.0f, -1.0f, 0.0f); // default + _yaw = 0.0f; + _pitch = 0.0f; + _roll = 0.0f; + _pupilSize = 0.10; + _interPupilDistance = 0.6; + _interBrowDistance = 0.75; + _nominalPupilSize = 0.10; + _pitchRate = 0.0; + yawRate = 0.0; + _rollRate = 0.0; + _eyebrowPitch[0] = -30; + _eyebrowPitch[1] = -30; + _eyebrowRoll [0] = 20; + _eyebrowRoll [1] = -20; + _mouthPitch = 0; + _mouthYaw = 0; + _mouthWidth = 1.0; + _mouthHeight = 0.2; + _eyeballPitch[0] = 0; + _eyeballPitch[1] = 0; + _eyeballScaleX = 1.2; + _eyeballScaleY = 1.5; + _eyeballScaleZ = 1.0; + _eyeballYaw[0] = 0; + _eyeballYaw[1] = 0; + _pitchTarget = 0; + _yawTarget = 0; + _noiseEnvelope = 1.0; + _pupilConverge = 10.0; + leanForward = 0.0; + leanSideways = 0.0; + _eyeContact = 1; + _eyeContactTarget = LEFT_EYE; + _scale = 1.0; + _audioAttack = 0.0; + _averageLoudness = 0.0; + _lastLoudness = 0.0; + _browAudioLift = 0.0; + noise = 0; + _returnSpringScale = 1.0; + _sphere = NULL; } +/* +void Head::copyFromHead(const Head &head) { + + returnHeadToCenter = head.returnHeadToCenter; + audioLoudness = head.audioLoudness; + skinColor = head.skinColor; + position = head.position; + rotation = head.rotation; + lookatPosition = head.lookatPosition; + _leftEyePosition = head._leftEyePosition; + _rightEyePosition = head._rightEyePosition; + yaw = head.yaw; + pitch = head.pitch; + roll = head.roll; + pitchRate = head.pitchRate; + yawRate = head.yawRate; + rollRate = head.rollRate; + noise = head.noise; + eyeballPitch[0] = head.eyeballPitch[0]; + eyeballYaw [0] = head.eyeballYaw [0]; + eyebrowPitch[0] = head.eyebrowPitch[0]; + eyebrowRoll [0] = head.eyebrowRoll [0]; + eyeballPitch[1] = head.eyeballPitch[1]; + eyeballYaw [1] = head.eyeballYaw [1]; + eyebrowPitch[1] = head.eyebrowPitch[1]; + eyebrowRoll [1] = head.eyebrowRoll [1]; + eyeballScaleX = head.eyeballScaleX; + eyeballScaleY = head.eyeballScaleY; + eyeballScaleZ = head.eyeballScaleZ; + interPupilDistance = head.interPupilDistance; + interBrowDistance = head.interBrowDistance; + nominalPupilSize = head.nominalPupilSize; + pupilSize = head.pupilSize; + mouthPitch = head.mouthPitch; + mouthYaw = head.mouthYaw; + mouthWidth = head.mouthWidth; + mouthHeight = head.mouthHeight; + leanForward = head.leanForward; + leanSideways = head.leanSideways; + pitchTarget = head.pitchTarget; + yawTarget = head.yawTarget; + noiseEnvelope = head.noiseEnvelope; + pupilConverge = head.pupilConverge; + scale = head.scale; + eyeContact = head.eyeContact; + browAudioLift = head.browAudioLift; + eyeContactTarget = head.eyeContactTarget; + _orientation = head._orientation; + _bodyYaw = head._bodyYaw; + lastLoudness = head.lastLoudness; + averageLoudness = head.averageLoudness; + audioAttack = head.audioAttack; + _looking = head._looking; + _gravity = head._gravity; + sphere = head.sphere; + returnSpringScale = head.returnSpringScale; +} +*/ + void Head::setPositionRotationAndScale(glm::vec3 p, glm::vec3 r, float s) { - position = p; - scale = s; - yaw = r.x; - pitch = r.y; - roll = r.z; + _position = p; + _scale = s; + _yaw = r.x; + _pitch = r.y; + _roll = r.z; } void Head::setSkinColor(glm::vec3 c) { - skinColor = c; + _skinColor = c; } void Head::setAudioLoudness(float loudness) { - audioLoudness = loudness; + _audioLoudness = loudness; } void Head::setNewTarget(float pitch, float yaw) { - pitchTarget = pitch; - yawTarget = yaw; + _pitchTarget = pitch; + _yawTarget = yaw; } void Head::simulate(float deltaTime, bool isMine) { + //generate orientation directions based on Euler angles... + _orientation.setToPitchYawRoll( _pitch, _bodyYaw + _yaw, _roll); + + //calculate the eye positions (algorithm still being designed) + updateEyePositions(); + // Decay head back to center if turned on - if (isMine && returnHeadToCenter) { + if (isMine && _returnHeadToCenter) { // Decay back toward center - pitch *= (1.0f - HEAD_MOTION_DECAY * returnSpringScale * 2 * deltaTime); - yaw *= (1.0f - HEAD_MOTION_DECAY * returnSpringScale * 2 * deltaTime); - roll *= (1.0f - HEAD_MOTION_DECAY * returnSpringScale * 2 * deltaTime); + _pitch *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime); + _yaw *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime); + _roll *= (1.0f - HEAD_MOTION_DECAY * _returnSpringScale * 2 * deltaTime); } // For invensense gyro, decay only slightly when roughly centered if (isMine) { const float RETURN_RANGE = 15.0; const float RETURN_STRENGTH = 2.0; - 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); } + 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); } } if (noise) { // Move toward new target - pitch += (pitchTarget - pitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; - yaw += (yawTarget - yaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime); - roll *= 1.f - (HEAD_MOTION_DECAY * deltaTime); + _pitch += (_pitchTarget - _pitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ; + _yaw += (_yawTarget - _yaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime); + _roll *= 1.f - (HEAD_MOTION_DECAY * deltaTime); } leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime); @@ -147,12 +275,12 @@ void Head::simulate(float deltaTime, bool isMine) { // // First, decide if we are making eye contact or not if (randFloat() < 0.005) { - eyeContact = !eyeContact; - eyeContact = 1; - if (!eyeContact) { + _eyeContact = !_eyeContact; + _eyeContact = 1; + if (!_eyeContact) { // If we just stopped making eye contact,move the eyes markedly away - eyeballPitch[0] = eyeballPitch[1] = eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10; - eyeballYaw [0] = eyeballYaw [1] = eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5; + _eyeballPitch[0] = _eyeballPitch[1] = _eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10; + _eyeballYaw [0] = _eyeballYaw [1] = _eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5; } else { // If now making eye contact, turn head to look right at viewer setNewTarget(0,0); @@ -162,80 +290,104 @@ void Head::simulate(float deltaTime, bool isMine) { const float DEGREES_BETWEEN_VIEWER_EYES = 3; const float DEGREES_TO_VIEWER_MOUTH = 7; - if (eyeContact) { + if (_eyeContact) { // Should we pick a new eye contact target? if (randFloat() < 0.01) { // Choose where to look next if (randFloat() < 0.1) { - eyeContactTarget = MOUTH; + _eyeContactTarget = MOUTH; } else { - if (randFloat() < 0.5) eyeContactTarget = LEFT_EYE; else eyeContactTarget = RIGHT_EYE; + if (randFloat() < 0.5) _eyeContactTarget = LEFT_EYE; else _eyeContactTarget = RIGHT_EYE; } } // Set eyeball pitch and yaw to make contact float eye_target_yaw_adjust = 0; float eye_target_pitch_adjust = 0; - if (eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; - if (eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; - if (eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; + if (_eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES; + if (_eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES; + if (_eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH; - eyeballPitch[0] = eyeballPitch[1] = -pitch + eye_target_pitch_adjust; - eyeballYaw [0] = eyeballYaw [1] = yaw + eye_target_yaw_adjust; + _eyeballPitch[0] = _eyeballPitch[1] = -_pitch + eye_target_pitch_adjust; + _eyeballYaw [0] = _eyeballYaw [1] = _yaw + eye_target_yaw_adjust; } if (noise) { - pitch += (randFloat() - 0.5) * 0.2 * noiseEnvelope; - yaw += (randFloat() - 0.5) * 0.3 *noiseEnvelope; + _pitch += (randFloat() - 0.5) * 0.2 * _noiseEnvelope; + _yaw += (randFloat() - 0.5) * 0.3 *_noiseEnvelope; //PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope; - if (randFloat() < 0.005) mouthWidth = _MouthWidthChoices[rand()%3]; + if (randFloat() < 0.005) _mouthWidth = _MouthWidthChoices[rand()%3]; - if (!eyeContact) { - if (randFloat() < 0.01) eyeballPitch[0] = eyeballPitch[1] = (randFloat() - 0.5) * 20; - if (randFloat() < 0.01) eyeballYaw[0] = eyeballYaw[1] = (randFloat()- 0.5) * 10; + if (!_eyeContact) { + if (randFloat() < 0.01) _eyeballPitch[0] = _eyeballPitch[1] = (randFloat() - 0.5) * 20; + if (randFloat() < 0.01) _eyeballYaw[0] = _eyeballYaw[1] = (randFloat()- 0.5) * 10; } - if ((randFloat() < 0.005) && (fabs(pitchTarget - pitch) < 1.0) && (fabs(yawTarget - yaw) < 1.0)) { + if ((randFloat() < 0.005) && (fabs(_pitchTarget - _pitch) < 1.0) && (fabs(_yawTarget - _yaw) < 1.0)) { setNewTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0); } if (0) { // Pick new target - pitchTarget = (randFloat() - 0.5) * 45; - yawTarget = (randFloat() - 0.5) * 22; + _pitchTarget = (randFloat() - 0.5) * 45; + _yawTarget = (randFloat() - 0.5) * 22; } if (randFloat() < 0.01) { - eyebrowPitch[0] = eyebrowPitch[1] = _BrowPitchAngle[rand()%3]; - eyebrowRoll [0] = eyebrowRoll[1] = _BrowRollAngle[rand()%5]; - eyebrowRoll [1] *=-1; + _eyebrowPitch[0] = _eyebrowPitch[1] = _BrowPitchAngle[rand()%3]; + _eyebrowRoll [0] = _eyebrowRoll[1] = _BrowRollAngle[rand()%5]; + _eyebrowRoll [1] *=-1; } } // Update audio trailing average for rendering facial animations const float AUDIO_AVERAGING_SECS = 0.05; - averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * averageLoudness + - (deltaTime / AUDIO_AVERAGING_SECS) * audioLoudness; + _averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _averageLoudness + + (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; } -void Head::setLooking(bool l) { - _looking = l; +void Head::updateEyePositions() { + float rightShift = _scale * 0.27f; + float upShift = _scale * 0.38f; + float frontShift = _scale * 0.8f; + + _leftEyePosition = _position + _orientation.getRight() * rightShift + + _orientation.getUp () * upShift + + _orientation.getFront() * frontShift; + _rightEyePosition = _position - _orientation.getRight() * rightShift + + _orientation.getUp () * upShift + + _orientation.getFront() * frontShift; } +void Head::setLooking(bool looking) { + + _looking = looking; + + glm::vec3 averagEyePosition = _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; + glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - averagEyePosition); + + float dot = glm::dot(targetLookatAxis, _orientation.getFront()); + if (dot < MINIMUM_EYE_ROTATION) { + _looking = false; + } +} void Head::setLookatPosition(glm::vec3 l) { - lookatPosition = l; + _lookatPosition = l; } +void Head::setGravity(glm::vec3 gravity) { + _gravity = gravity; +} +glm::vec3 Head::getApproximateEyePosition() { + return _leftEyePosition + (_rightEyePosition - _leftEyePosition) * ONE_HALF; +} -void Head::render(bool lookingInMirror, float bodyYaw) { - - -//float a = angleBetween( &position, &position); +void Head::render(bool lookingInMirror) { int side = 0; @@ -244,22 +396,22 @@ void Head::render(bool lookingInMirror, float bodyYaw) { glPushMatrix(); - glTranslatef(position.x, position.y, position.z); + glTranslatef(_position.x, _position.y, _position.z); - glScalef(scale, scale, scale); + glScalef(_scale, _scale, _scale); if (lookingInMirror) { - glRotatef(bodyYaw - yaw, 0, 1, 0); - glRotatef(pitch, 1, 0, 0); - glRotatef(-roll, 0, 0, 1); + glRotatef(_bodyYaw - _yaw, 0, 1, 0); + glRotatef(_pitch, 1, 0, 0); + glRotatef(-_roll, 0, 0, 1); } else { - glRotatef(bodyYaw + yaw, 0, 1, 0); - glRotatef(pitch, 1, 0, 0); - glRotatef(roll, 0, 0, 1); + glRotatef(_bodyYaw + _yaw, 0, 1, 0); + glRotatef(_pitch, 1, 0, 0); + glRotatef(_roll, 0, 0, 1); } //glScalef(2.0, 2.0, 2.0); - glColor3f(skinColor.x, skinColor.y, skinColor.z); + glColor3f(_skinColor.x, _skinColor.y, _skinColor.z); glutSolidSphere(1, 30, 30); @@ -276,28 +428,28 @@ void Head::render(bool lookingInMirror, float bodyYaw) { glPopMatrix(); // Update audio attack data for facial animation (eyebrows and mouth) - audioAttack = 0.9 * audioAttack + 0.1 * fabs(audioLoudness - lastLoudness); - lastLoudness = audioLoudness; + _audioAttack = 0.9 * _audioAttack + 0.1 * fabs(_audioLoudness - _lastLoudness); + _lastLoudness = _audioLoudness; const float BROW_LIFT_THRESHOLD = 100; - if (audioAttack > BROW_LIFT_THRESHOLD) - browAudioLift += sqrt(audioAttack) / 1000.0; + if (_audioAttack > BROW_LIFT_THRESHOLD) + _browAudioLift += sqrt(_audioAttack) / 1000.0; - browAudioLift *= .90; + _browAudioLift *= .90; // Render Eyebrows glPushMatrix(); - glTranslatef(-interBrowDistance / 2.0,0.4,0.45); + glTranslatef(-_interBrowDistance / 2.0,0.4,0.45); for(side = 0; side < 2; side++) { glColor3fv(_browColor); glPushMatrix(); - glTranslatef(0, 0.35 + browAudioLift, 0); - glRotatef(eyebrowPitch[side]/2.0, 1, 0, 0); - glRotatef(eyebrowRoll[side]/2.0, 0, 0, 1); + glTranslatef(0, 0.35 + _browAudioLift, 0); + glRotatef(_eyebrowPitch[side]/2.0, 1, 0, 0); + glRotatef(_eyebrowRoll[side]/2.0, 0, 0, 1); glScalef(_browWidth, _browThickness, 1); glutSolidCube(0.5); glPopMatrix(); - glTranslatef(interBrowDistance, 0, 0); + glTranslatef(_interBrowDistance, 0, 0); } glPopMatrix(); @@ -306,184 +458,188 @@ void Head::render(bool lookingInMirror, float bodyYaw) { glTranslatef(0,-0.35,0.75); glColor3f(0,0,0); - glRotatef(mouthPitch, 1, 0, 0); - glRotatef(mouthYaw, 0, 0, 1); + glRotatef(_mouthPitch, 1, 0, 0); + glRotatef(_mouthYaw, 0, 0, 1); - if (averageLoudness > 1.f) { - glScalef(mouthWidth * (.7f + sqrt(averageLoudness) /60.f), - mouthHeight * (1.f + sqrt(averageLoudness) /30.f), 1); + if (_averageLoudness > 1.f) { + glScalef(_mouthWidth * (.7f + sqrt(_averageLoudness) /60.f), + _mouthHeight * (1.f + sqrt(_averageLoudness) /30.f), 1); } else { - glScalef(mouthWidth, mouthHeight, 1); + glScalef(_mouthWidth, _mouthHeight, 1); } glutSolidCube(0.5); glPopMatrix(); - - renderEyeBalls(); + + // the original code from Philip's implementation + //previouseRenderEyeBalls(); glPopMatrix(); + //a new version of eyeballs that has the ability to look at specific targets in the world (algo still not finished yet) + renderEyeBalls(); + if (_looking) { - //the irises are special - they have the ability to look at specific targets in the world (code still not finished yet) - renderIrises(bodyYaw + yaw); + // Render lines originating from the eyes and converging on the lookatPosition + debugRenderLookatVectors(_leftEyePosition, _rightEyePosition, _lookatPosition); } } -void Head::renderEyeBalls() { + +void Head::renderEyeBalls() { + + //make the texture for the iris... + if (_sphere == NULL) { + _sphere = gluNewQuadric(); + gluQuadricTexture(_sphere, GL_TRUE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluQuadricOrientation(_sphere, GLU_OUTSIDE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); + } + + // left eyeball + glPushMatrix(); + glColor3fv(_eyeColor); + glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); + gluSphere(_sphere, 0.02, 30, 30); + glPopMatrix(); + + // left iris + glPushMatrix(); { + glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); + glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - _leftEyePosition); + + if (!_looking) { + targetLookatAxis = _orientation.getFront(); + } + + glPushMatrix(); + glm::vec3 rotationAxis = glm::cross(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f)); + float angle = 180.0f - angleBetween(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f)); + + //glm::vec3 U_rotationAxis = glm::vec3(0.0f, 0.0f, 1.0f); + //float U_angle = angleBetween(_orientation.getFront(), glm::vec3(1.0f, 0.0f, 0.0f)); + //glRotatef(U_angle, U_rotationAxis.x, U_rotationAxis.y, U_rotationAxis.z); + glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); + + glTranslatef( 0.0f, -0.018f, 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(_sphere, 0.007, 15, 15); + glDisable(GL_TEXTURE_2D); + glPopMatrix(); + } + glPopMatrix(); + + //right eyeball + glPushMatrix(); + glColor3fv(_eyeColor); + glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); + gluSphere(_sphere, 0.02, 30, 30); + glPopMatrix(); + + //right iris + glPushMatrix(); { + glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); + glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - _rightEyePosition); + + if (!_looking) { + targetLookatAxis = _orientation.getFront(); + } + + glPushMatrix(); + glm::vec3 rotationAxis = glm::cross(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f)); + float angle = 180.0f - angleBetween(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f)); + glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); + glTranslatef( 0.0f, -0.018f, 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(_sphere, 0.007, 15, 15); + glDisable(GL_TEXTURE_2D); + glPopMatrix(); + } + glPopMatrix(); +} + + + + + +void Head::previouseRenderEyeBalls() { glTranslatef(0, 1.0, 0); - glTranslatef(-interPupilDistance/2.0,-0.68,0.7); + glTranslatef(-_interPupilDistance/2.0,-0.68,0.7); // Right Eye glRotatef(-10, 1, 0, 0); glColor3fv(_eyeColor); glPushMatrix(); { - glTranslatef(interPupilDistance/10.0, 0, 0.05); + glTranslatef(_interPupilDistance/10.0, 0, 0.05); glRotatef(20, 0, 0, 1); - glScalef(eyeballScaleX, eyeballScaleY, eyeballScaleZ); + glScalef(_eyeballScaleX, _eyeballScaleY, _eyeballScaleZ); glutSolidSphere(0.25, 30, 30); } glPopMatrix(); - if (!_looking) { - // Right Pupil - if (sphere == NULL) { - sphere = gluNewQuadric(); - gluQuadricTexture(sphere, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluQuadricOrientation(sphere, GLU_OUTSIDE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); - } - - glPushMatrix(); - { - glRotatef(eyeballPitch[1], 1, 0, 0); - glRotatef(eyeballYaw[1] + yaw + pupilConverge, 0, 1, 0); - glTranslatef(0,0,.35); - glRotatef(-75,1,0,0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(sphere, pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - glPopMatrix(); + // Right Pupil + if (_sphere == NULL) { + _sphere = gluNewQuadric(); + gluQuadricTexture(_sphere, GL_TRUE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gluQuadricOrientation(_sphere, GLU_OUTSIDE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); } + glPushMatrix(); + { + glRotatef(_eyeballPitch[1], 1, 0, 0); + glRotatef(_eyeballYaw[1] + _yaw + _pupilConverge, 0, 1, 0); + glTranslatef(0,0,.35); + glRotatef(-75,1,0,0); + glScalef(1.0, 0.4, 1.0); + + glEnable(GL_TEXTURE_2D); + gluSphere(_sphere, _pupilSize, 15, 15); + glDisable(GL_TEXTURE_2D); + } + glPopMatrix(); + // Left Eye glColor3fv(_eyeColor); - glTranslatef(interPupilDistance, 0, 0); + glTranslatef(_interPupilDistance, 0, 0); glPushMatrix(); { - glTranslatef(-interPupilDistance/10.0, 0, .05); + glTranslatef(-_interPupilDistance/10.0, 0, .05); glRotatef(-20, 0, 0, 1); - glScalef(eyeballScaleX, eyeballScaleY, eyeballScaleZ); + glScalef(_eyeballScaleX, _eyeballScaleY, _eyeballScaleZ); glutSolidSphere(0.25, 30, 30); } glPopMatrix(); - if (!_looking) { - // Left Pupil - glPushMatrix(); - { - glRotatef(eyeballPitch[0], 1, 0, 0); - glRotatef(eyeballYaw[0] + yaw - pupilConverge, 0, 1, 0); - glTranslatef(0, 0, .35); - glRotatef(-75, 1, 0, 0); - glScalef(1.0, 0.4, 1.0); - - glEnable(GL_TEXTURE_2D); - gluSphere(sphere, pupilSize, 15, 15); - glDisable(GL_TEXTURE_2D); - } - glPopMatrix(); - } -} - - -//--------------------------------------------------------- -// the code below is still in the prototyping stages.... -//--------------------------------------------------------- -void Head::renderIrises(float yaw) { - - Orientation orientation; - orientation.setToPitchYawRoll( pitch, yaw, roll); - - float rightShift = scale * 0.22f; - float upShift = scale * 0.38f; - float frontShift = scale * 0.9f; - - glm::vec3 leftEyePosition = position + orientation.getRight() * rightShift - + orientation.getUp () * upShift - + orientation.getFront() * frontShift; - glm::vec3 rightEyePosition = position - orientation.getRight() * rightShift - + orientation.getUp () * upShift - + orientation.getFront() * frontShift; - - // Render lines originating from the eyes and converging on the lookatPosition - debugRenderLookatVectors(leftEyePosition, rightEyePosition, lookatPosition); - - glColor3fv(_eyeColor); - - //make the texture for the iris sphere... - if (sphere == NULL) { - sphere = gluNewQuadric(); - gluQuadricTexture(sphere, GL_TRUE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluQuadricOrientation(sphere, GLU_OUTSIDE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]); - } - - //render left iris - glPushMatrix(); { - glTranslatef(leftEyePosition.x, leftEyePosition.y, leftEyePosition.z); - glm::vec3 targetLookatAxis = glm::normalize(lookatPosition - leftEyePosition); + // Left Pupil + glPushMatrix(); + { + glRotatef(_eyeballPitch[0], 1, 0, 0); + glRotatef(_eyeballYaw[0] + _yaw - _pupilConverge, 0, 1, 0); + glTranslatef(0, 0, .35); + glRotatef(-75, 1, 0, 0); + glScalef(1.0, 0.4, 1.0); - glPushMatrix(); - glm::vec3 pitchRotationAxis = glm::cross(targetLookatAxis, orientation.getRight()); - glm::vec3 yawRotationAxis = glm::cross(targetLookatAxis, orientation.getUp()); - - float yaw = angleBetween(targetLookatAxis, orientation.getUp()); - float pitch = angleBetween(targetLookatAxis, orientation.getRight()); - - glRotatef(yaw, yawRotationAxis.x, yawRotationAxis.y, yawRotationAxis.z); - glRotatef(pitch, pitchRotationAxis.x, pitchRotationAxis.y, pitchRotationAxis.z); - glEnable(GL_TEXTURE_2D); - gluSphere(sphere, 0.01, 15, 15); - glDisable(GL_TEXTURE_2D); - glPopMatrix(); - } - glPopMatrix(); - - //render right iris - glPushMatrix(); { - glTranslatef(rightEyePosition.x, rightEyePosition.y, rightEyePosition.z); - glm::vec3 targetLookatAxis = glm::normalize(lookatPosition - rightEyePosition); - - glPushMatrix(); - glm::vec3 pitchRotationAxis = glm::cross(targetLookatAxis, orientation.getRight()); - glm::vec3 yawRotationAxis = glm::cross(targetLookatAxis, orientation.getUp()); - - float yaw = angleBetween(targetLookatAxis, orientation.getUp()); - float pitch = angleBetween(targetLookatAxis, orientation.getRight()); - - glRotatef(yaw, yawRotationAxis.x, yawRotationAxis.y, yawRotationAxis.z); - glRotatef(pitch, pitchRotationAxis.x, pitchRotationAxis.y, pitchRotationAxis.z); - glEnable(GL_TEXTURE_2D); - gluSphere(sphere, 0.01, 15, 15); - glDisable(GL_TEXTURE_2D); - glPopMatrix(); + glEnable(GL_TEXTURE_2D); + gluSphere(_sphere, _pupilSize, 15, 15); + glDisable(GL_TEXTURE_2D); } glPopMatrix(); } + void Head::debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { glColor3f(0.0f, 0.0f, 0.0f); diff --git a/interface/src/Head.h b/interface/src/Head.h index 9d6e84ce7d..bf1a5426de 100644 --- a/interface/src/Head.h +++ b/interface/src/Head.h @@ -22,80 +22,98 @@ class Head { public: Head(); + Head(const Head &otherHead); + void initialize(); void simulate(float deltaTime, bool isMine); void setPositionRotationAndScale(glm::vec3 position, glm::vec3 rotation, float scale); void setSkinColor(glm::vec3 color); void setAudioLoudness(float loudness); - void render(bool lookingInMirror, float bodyYaw); + void render(bool lookingInMirror); void setNewTarget(float, float); - void setSpringScale(float s) { returnSpringScale = s; } + void setSpringScale(float s) { _returnSpringScale = s; } void setLookatPosition(glm::vec3 lookatPosition); void setLooking(bool looking); + void setGravity(glm::vec3 gravity); + void setBodyYaw(float y) { _bodyYaw = y; } + void copyFromHead(const Head &head); + + glm::vec3 getApproximateEyePosition(); // Do you want head to try to return to center (depends on interface detected) - void setReturnToCenter(bool r) { returnHeadToCenter = r; } - const bool getReturnToCenter() const { return returnHeadToCenter; } + void setReturnToCenter(bool r) { _returnHeadToCenter = r; } + const bool getReturnToCenter() const { return _returnHeadToCenter; } - float getAverageLoudness() {return averageLoudness;}; - void setAverageLoudness(float al) { averageLoudness = al;}; + float getAverageLoudness() {return _averageLoudness;}; + void setAverageLoudness(float al) { _averageLoudness = al;}; - bool returnHeadToCenter; - float audioLoudness; - glm::vec3 skinColor; - glm::vec3 position; - glm::vec3 rotation; - glm::vec3 lookatPosition; - float yaw; - float pitch; - float roll; - float pitchRate; float yawRate; - float rollRate; float noise; - float eyeballPitch[2]; - float eyeballYaw [2]; - float eyebrowPitch[2]; - float eyebrowRoll [2]; - float eyeballScaleX; - float eyeballScaleY; - float eyeballScaleZ; - float interPupilDistance; - float interBrowDistance; - float nominalPupilSize; - float pupilSize; - float mouthPitch; - float mouthYaw; - float mouthWidth; - float mouthHeight; float leanForward; float leanSideways; - float pitchTarget; - float yawTarget; - float noiseEnvelope; - float pupilConverge; - float scale; - int eyeContact; - float browAudioLift; - eyeContactTargets eyeContactTarget; + +private: + + bool _returnHeadToCenter; + float _audioLoudness; + glm::vec3 _skinColor; + glm::vec3 _position; + glm::vec3 _rotation; + glm::vec3 _lookatPosition; + + glm::vec3 _leftEyePosition; + glm::vec3 _rightEyePosition; + + float _yaw; + float _pitch; + float _roll; + float _pitchRate; + float _rollRate; + float _eyeballPitch[2]; + float _eyeballYaw [2]; + float _eyebrowPitch[2]; + float _eyebrowRoll [2]; + float _eyeballScaleX; + float _eyeballScaleY; + float _eyeballScaleZ; + float _interPupilDistance; + float _interBrowDistance; + float _nominalPupilSize; + float _pupilSize; + float _mouthPitch; + float _mouthYaw; + float _mouthWidth; + float _mouthHeight; + float _pitchTarget; + float _yawTarget; + float _noiseEnvelope; + float _pupilConverge; + float _scale; + int _eyeContact; + float _browAudioLift; + eyeContactTargets _eyeContactTarget; + Orientation _orientation; + float _bodyYaw; // Sound loudness information - float lastLoudness; - float averageLoudness; - float audioAttack; + float _lastLoudness; + float _averageLoudness; + float _audioAttack; bool _looking; + glm::vec3 _gravity; + - GLUquadric* sphere; + GLUquadric* _sphere; // Strength of return springs - float returnSpringScale; + float _returnSpringScale; -private: + // private methods + void previouseRenderEyeBalls(); void renderEyeBalls(); - void renderIrises(float yaw); void debugRenderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition); - + void updateEyePositions(); }; #endif