// 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::vec2 CompositorHelper::getReticlePosition() const { if (isHMD()) { QMutexLocker locker(&_reticleLock); return _reticlePositionInHMD; } return toGlm(_renderingWidget->mapFromGlobal(QCursor::pos())); }
QPointF CompositorHelper::getMouseEventPosition(QMouseEvent* event) { if (isHMD()) { QMutexLocker locker(&_reticleLock); return QPointF(_reticlePositionInHMD.x, _reticlePositionInHMD.y); } return event->localPos(); }
void CompositorHelper::setReticlePosition(const glm::vec2& position, bool sendFakeEvent) { if (isHMD()) { glm::vec2 maxOverlayPosition = _currentDisplayPlugin->getRecommendedUiSize(); // FIXME don't allow negative mouseExtra glm::vec2 mouseExtra = (MOUSE_EXTENTS_PIXELS - maxOverlayPosition) / 2.0f; glm::vec2 minMouse = vec2(0) - mouseExtra; glm::vec2 maxMouse = maxOverlayPosition + mouseExtra; { QMutexLocker locker(&_reticleLock); _reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); } if (sendFakeEvent) { sendFakeMouseEvent(); } } else { // NOTE: This is some debugging code we will leave in while debugging various reticle movement strategies, // remove it after we're done const float REASONABLE_CHANGE = 50.0f; glm::vec2 oldPos = toGlm(QCursor::pos()); auto distance = glm::distance(oldPos, position); if (distance > REASONABLE_CHANGE) { qDebug() << "Contrller::ScriptingInterface ---- UNREASONABLE CHANGE! distance:" << distance << " oldPos:" << oldPos.x << "," << oldPos.y << " newPos:" << position.x << "," << position.y; } QCursor::setPos(position.x, position.y); } }
glm::vec2 CompositorHelper::getReticlePosition() const { if (isHMD()) { QMutexLocker locker(&_reticleLock); return _reticlePositionInHMD; } return toGlm(QCursor::pos()); }
glm::vec2 CompositorHelper::getReticleMaximumPosition() const { glm::vec2 result; if (isHMD()) { result = VIRTUAL_SCREEN_SIZE; } else { QRect rec = QApplication::desktop()->screenGeometry(); result = glm::vec2(rec.right(), rec.bottom()); } return result; }
bool CompositorHelper::getReticleOverDesktop() const { // if the QML/Offscreen UI thinks we're over the desktop, then we are... // but... if we're outside of the overlay area, we also want to call ourselves // as being over the desktop. if (isHMD()) { QMutexLocker locker(&_reticleLock); glm::vec2 maxOverlayPosition = _currentDisplayPlugin->getRecommendedUiSize(); static const glm::vec2 minOverlayPosition; if (glm::any(glm::lessThan(_reticlePositionInHMD, minOverlayPosition)) || glm::any(glm::greaterThan(_reticlePositionInHMD, maxOverlayPosition))) { return true; } } return _isOverDesktop; }
void CompositorHelper::setReticlePosition(const glm::vec2& position, bool sendFakeEvent) { if (isHMD()) { glm::vec2 maxOverlayPosition = _currentDisplayPlugin->getRecommendedUiSize(); // FIXME don't allow negative mouseExtra glm::vec2 mouseExtra = (MOUSE_EXTENTS_PIXELS - maxOverlayPosition) / 2.0f; glm::vec2 minMouse = vec2(0) - mouseExtra; glm::vec2 maxMouse = maxOverlayPosition + mouseExtra; { QMutexLocker locker(&_reticleLock); _reticlePositionInHMD = glm::clamp(position, minMouse, maxMouse); } if (sendFakeEvent) { sendFakeMouseEvent(); } } else { const QPoint point(position.x, position.y); QCursor::setPos(_renderingWidget->mapToGlobal(point)); } }
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; }
bool CompositorHelper::shouldCaptureMouse() const { // if we're in HMD mode, and some window of ours is active, but we're not currently showing a popup menu return _allowMouseCapture && isHMD() && QApplication::activeWindow() && !ui::Menu::isSomeSubmenuShown(); }