From d28c555a79c20365ce3cb37f8eea160a67102d4d Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 14 Aug 2015 16:47:34 -0700 Subject: [PATCH 1/3] Synchronize eye joint and debugging vectors when the other avatar is looking at me. --- interface/src/Application.cpp | 4 ++++ interface/src/avatar/Head.cpp | 16 ++++++++++++++- interface/src/avatar/SkeletonModel.cpp | 27 ++++++++++++++++++-------- libraries/animation/src/Rig.cpp | 9 +++++++-- libraries/animation/src/Rig.h | 2 ++ 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2f6b038e40..1b8ba2d4cd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2352,6 +2352,10 @@ void Application::updateMouseRay() { } } +// Called during Application::update immediately before AvatarManager::updateMyAvatar, updating my data that is then sent to everyone. +// (Maybe this code should be moved there?) +// The principal result is to call updateLookAtTargetAvatar() and then setLookAtPosition(). +// Note that it is called BEFORE we update position or joints based on sensors, etc. void Application::updateMyAvatarLookAtPosition() { PerformanceTimer perfTimer("lookAt"); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index cec9079443..065b655628 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -344,6 +344,20 @@ glm::quat Head::getFinalOrientationInLocalFrame() const { return glm::quat(glm::radians(glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); } +// Everyone else's head keeps track of a lookAtPosition that everybody sees the same, and refers to where that head +// is looking in model space -- e.g., at someone's eyeball, or between their eyes, or mouth, etc. Everyon's Interface +// will have the same value for the lookAtPosition of any given head. +// +// Everyone else's head also keeps track of a correctedLookAtPosition that may be different for the same head within +// different Interfaces. If that head is not looking at me, the correctedLookAtPosition is the same as the lookAtPosition. +// However, if that head is looking at me, then I will attempt to adjust the lookAtPosition by the difference between +// my (singular) eye position and my actual camera position. This adjustment is used on their eyeballs during rendering +// (and also on any lookAt vector display for that head, during rendering). Note that: +// 1. this adjustment can be made directly to the other head's eyeball joints, because we won't be send their joint information to others. +// 2. the corrected position is a separate ivar, so the common/uncorrected value is still available +// +// There is a pun here: The two lookAtPositions will always be the same for my own avatar in my own Interface, because I +// will not be looking at myself. (Even in a mirror, I will be looking at the camera.) glm::vec3 Head::getCorrectedLookAtPosition() { if (isLookingAtMe()) { return _correctedLookAtPosition; @@ -364,7 +378,7 @@ void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { bool Head::isLookingAtMe() { // Allow for outages such as may be encountered during avatar movement quint64 now = usecTimestampNow(); - const quint64 LOOKING_AT_ME_GAP_ALLOWED = 1000000; // microseconds + const quint64 LOOKING_AT_ME_GAP_ALLOWED = (5 * 1000.0f * 1000.0f) / 60.0f; // n frames, in microseconds return _isLookingAtMe || (now - _wasLastLookingAtMe) < LOOKING_AT_ME_GAP_ALLOWED; } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e870ba2140..e11e8996ca 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -97,7 +97,7 @@ void SkeletonModel::initJointStates(QVector states) { } const float PALM_PRIORITY = DEFAULT_PRIORITY; - +// Called within Model::simulate call, below. void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { if (_owningAvatar->isMyAvatar()) { _rig->computeMotionAnimationState(deltaTime, _owningAvatar->getPosition(), _owningAvatar->getVelocity(), _owningAvatar->getOrientation()); @@ -105,26 +105,37 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { Model::updateRig(deltaTime, parentTransform); if (_owningAvatar->isMyAvatar()) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); + Head* head = _owningAvatar->getHead(); Rig::HeadParameters params; params.modelRotation = getRotation(); params.modelTranslation = getTranslation(); - params.leanSideways = _owningAvatar->getHead()->getFinalLeanSideways(); - params.leanForward = _owningAvatar->getHead()->getFinalLeanForward(); - params.torsoTwist = _owningAvatar->getHead()->getTorsoTwist(); - params.localHeadOrientation = _owningAvatar->getHead()->getFinalOrientationInLocalFrame(); - params.worldHeadOrientation = _owningAvatar->getHead()->getFinalOrientationInWorldFrame(); - params.eyeLookAt = _owningAvatar->getHead()->getLookAtPosition(); - params.eyeSaccade = _owningAvatar->getHead()->getSaccade(); + params.leanSideways = head->getFinalLeanSideways(); + params.leanForward = head->getFinalLeanForward(); + params.torsoTwist = head->getTorsoTwist(); + params.localHeadOrientation = head->getFinalOrientationInLocalFrame(); + params.worldHeadOrientation = head->getFinalOrientationInWorldFrame(); + params.eyeLookAt = head->getLookAtPosition(); + params.eyeSaccade = head->getSaccade(); params.leanJointIndex = geometry.leanJointIndex; params.neckJointIndex = geometry.neckJointIndex; params.leftEyeJointIndex = geometry.leftEyeJointIndex; params.rightEyeJointIndex = geometry.rightEyeJointIndex; _rig->updateFromHeadParameters(params); + } else if (true) { //(_owningAvatar->getHead()->isLookingAtMe()) { + // Other avatars joint, including their eyes, will already be set just like any other joints + // from the wire data. But when looking at me, we want the eyes to use the corrected lookAt. + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + Head* head = _owningAvatar->getHead(); + _rig->updateEyeJoints(geometry.leftEyeJointIndex, geometry.rightEyeJointIndex, + getTranslation(), getRotation(), + head->getFinalOrientationInWorldFrame(), head->getCorrectedLookAtPosition()); } } +// Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed), +// but just before head has been simulated. void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { setTranslation(_owningAvatar->getSkeletonPosition()); static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 1a8bd0bbad..2212e06e31 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -786,8 +786,8 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) { void Rig::updateFromHeadParameters(const HeadParameters& params) { updateLeanJoint(params.leanJointIndex, params.leanSideways, params.leanForward, params.torsoTwist); updateNeckJoint(params.neckJointIndex, params.localHeadOrientation, params.leanSideways, params.leanForward, params.torsoTwist); - updateEyeJoint(params.leftEyeJointIndex, params.modelTranslation, params.modelRotation, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); - updateEyeJoint(params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); + updateEyeJoints(params.leftEyeJointIndex, params.rightEyeJointIndex, params.modelTranslation, params.modelRotation, + params.worldHeadOrientation, params.eyeLookAt, params.eyeSaccade); } void Rig::updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist) { @@ -828,6 +828,11 @@ void Rig::updateNeckJoint(int index, const glm::quat& localHeadOrientation, floa } } +void Rig::updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, + const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) { + updateEyeJoint(leftEyeIndex, modelTranslation, modelRotation, worldHeadOrientation, lookAtSpot, saccade); + updateEyeJoint(rightEyeIndex, modelTranslation, modelRotation, worldHeadOrientation, lookAtSpot, saccade); +} void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade) { if (index >= 0 && _jointStates[index].getParentIndex() >= 0) { auto& state = _jointStates[index]; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index face79bc15..8da20062cf 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -157,6 +157,8 @@ public: void setEnableRig(bool isEnabled) { _enableRig = isEnabled; } void updateFromHeadParameters(const HeadParameters& params); + void updateEyeJoints(int leftEyeIndex, int rightEyeIndex, const glm::vec3& modelTranslation, const glm::quat& modelRotation, + const glm::quat& worldHeadOrientation, const glm::vec3& lookAtSpot, const glm::vec3& saccade = glm::vec3(0.0f)); virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, float scale, float priority) = 0; From eeeaa8050d75f6fd796832e25b3150ddb435da2d Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 14 Aug 2015 18:58:49 -0700 Subject: [PATCH 2/3] Fix the rush jobs, so gustavo can build build for me... --- interface/src/avatar/Head.cpp | 2 +- interface/src/avatar/SkeletonModel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 065b655628..9ab2c83a79 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -378,7 +378,7 @@ void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { bool Head::isLookingAtMe() { // Allow for outages such as may be encountered during avatar movement quint64 now = usecTimestampNow(); - const quint64 LOOKING_AT_ME_GAP_ALLOWED = (5 * 1000.0f * 1000.0f) / 60.0f; // n frames, in microseconds + const quint64 LOOKING_AT_ME_GAP_ALLOWED = (5 * 1000 * 1000) / 60; // n frames, in microseconds return _isLookingAtMe || (now - _wasLastLookingAtMe) < LOOKING_AT_ME_GAP_ALLOWED; } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index e11e8996ca..831fb26abb 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -123,7 +123,7 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { params.rightEyeJointIndex = geometry.rightEyeJointIndex; _rig->updateFromHeadParameters(params); - } else if (true) { //(_owningAvatar->getHead()->isLookingAtMe()) { + } else if (_owningAvatar->getHead()->isLookingAtMe()) { // Other avatars joint, including their eyes, will already be set just like any other joints // from the wire data. But when looking at me, we want the eyes to use the corrected lookAt. const FBXGeometry& geometry = _geometry->getFBXGeometry(); From 941b966dc745fa1c0175feb2a25c4ab4387aa18b Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 17 Aug 2015 11:57:08 -0700 Subject: [PATCH 3/3] Force eyeball update even when not looking at me. --- interface/src/avatar/SkeletonModel.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 831fb26abb..d58cd8d7c4 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -123,9 +123,15 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { params.rightEyeJointIndex = geometry.rightEyeJointIndex; _rig->updateFromHeadParameters(params); - } else if (_owningAvatar->getHead()->isLookingAtMe()) { - // Other avatars joint, including their eyes, will already be set just like any other joints + } else { + // This is a little more work than we really want. + // + // Other avatars joint, including their eyes, should already be set just like any other joints // from the wire data. But when looking at me, we want the eyes to use the corrected lookAt. + // + // Thus this should really only be ... else if (_owningAvatar->getHead()->isLookingAtMe()) {... + // However, in the !isLookingAtMe case, the eyes aren't rotating the way they should right now. + // (They latch their looking at me position.) We will revisit that as priorities allow. const FBXGeometry& geometry = _geometry->getFBXGeometry(); Head* head = _owningAvatar->getHead(); _rig->updateEyeJoints(geometry.leftEyeJointIndex, geometry.rightEyeJointIndex,