//Renders a small magnification of the currently bound texture at the coordinates void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const { Application* application = Application::getInstance(); GLCanvas* glWidget = application->getGLWidget(); const int widgetWidth = glWidget->width(); const int widgetHeight = glWidget->height(); const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; // Magnification Texture Coordinates const float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; const float newHalfWidth = halfWidth * MAGNIFY_MULT; const float newHalfHeight = halfHeight * MAGNIFY_MULT; //Get yaw / pitch value for the corners const glm::vec2 topLeftYawPitch = overlayToSpherical(glm::vec2(magPos.x - newHalfWidth, magPos.y - newHalfHeight)); const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth, magPos.y + newHalfHeight)); const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y); const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y); const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y); const glm::vec3 topRight = getPoint(bottomRightYawPitch.x, topLeftYawPitch.y); glPushMatrix(); { if (showBorder) { glDisable(GL_TEXTURE_2D); glLineWidth(1.0f); //Outer Line glBegin(GL_LINE_STRIP); { glColor4f(1.0f, 0.0f, 0.0f, _alpha); glVertex3f(topLeft.x, topLeft.y, topLeft.z); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); glVertex3f(topRight.x, topRight.y, topRight.z); glVertex3f(topLeft.x, topLeft.y, topLeft.z); } glEnd(); glEnable(GL_TEXTURE_2D); } glColor4f(1.0f, 1.0f, 1.0f, _alpha); glBegin(GL_QUADS); { glTexCoord2f(magnifyULeft, magnifyVBottom); glVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); glTexCoord2f(magnifyURight, magnifyVBottom); glVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); glTexCoord2f(magnifyURight, magnifyVTop); glVertex3f(topRight.x, topRight.y, topRight.z); glTexCoord2f(magnifyULeft, magnifyVTop); glVertex3f(topLeft.x, topLeft.y, topLeft.z); } glEnd(); } glPopMatrix(); }
// eyePose and headPosition are in sensor space. // the resulting matrix should be in view space. glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const glm::vec3& headPosition) const { glm::mat4 result; if (isHMD()) { vec2 spherical = overlayToSpherical(getReticlePosition()); vec3 overlaySurfacePoint = getPoint(spherical.x, spherical.y); // overlay space vec3 sensorSurfacePoint = _modelTransform.transform(overlaySurfacePoint); // sensor space vec3 d = sensorSurfacePoint - headPosition; vec3 reticlePosition; if (glm::length(d) >= EPSILON) { d = glm::normalize(d); } else { d = glm::normalize(overlaySurfacePoint); } reticlePosition = headPosition + (d * getReticleDepth()); quat reticleOrientation = cancelOutRoll(glm::quat_cast(_currentDisplayPlugin->getHeadPose())); vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize * getReticleDepth()); return glm::inverse(eyePose) * createMatFromScaleQuatAndPos(reticleScale, reticleOrientation, reticlePosition); } else { static const float CURSOR_PIXEL_SIZE = 32.0f; const auto canvasSize = vec2(toGlm(_renderingWidget->size()));; vec2 mousePosition = toGlm(_renderingWidget->mapFromGlobal(QCursor::pos())); mousePosition /= canvasSize; mousePosition *= 2.0; mousePosition -= 1.0; mousePosition.y *= -1.0f; vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; result = glm::scale(glm::translate(glm::mat4(), vec3(mousePosition, 0.0f)), vec3(mouseSize, 1.0f)); } return result; }
glm::vec3 CompositorHelper::sphereSurfaceFromOverlay(const glm::vec2& overlay) const { auto spherical = overlayToSpherical(overlay); // FIXME use a GLMHelper sphericalToCartesian after fixing the rotation signs. auto sphereSurfacePoint = getPoint(spherical.x, spherical.y); auto UITransform = getUiTransform(); auto position4 = UITransform * vec4(sphereSurfacePoint, 1); return vec3(position4) / position4.w; }
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(); 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(); const auto canvasSize = vec2(toGlm(renderingWidget->size()));; vec2 mousePosition = toGlm(renderingWidget->mapFromGlobal(QCursor::pos())); mousePosition /= canvasSize; mousePosition *= 2.0; mousePosition -= 1.0; mousePosition.y *= -1.0f; vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; return glm::scale(glm::translate(glm::mat4(), vec3(mousePosition, 0.0f)), vec3(mouseSize, 1.0f)); } return result; }
glm::vec2 ApplicationCompositor::overlayToScreen(const glm::vec2& overlayPos) const { return sphericalToScreen(overlayToSpherical(overlayPos)); }
//Renders a small magnification of the currently bound texture at the coordinates void ApplicationCompositor::renderMagnifier(gpu::Batch& batch, const glm::vec2& magPos, float sizeMult, bool showBorder) { if (!_magnifier) { return; } auto canvasSize = qApp->getCanvasSize(); const int widgetWidth = canvasSize.x; const int widgetHeight = canvasSize.y; const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; // Magnification Texture Coordinates const float magnifyULeft = (magPos.x - halfWidth) / (float)widgetWidth; const float magnifyURight = (magPos.x + halfWidth) / (float)widgetWidth; const float magnifyVTop = 1.0f - (magPos.y - halfHeight) / (float)widgetHeight; const float magnifyVBottom = 1.0f - (magPos.y + halfHeight) / (float)widgetHeight; const float newHalfWidth = halfWidth * MAGNIFY_MULT; const float newHalfHeight = halfHeight * MAGNIFY_MULT; //Get yaw / pitch value for the corners const glm::vec2 topLeftYawPitch = overlayToSpherical(glm::vec2(magPos.x - newHalfWidth, magPos.y - newHalfHeight)); const glm::vec2 bottomRightYawPitch = overlayToSpherical(glm::vec2(magPos.x + newHalfWidth, magPos.y + newHalfHeight)); const glm::vec3 bottomLeft = getPoint(topLeftYawPitch.x, bottomRightYawPitch.y); const glm::vec3 bottomRight = getPoint(bottomRightYawPitch.x, bottomRightYawPitch.y); const glm::vec3 topLeft = getPoint(topLeftYawPitch.x, topLeftYawPitch.y); const glm::vec3 topRight = getPoint(bottomRightYawPitch.x, topLeftYawPitch.y); auto geometryCache = DependencyManager::get<GeometryCache>(); if (bottomLeft != _previousMagnifierBottomLeft || bottomRight != _previousMagnifierBottomRight || topLeft != _previousMagnifierTopLeft || topRight != _previousMagnifierTopRight) { QVector<glm::vec3> border; border << topLeft; border << bottomLeft; border << bottomRight; border << topRight; border << topLeft; geometryCache->updateVertices(_magnifierBorder, border, glm::vec4(1.0f, 0.0f, 0.0f, _alpha)); _previousMagnifierBottomLeft = bottomLeft; _previousMagnifierBottomRight = bottomRight; _previousMagnifierTopLeft = topLeft; _previousMagnifierTopRight = topRight; } glPushMatrix(); { if (showBorder) { glDisable(GL_TEXTURE_2D); glLineWidth(1.0f); //Outer Line geometryCache->renderVertices(gpu::LINE_STRIP, _magnifierBorder); glEnable(GL_TEXTURE_2D); } glm::vec4 magnifierColor = { 1.0f, 1.0f, 1.0f, _alpha }; DependencyManager::get<GeometryCache>()->renderQuad(bottomLeft, bottomRight, topRight, topLeft, glm::vec2(magnifyULeft, magnifyVBottom), glm::vec2(magnifyURight, magnifyVBottom), glm::vec2(magnifyURight, magnifyVTop), glm::vec2(magnifyULeft, magnifyVTop), magnifierColor, _magnifierQuad); } glPopMatrix(); }
glm::vec2 ApplicationOverlay::overlayToScreen(glm::vec2 overlayPos) const { return sphericalToScreen(overlayToSpherical(overlayPos)); }