From f26849c7e15a25b836308f9c3a613e43ef48eded Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 20 Aug 2015 12:34:50 -0700 Subject: [PATCH 1/4] Proper HMD scaling. --- interface/src/avatar/MyAvatar.cpp | 40 +++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 52473a6d47..cd968c3d59 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -846,7 +846,7 @@ void MyAvatar::sendKillAvatar() { void MyAvatar::updateLookAtTargetAvatar() { // // Look at the avatar whose eyes are closest to the ray in direction of my avatar's head - // + // And set the correctedLookAt for all (nearby) avatars that are looking at me. _lookAtTargetAvatar.reset(); _targetAvatarPosition = glm::vec3(0.0f); @@ -870,14 +870,39 @@ void MyAvatar::updateLookAtTargetAvatar() { smallestAngleTo = angleTo; } if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { + // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. // Offset their gaze according to whether they're looking at one of my eyes or my mouth. - glm::vec3 gazeOffset = avatar->getHead()->getLookAtPosition() - getHead()->getEyePosition(); - const float HUMAN_EYE_SEPARATION = 0.065f; - float myEyeSeparation = glm::length(getHead()->getLeftEyePosition() - getHead()->getRightEyePosition()); - gazeOffset = gazeOffset * HUMAN_EYE_SEPARATION / myEyeSeparation; - avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition() - + gazeOffset); + + // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) + // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. + // (We will be adding that offset to the camera position, after making some other adjustments.) + glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); + glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); + + // Scale by proportional differences between avatar and human. + glm::mat4 leftEye = Application::getInstance()->getEyeOffset(Eye::Left); // Pose? + glm::mat4 rightEye = Application::getInstance()->getEyeOffset(Eye::Right); + glm::vec3 leftEyePosition = glm::vec3(leftEye[3]); + glm::vec3 rightEyePosition = glm::vec3(rightEye[3]); + float humanEyeSeparationInModelSpace = glm::length(leftEyePosition - rightEyePosition); + float avatarEyeSeparation = glm::length(getHead()->getLeftEyePosition() - getHead()->getRightEyePosition()); + gazeOffset = gazeOffset * humanEyeSeparationInModelSpace / avatarEyeSeparation; + + // If the camera is also not oriented with the head, adjust by getting the offset in head-space... + /* Not needed (i.e., code is a no-op), but I'm leaving the example code here in case something like this is needed someday. + glm::quat avatarHeadOrientation = getHead()->getOrientation(); + glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset; + // ... and treat that as though it were in camera space, bringing it back to world space. + // But camera is fudged to make the picture feel like the avatar's orientation. + glm::quat humanOrientation = Application::getInstance()->getViewFrustum()->getOrientation(); // or just avatar getOrienation() ? + gazeOffset = humanOrientation * gazeOffsetLocalToHead; + */ + + // And now we can finally add that offset to the camera. + glm::vec3 corrected = Application::getInstance()->getViewFrustum()->getPosition() + gazeOffset; + avatar->getHead()->setCorrectedLookAtPosition(corrected); + } else { avatar->getHead()->clearCorrectedLookAtPosition(); } @@ -1114,6 +1139,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl getHead()->render(renderArgs, 1.0f, renderFrustum); } + // This is drawing the lookat vectors from our avatar to wherever we're looking. if (qApp->isHMDMode()) { glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); From 05f4145acb97974b8fb40a85ac28e2a333b647c0 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 20 Aug 2015 16:28:40 -0700 Subject: [PATCH 2/4] Checkpoint. Working? --- interface/src/avatar/MyAvatar.cpp | 54 ++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cd968c3d59..1b8a3b2f89 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -843,6 +843,7 @@ void MyAvatar::sendKillAvatar() { DependencyManager::get()->broadcastToNodes(std::move(killPacket), NodeSet() << NodeType::AvatarMixer); } +static int counter = 0; void MyAvatar::updateLookAtTargetAvatar() { // // Look at the avatar whose eyes are closest to the ray in direction of my avatar's head @@ -872,21 +873,34 @@ void MyAvatar::updateLookAtTargetAvatar() { if (Application::getInstance()->isLookingAtMyAvatar(avatar)) { // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. - // Offset their gaze according to whether they're looking at one of my eyes or my mouth. + glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) + // Let's get everything to world space: + glm::vec3 avatarLeftEye = getHead()->getLeftEyePosition(); + glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); + // When not in HMD, these might both answer identity (i.e., the bridge of the nose). That's ok. + // By my inpsection of the code and live testing, getEyeOffset and getEyePose are the same. (Application hands identity as offset matrix.) + glm::mat4 leftEye = Application::getInstance()->getEyeOffset(Eye::Left); + glm::mat4 rightEye = Application::getInstance()->getEyeOffset(Eye::Right); + glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); + glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); + auto humanSystem = Application::getInstance()->getViewFrustum(); + glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); + glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); + + // debugging or some code paths + glm::vec3 avatarAverage = avatarLeftEye + ((avatarRightEye - avatarLeftEye) * 0.5f); + glm::vec3 humanAverage = humanLeftEye + ((humanRightEye - humanLeftEye) * 0.5f); + +#if 1 // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. // (We will be adding that offset to the camera position, after making some other adjustments.) - glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); // Scale by proportional differences between avatar and human. - glm::mat4 leftEye = Application::getInstance()->getEyeOffset(Eye::Left); // Pose? - glm::mat4 rightEye = Application::getInstance()->getEyeOffset(Eye::Right); - glm::vec3 leftEyePosition = glm::vec3(leftEye[3]); - glm::vec3 rightEyePosition = glm::vec3(rightEye[3]); - float humanEyeSeparationInModelSpace = glm::length(leftEyePosition - rightEyePosition); - float avatarEyeSeparation = glm::length(getHead()->getLeftEyePosition() - getHead()->getRightEyePosition()); + float humanEyeSeparationInModelSpace = glm::length(humanLeftEye - humanRightEye); + float avatarEyeSeparation = glm::length(avatarLeftEye - avatarRightEye); gazeOffset = gazeOffset * humanEyeSeparationInModelSpace / avatarEyeSeparation; // If the camera is also not oriented with the head, adjust by getting the offset in head-space... @@ -895,13 +909,30 @@ void MyAvatar::updateLookAtTargetAvatar() { glm::vec3 gazeOffsetLocalToHead = glm::inverse(avatarHeadOrientation) * gazeOffset; // ... and treat that as though it were in camera space, bringing it back to world space. // But camera is fudged to make the picture feel like the avatar's orientation. - glm::quat humanOrientation = Application::getInstance()->getViewFrustum()->getOrientation(); // or just avatar getOrienation() ? + glm::quat humanOrientation = humanSystem->getOrientation(); // or just avatar getOrienation() ? gazeOffset = humanOrientation * gazeOffsetLocalToHead; - */ + glm::vec3 corrected = humanSystem->getPosition() + gazeOffset; + */ // And now we can finally add that offset to the camera. glm::vec3 corrected = Application::getInstance()->getViewFrustum()->getPosition() + gazeOffset; +#else + //glm::vec3 gazeOffset = ((humanRightEye - avatarRightEye) + (humanLeftEye - avatarLeftEye)) * 0.5f; + glm::vec3 gazeOffset = humanAverage - avatarAverage; + glm::vec3 corrected = lookAtPosition + gazeOffset; +#endif avatar->getHead()->setCorrectedLookAtPosition(corrected); + + if (counter++ > 60) { + counter = 0; + qCDebug(interfaceapp) << Application::getInstance()->isHMDMode(); + qCDebug(interfaceapp) << "camera:" << Application::getInstance()->getViewFrustum()->getPosition() << "delta from av human:" << (humanAverage - Application::getInstance()->getViewFrustum()->getPosition()); + + qCDebug(interfaceapp) << "lt avatar:" << avatarLeftEye << " lt human:" << humanLeftEye; + qCDebug(interfaceapp) << "rt avatar:" << avatarRightEye << " rt human:" << humanRightEye; + qCDebug(interfaceapp) << "av avatar:" << avatarAverage << " av humn:" << humanAverage; + qCDebug(interfaceapp) << "offset:" << gazeOffset << " corrected:" << corrected << " from:" << lookAtPosition; + } } else { avatar->getHead()->clearCorrectedLookAtPosition(); @@ -1140,6 +1171,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl } // This is drawing the lookat vectors from our avatar to wherever we're looking. + /* if (qApp->isHMDMode()) { glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); @@ -1155,7 +1187,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl cameraPosition + getOrientation() * (rightEyePosition - headPosition)); } else { getHead()->renderLookAts(renderArgs); - } + }*/ getHand()->render(renderArgs, true); } From ea02583875178380c429046fd5e8ef3fcfb8258a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 20 Aug 2015 17:33:10 -0700 Subject: [PATCH 3/4] Cleanup. --- interface/src/avatar/MyAvatar.cpp | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1b8a3b2f89..501c7eb8d5 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -881,6 +881,7 @@ void MyAvatar::updateLookAtTargetAvatar() { glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); // When not in HMD, these might both answer identity (i.e., the bridge of the nose). That's ok. // By my inpsection of the code and live testing, getEyeOffset and getEyePose are the same. (Application hands identity as offset matrix.) + // This might be more work than needed for any given use, but as we explore different formulations, we go mad if we don't work in world space. glm::mat4 leftEye = Application::getInstance()->getEyeOffset(Eye::Left); glm::mat4 rightEye = Application::getInstance()->getEyeOffset(Eye::Right); glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); @@ -888,12 +889,8 @@ void MyAvatar::updateLookAtTargetAvatar() { auto humanSystem = Application::getInstance()->getViewFrustum(); glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal); glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal); - - // debugging or some code paths - glm::vec3 avatarAverage = avatarLeftEye + ((avatarRightEye - avatarLeftEye) * 0.5f); - glm::vec3 humanAverage = humanLeftEye + ((humanRightEye - humanLeftEye) * 0.5f); -#if 1 + // First find out where (in world space) the person is looking relative to that bridge-of-the-avatar point. // (We will be adding that offset to the camera position, after making some other adjustments.) glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); @@ -916,23 +913,8 @@ void MyAvatar::updateLookAtTargetAvatar() { // And now we can finally add that offset to the camera. glm::vec3 corrected = Application::getInstance()->getViewFrustum()->getPosition() + gazeOffset; -#else - //glm::vec3 gazeOffset = ((humanRightEye - avatarRightEye) + (humanLeftEye - avatarLeftEye)) * 0.5f; - glm::vec3 gazeOffset = humanAverage - avatarAverage; - glm::vec3 corrected = lookAtPosition + gazeOffset; -#endif + avatar->getHead()->setCorrectedLookAtPosition(corrected); - - if (counter++ > 60) { - counter = 0; - qCDebug(interfaceapp) << Application::getInstance()->isHMDMode(); - qCDebug(interfaceapp) << "camera:" << Application::getInstance()->getViewFrustum()->getPosition() << "delta from av human:" << (humanAverage - Application::getInstance()->getViewFrustum()->getPosition()); - - qCDebug(interfaceapp) << "lt avatar:" << avatarLeftEye << " lt human:" << humanLeftEye; - qCDebug(interfaceapp) << "rt avatar:" << avatarRightEye << " rt human:" << humanRightEye; - qCDebug(interfaceapp) << "av avatar:" << avatarAverage << " av humn:" << humanAverage; - qCDebug(interfaceapp) << "offset:" << gazeOffset << " corrected:" << corrected << " from:" << lookAtPosition; - } } else { avatar->getHead()->clearCorrectedLookAtPosition(); From 642e56903329bbbe3c70d0795f40a2fc3f7913f7 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 20 Aug 2015 17:38:49 -0700 Subject: [PATCH 4/4] Uncomment code that was commented out to simplify debugging. --- interface/src/avatar/MyAvatar.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 501c7eb8d5..eada41eb29 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1153,7 +1153,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl } // This is drawing the lookat vectors from our avatar to wherever we're looking. - /* if (qApp->isHMDMode()) { glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); @@ -1169,7 +1168,7 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl cameraPosition + getOrientation() * (rightEyePosition - headPosition)); } else { getHead()->renderLookAts(renderArgs); - }*/ + } getHand()->render(renderArgs, true); }