diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4e7b8a07f1..4fba110547 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -6593,18 +6593,18 @@ void MyAvatar::updateEyesLookAtPosition(float deltaTime) { // A script has set the eye rotations, so use these to set lookAtSpot glm::quat leftEyeRotation = getAbsoluteJointRotationInObjectFrame(leftEyeJointIndex); glm::quat rightEyeRotation = getAbsoluteJointRotationInObjectFrame(rightEyeJointIndex); - glm::vec3 leftVec = getWorldOrientation() * leftEyeRotation * IDENTITY_FORWARD; - glm::vec3 rightVec = getWorldOrientation() * rightEyeRotation * IDENTITY_FORWARD; + glm::vec3 leftVec = getWorldOrientation() * leftEyeRotation * Vectors::UNIT_Z; + glm::vec3 rightVec = getWorldOrientation() * rightEyeRotation * Vectors::UNIT_Z; glm::vec3 leftEyePosition = myHead->getLeftEyePosition(); glm::vec3 rightEyePosition = myHead->getRightEyePosition(); float t1, t2; bool success = findClosestApproachOfLines(leftEyePosition, leftVec, rightEyePosition, rightVec, t1, t2); - if (success) { + if (success && t1 > 0 && t2 > 0) { glm::vec3 leftFocus = leftEyePosition + leftVec * t1; glm::vec3 rightFocus = rightEyePosition + rightVec * t2; lookAtSpot = (leftFocus + rightFocus) / 2.0f; // average } else { - lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 1000.0f; + lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 20.0f; } } else if (_scriptControlsEyesLookAt) { if (_scriptEyesControlTimer < MAX_LOOK_AT_TIME_SCRIPT_CONTROL) { @@ -6618,19 +6618,18 @@ void MyAvatar::updateEyesLookAtPosition(float deltaTime) { controller::Pose rightEyePose = getControllerPoseInAvatarFrame(controller::Action::RIGHT_EYE); if (leftEyePose.isValid() && rightEyePose.isValid()) { // an eye tracker is in use, set lookAtSpot from this - glm::vec3 leftVec = getWorldOrientation() * leftEyePose.rotation * glm::vec3(0.0f, 0.0f, -1.0f); - glm::vec3 rightVec = getWorldOrientation() * rightEyePose.rotation * glm::vec3(0.0f, 0.0f, -1.0f); - + glm::vec3 leftVec = getWorldOrientation() * leftEyePose.rotation * Vectors::UNIT_Z; + glm::vec3 rightVec = getWorldOrientation() * rightEyePose.rotation * Vectors::UNIT_Z; glm::vec3 leftEyePosition = myHead->getLeftEyePosition(); glm::vec3 rightEyePosition = myHead->getRightEyePosition(); float t1, t2; bool success = findClosestApproachOfLines(leftEyePosition, leftVec, rightEyePosition, rightVec, t1, t2); - if (success) { + if (success && t1 > 0 && t2 > 0) { glm::vec3 leftFocus = leftEyePosition + leftVec * t1; glm::vec3 rightFocus = rightEyePosition + rightVec * t2; lookAtSpot = (leftFocus + rightFocus) / 2.0f; // average } else { - lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 1000.0f; + lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 20.0f; } } else { // no script override, no eye tracker, so do procedural eye motion diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index 761f73ae05..ee0543fa6b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -96,18 +96,21 @@ void Head::simulate(float deltaTime) { const float BLINK_START_VARIABILITY = 0.25f; const float FULLY_OPEN = 0.0f; const float FULLY_CLOSED = 1.0f; + const float TALKING_LOUDNESS = 150.0f; + + _timeWithoutTalking += deltaTime; + if ((_averageLoudness - _longTermAverageLoudness) > TALKING_LOUDNESS) { + _timeWithoutTalking = 0.0f; + } + if (getProceduralAnimationFlag(HeadData::BlinkProceduralBlendshapeAnimation) && !getSuppressProceduralAnimationFlag(HeadData::BlinkProceduralBlendshapeAnimation)) { // handle automatic blinks // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; - const float TALKING_LOUDNESS = 150.0f; const float BLINK_AFTER_TALKING = 0.25f; - _timeWithoutTalking += deltaTime; - if ((_averageLoudness - _longTermAverageLoudness) > TALKING_LOUDNESS) { - _timeWithoutTalking = 0.0f; - } else if (_timeWithoutTalking - deltaTime < BLINK_AFTER_TALKING && _timeWithoutTalking >= BLINK_AFTER_TALKING) { + if (_timeWithoutTalking - deltaTime < BLINK_AFTER_TALKING && _timeWithoutTalking >= BLINK_AFTER_TALKING) { forceBlink = true; } if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) { @@ -151,6 +154,7 @@ void Head::simulate(float deltaTime) { } else { _rightEyeBlink = FULLY_OPEN; _leftEyeBlink = FULLY_OPEN; + updateEyeLookAt(); } // use data to update fake Faceshift blendshape coefficients diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5fe7998ecb..e670a5437a 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -376,7 +376,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent tranlationChangedSince(lastSentTime) || parentInfoChangedSince(lastSentTime)); hasHandControllers = _controllerLeftHandMatrixCache.isValid() || _controllerRightHandMatrixCache.isValid(); - hasFaceTrackerInfo = !dropFaceTracking && getHasScriptedBlendshapes() && + hasFaceTrackerInfo = !dropFaceTracking && (getHasScriptedBlendshapes() || _headData->_hasInputDrivenBlendshapes) && (sendAll || faceTrackerInfoChangedSince(lastSentTime)); hasJointData = !sendMinimum; hasJointDefaultPoseFlags = hasJointData; diff --git a/plugins/hifiOsc/src/OscPlugin.cpp b/plugins/hifiOsc/src/OscPlugin.cpp index 475691069f..788342971d 100644 --- a/plugins/hifiOsc/src/OscPlugin.cpp +++ b/plugins/hifiOsc/src/OscPlugin.cpp @@ -374,16 +374,16 @@ static int genericHandlerFunc(const char* path, const char* types, lo_arg** argv // map /ELR to left eye rot if (path[0] == '/' && path[1] == 'E' && path[2] == 'L' && path[3] == 'R' && types[0] == 'f' && types[1] == 'f') { - glm::vec3 euler(-argv[0]->f, -argv[1]->f, 0.0f); - container->_eyeLeftRot = glm::quat(glm::radians(euler)) * Quaternions::Y_180; + glm::vec3 euler(argv[0]->f, -argv[1]->f, 0.0f); + container->_eyeLeftRot = container->_headRot * glm::quat(glm::radians(euler)); container->_eyeLeftRotValid = true; } // map /ERR to right eye rot if (path[0] == '/' && path[1] == 'E' && path[2] == 'R' && path[3] == 'R' && types[0] == 'f' && types[1] == 'f') { - glm::vec3 euler((float)-argv[0]->f, (float)-argv[1]->f, 0.0f); - container->_eyeRightRot = glm::quat(glm::radians(euler)) * Quaternions::Y_180; + glm::vec3 euler((float)argv[0]->f, (float)-argv[1]->f, 0.0f); + container->_eyeRightRot = container->_headRot * glm::quat(glm::radians(euler)); container->_eyeRightRotValid = true; }