From f5acf49e478d34f3a3b4235f6111a45382f7ee23 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 7 Mar 2016 16:21:08 -0800 Subject: [PATCH] Fix reticle transform when depth != 1 --- .../src/display-plugins/CompositorHelper.cpp | 54 ++++++++----------- .../src/display-plugins/CompositorHelper.h | 2 +- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 5 +- 3 files changed, 24 insertions(+), 37 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index ceaff0c0a1..1ef86cc7d2 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -26,7 +26,6 @@ // Used to animate the magnification windows -static const quint64 MSECS_TO_USECS = 1000ULL; //static const quint64 TOOLTIP_DELAY = 500 * MSECS_TO_USECS; static const float reticleSize = TWO_PI / 100.0f; @@ -432,42 +431,31 @@ void CompositorHelper::toggle() { } -glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const glm::mat4& headPose) const { + +glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const glm::vec3& headPosition) const { glm::mat4 result; if (isHMD()) { vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); auto reticlePosition = getReticlePosition(); - if (getReticleDepth() != 1.0f) { - auto spherical = overlayToSpherical(reticlePosition); - auto sphereSurfacePoint = getPoint(spherical.x, spherical.y); - auto origin = vec3(headPose[3]); - auto direction = glm::normalize(sphereSurfacePoint - origin); - auto apparentPosition = (direction * getReticleDepth()); - - // same code as used to render for apparent location - auto relativePosition4 = glm::inverse(eyePose) * vec4(apparentPosition, 1); - auto relativePosition = vec3(relativePosition4) / relativePosition4.w; - auto relativeDistance = glm::length(relativePosition); - - // look at borrowed from overlays - float elevation = -asinf(relativePosition.y / glm::length(relativePosition)); - float azimuth = atan2f(relativePosition.x, relativePosition.z); - glm::quat faceCamera = glm::quat(glm::vec3(elevation, azimuth, 0)) * quat(vec3(0, -PI, 0)); // this extra *quat(vec3(0,-PI,0)) was required to get the quad to flip this seems like we could optimize - - Transform transform; - transform.setTranslation(relativePosition); - transform.setScale(reticleScale); - transform.postScale(relativeDistance); - transform.setRotation(faceCamera); - transform.getMatrix(result); - } else { - glm::mat4 overlayXfm; - _modelTransform.getMatrix(overlayXfm); - glm::vec2 projection = overlayToSpherical(reticlePosition); - mat4 pointerXfm = glm::inverse(eyePose) * glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); - mat4 reticleXfm = overlayXfm * pointerXfm; - result = glm::scale(reticleXfm, reticleScale); - } + auto spherical = overlayToSpherical(reticlePosition); + // The pointer transform relative to the sensor + auto pointerTransform = glm::mat4_cast(quat(vec3(-spherical.y, spherical.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); + float reticleDepth = getReticleDepth(); + if (reticleDepth != 1.0f) { + // Cursor position in UI space + auto cursorPosition = vec3(pointerTransform[3]) / pointerTransform[3].w; + // Ray to the cursor, in UI space + auto cursorRay = glm::normalize(cursorPosition - headPosition) * reticleDepth; + // Move the ray to be relative to the head pose + pointerTransform[3] = vec4(cursorRay + headPosition, 1); + // Scale up the cursor because of distance + reticleScale *= reticleDepth; + } + glm::mat4 overlayXfm; + _modelTransform.getMatrix(overlayXfm); + pointerTransform = overlayXfm * pointerTransform; + pointerTransform = glm::inverse(eyePose) * pointerTransform; + result = glm::scale(pointerTransform, reticleScale); } else { static const float CURSOR_PIXEL_SIZE = 32.0f; static auto renderingWidget = PluginContainer::getInstance().getPrimaryWidget(); diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index d5424282c7..0de1029203 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -91,7 +91,7 @@ public: glm::vec2 getReticleMaximumPosition() const; - glm::mat4 getReticleTransform(const glm::mat4& eyePose = glm::mat4(), const glm::mat4& headPose = glm::mat4()) const; + glm::mat4 getReticleTransform(const glm::mat4& eyePose = glm::mat4(), const glm::vec3& headPosition = glm::vec3()) const; ReticleInterface* getReticleInterface() { return _reticleInterface; } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 056378e094..9470194180 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -77,12 +77,11 @@ void HmdDisplayPlugin::compositePointer() { auto compositorHelper = DependencyManager::get(); _plane->Use(); // Reconstruct the headpose from the eye poses - auto currentHeadPose = _currentRenderEyePoses[Left]; - currentHeadPose[3] = vec4((vec3(_currentRenderEyePoses[Left][3]) + vec3(_currentRenderEyePoses[Right][3])) / 2.0f, 1.0f); + auto headPosition = (vec3(_currentRenderEyePoses[Left][3]) + vec3(_currentRenderEyePoses[Right][3])) / 2.0f; for_each_eye([&](Eye eye) { using namespace oglplus; eyeViewport(eye); - auto reticleTransform = compositorHelper->getReticleTransform(_currentRenderEyePoses[eye], currentHeadPose); + auto reticleTransform = compositorHelper->getReticleTransform(_currentRenderEyePoses[eye], headPosition); Uniform(*_program, _modelViewUniform).Set(reticleTransform); Uniform(*_program, _projectionUniform).Set(_eyeProjections[eye]); _plane->Draw();