diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f529f168f4..0abbd4e324 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2150,7 +2150,7 @@ static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myP const float DISTANCE_FACTOR = 3.14f; const float MY_ANGLE_FACTOR = 1.0f; const float OTHER_ANGLE_FACTOR = 1.0f; - const float OTHER_IS_TALKING_TERM = otherIsTalking ? 1.0f : 0.0f; + const float OTHER_IS_TALKING_TERM = otherIsTalking ? -1.0f : 0.0f; const float LOOKING_AT_OTHER_ALREADY_TERM = lookingAtOtherAlready ? -0.2f : 0.0f; const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; // meters @@ -2176,6 +2176,9 @@ static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myP void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) { glm::vec3 myForward = _lookAtYaw * IDENTITY_FORWARD; + if (_skeletonModel->isLoaded()) { + myForward = getHeadJointFrontVector(); + } glm::vec3 myPosition = getHead()->getEyePosition(); CameraMode mode = qApp->getCamera().getMode(); if (mode == CAMERA_MODE_FIRST_PERSON) { @@ -2189,7 +2192,7 @@ void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) { std::shared_ptr avatar = std::static_pointer_cast(avatarData); if (!avatar->isMyAvatar() && avatar->isInitialized()) { if (_forceTargetAvatarID.isNull() || avatar->getID() != _forceTargetAvatarID) { - glm::vec3 otherForward = avatar->getHead()->getForwardDirection(); + glm::vec3 otherForward = avatar->getHeadJointFrontVector(); glm::vec3 otherPosition = avatar->getHead()->getEyePosition(); const float TIME_WITHOUT_TALKING_THRESHOLD = 1.0f; bool otherIsTalking = avatar->getHead()->getTimeWithoutTalking() <= TIME_WITHOUT_TALKING_THRESHOLD; @@ -6842,11 +6845,3 @@ void MyAvatar::resetPointAt() { POINT_BLEND_LINEAR_ALPHA_NAME, POINT_ALPHA_BLENDING); } } - -void MyAvatar::setLookAtAvatarID(const QUuid& avatarID) { - if (QThread::currentThread() != thread()) { - BLOCKING_INVOKE_METHOD(this, "setLookAtAvatarID", - Q_ARG(const QUuid&, avatarID)); - } - _forceTargetAvatarID = avatarID; -} \ No newline at end of file diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d93ee776be..3f91222392 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -971,7 +971,6 @@ public: * @param {Uuid} entityID - The entity that the hand touch effect will be enabled for. */ Q_INVOKABLE void enableHandTouchForID(const QUuid& entityID); - Q_INVOKABLE void setLookAtAvatarID(const QUuid& avatarID); bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); } void setUseAdvancedMovementControls(bool useAdvancedMovementControls) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp index a9dde201af..8184804e1f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Head.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Head.cpp @@ -96,12 +96,15 @@ void Head::simulate(float deltaTime) { // 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 || forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * + if (_blinkToRetarget || forceBlink || + (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) * ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) { float randSpeedVariability = randFloat(); float eyeBlinkVelocity = BLINK_SPEED + randSpeedVariability * BLINK_SPEED_VARIABILITY; - if (_forceBlink) { + if (_blinkToRetarget) { + // Slow down by half the blink if reseting eye target eyeBlinkVelocity = 0.5f * eyeBlinkVelocity; + _blinkToRetarget = false; } _leftEyeBlinkVelocity = eyeBlinkVelocity; _rightEyeBlinkVelocity = eyeBlinkVelocity; @@ -123,7 +126,6 @@ void Head::simulate(float deltaTime) { } if (_rightEyeBlink == FULLY_CLOSED) { _rightEyeBlinkVelocity = -BLINK_SPEED; - } else if (_rightEyeBlink == FULLY_OPEN) { _rightEyeBlinkVelocity = 0.0f; } diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a91154ff15..69694a00c3 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -3214,3 +3214,12 @@ void AvatarData::clearAvatarGrabData(const QUuid& grabID) { } }); } + +glm::vec3 AvatarData::getHeadJointFrontVector() const { + int headJointIndex = getJointIndex("Head"); + glm::quat headJointRotation = Quaternions::Y_180 * getAbsoluteJointRotationInObjectFrame(headJointIndex);// getAbsoluteJointRotationInRigFrame(headJointIndex, headJointRotation); + headJointRotation = getWorldOrientation() * headJointRotation; + float headYaw = safeEulerAngles(headJointRotation).y; + glm::quat headYawRotation = glm::angleAxis(headYaw, Vectors::UP); + return headYawRotation * IDENTITY_FORWARD; +} diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 59a2e2a53e..bfe775e972 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1484,6 +1484,7 @@ public: std::vector getSkeletonData() const; void sendSkeletonData() const; QVector getJointData() const; + glm::vec3 getHeadJointFrontVector() const; signals: diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index f8a09905ef..7d05a50143 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -240,12 +240,16 @@ void HeadData::setLookAtPosition(const glm::vec3& lookAtPosition) { glm::vec3 oldAvatarLookAtVector = _requestLookAtPosition - _owningAvatar->getWorldPosition(); glm::vec3 newAvatarLookAtVector = lookAtPosition - _owningAvatar->getWorldPosition(); const float MIN_BLINK_ANGLE = 0.35f; // 20 degrees - _forceBlink = angleBetween(oldAvatarLookAtVector, newAvatarLookAtVector) > MIN_BLINK_ANGLE; + _blinkToRetarget = angleBetween(oldAvatarLookAtVector, newAvatarLookAtVector) > MIN_BLINK_ANGLE; _lookAtUpdated = false; + } + if (_lookAtUpdated) { + _lookAtPosition = lookAtPosition; } _requestLookAtPosition = lookAtPosition; - if (_lookAtUpdated) { - _forceBlink = false; - _lookAtPosition = lookAtPosition; - } -} \ No newline at end of file +} + +void HeadData::updateEyeLookAt() { + _lookAtPosition = _requestLookAtPosition; + _lookAtUpdated = true; +} diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index a8005b5659..7b73f57113 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -79,10 +79,7 @@ public: void setFaceTrackerConnected(bool value); bool getFaceTrackerConnected() const { return _isFaceTrackerConnected; } - void updateEyeLookAt() { - _lookAtPosition = _requestLookAtPosition; - _lookAtUpdated = true; - } + void updateEyeLookAt(); friend class AvatarData; @@ -116,7 +113,7 @@ protected: QVector _summedBlendshapeCoefficients; QMap _blendshapeLookupMap; AvatarData* _owningAvatar; - bool _forceBlink { false }; + bool _blinkToRetarget { false }; bool _lookAtUpdated { false }; private: