diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 81a1ba3e14..1d586f8868 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2001,7 +2001,11 @@ void Application::updateMyAvatarLookAtPosition() { if (!OculusManager::isConnected()) { lookAtSpot = _myCamera.getPosition(); } else { - lookAtSpot = OculusManager::getLeftEyePosition(); + if (_myAvatar->isLookingAtLeftEye()) { + lookAtSpot = OculusManager::getLeftEyePosition(); + } else { + lookAtSpot = OculusManager::getRightEyePosition(); + } } } else { @@ -2011,7 +2015,7 @@ void Application::updateMyAvatarLookAtPosition() { isLookingAtSomeone = true; // If I am looking at someone else, look directly at one of their eyes if (tracker) { - // If tracker active, look at the eye for the side my gaze is biased toward + // If a face tracker is active, look at the eye for the side my gaze is biased toward if (tracker->getEstimatedEyeYaw() > _myAvatar->getHead()->getFinalYaw()) { // Look at their right eye lookAtSpot = static_cast(lookingAt.data())->getHead()->getRightEyePosition(); @@ -2021,7 +2025,11 @@ void Application::updateMyAvatarLookAtPosition() { } } else { // Need to add randomly looking back and forth between left and right eye for case with no tracker - lookAtSpot = static_cast(lookingAt.data())->getHead()->getEyePosition(); + if (_myAvatar->isLookingAtLeftEye()) { + lookAtSpot = static_cast(lookingAt.data())->getHead()->getLeftEyePosition(); + } else { + lookAtSpot = static_cast(lookingAt.data())->getHead()->getRightEyePosition(); + } } } else { // I am not looking at anyone else, so just look forward diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 9c41cf8084..85e771d3dd 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -110,7 +110,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { bool forceBlink = false; const float TALKING_LOUDNESS = 100.0f; const float BLINK_AFTER_TALKING = 0.25f; - if (_averageLoudness > TALKING_LOUDNESS) { + if ((_averageLoudness - _longTermAverageLoudness) > TALKING_LOUDNESS) { _timeWithoutTalking = 0.0f; } else if (_timeWithoutTalking < BLINK_AFTER_TALKING && (_timeWithoutTalking += deltaTime) >= BLINK_AFTER_TALKING) { @@ -128,16 +128,23 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _browAudioLift = glm::clamp(_browAudioLift *= 0.7f, 0.0f, 1.0f); const float BLINK_SPEED = 10.0f; + const float BLINK_SPEED_VARIABILITY = 1.0f; + const float BLINK_START_VARIABILITY = 0.25f; const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { // no blinking when brows are raised; blink less with increasing loudness const float BASE_BLINK_RATE = 15.0f / 60.0f; const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f; - if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(_averageLoudness) * + if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { - _leftEyeBlinkVelocity = BLINK_SPEED; - _rightEyeBlinkVelocity = BLINK_SPEED; + _leftEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + _rightEyeBlinkVelocity = BLINK_SPEED + randFloat() * BLINK_SPEED_VARIABILITY; + if (randFloat() < 0.5f) { + _leftEyeBlink = BLINK_START_VARIABILITY; + } else { + _rightEyeBlink = BLINK_START_VARIABILITY; + } } } else { _leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, FULLY_OPEN, FULLY_CLOSED); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 012c4560cf..b4fbadeaa9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -86,7 +86,8 @@ MyAvatar::MyAvatar() : _shouldRender(true), _billboardValid(false), _physicsSimulation(), - _voxelShapeManager() + _voxelShapeManager(), + _isLookingAtLeftEye(true) { ShapeCollider::initDispatchTable(); for (int i = 0; i < MAX_DRIVE_KEYS; i++) { @@ -997,6 +998,14 @@ void MyAvatar::clearLookAtTargetAvatar() { _lookAtTargetAvatar.clear(); } +bool MyAvatar::isLookingAtLeftEye() { + float const CHANCE_OF_CHANGING_EYE = 0.01f; + if (randFloat() < CHANCE_OF_CHANGING_EYE) { + _isLookingAtLeftEye = !_isLookingAtLeftEye; + } + return _isLookingAtLeftEye; +} + glm::vec3 MyAvatar::getUprightHeadPosition() const { return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e38f3f4b2b..14b3ea9924 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -105,6 +105,8 @@ public: void jump() { _shouldJump = true; }; bool isMyAvatar() { return true; } + + bool isLookingAtLeftEye(); virtual int parseDataAtOffset(const QByteArray& packet, int offset); @@ -229,6 +231,8 @@ private: QList _animationHandles; PhysicsSimulation _physicsSimulation; VoxelShapeManager _voxelShapeManager; + + bool _isLookingAtLeftEye; RecorderPointer _recorder; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 8fc17ee4d6..5f5a5650c9 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -352,12 +352,14 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p _camera->setTargetPosition(position + trackerPosition); // Store the latest left and right eye render locations for things that need to know + glm::vec3 thisEyePosition = position + trackerPosition + + (bodyOrientation * glm::quat(orientation.x, orientation.y, orientation.z, orientation.w) * + glm::vec3(_eyeRenderDesc[eye].ViewAdjust.x, _eyeRenderDesc[eye].ViewAdjust.y, _eyeRenderDesc[eye].ViewAdjust.z)); + if (eyeIndex == 0) { - //_leftEyePosition = position + trackerPosition; - glm::vec3 leftEye = position + trackerPosition; - qDebug() << "LE: " << leftEye.x << ", " << leftEye.y << ", " << leftEye.z; + _leftEyePosition = thisEyePosition; } else { - whichCamera.setRightEyePosition(position + trackerPosition); + _rightEyePosition = thisEyePosition; } _camera->update(1.0f / Application::getInstance()->getFps());