bool checkMinSpecImpl() { // If OpenVR isn't supported, we have no min spec, so pass if (!openVrSupported()) { return true; } // If we have at least MIN_CORES_SPEC cores, pass auto coreCount = QThread::idealThreadCount(); if (coreCount >= MIN_CORES_SPEC) { return true; } // Even if we have too few cores... if the compositor is using async reprojection, pass auto system = acquireOpenVrSystem(); auto compositor = vr::VRCompositor(); if (system && compositor) { vr::Compositor_FrameTiming timing; memset(&timing, 0, sizeof(timing)); timing.m_nSize = sizeof(vr::Compositor_FrameTiming); compositor->GetFrameTiming(&timing); releaseOpenVrSystem(); if (timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync) { return true; } } // We're using OpenVR and we don't have enough cores... showMinSpecWarning(); return false; }
void OpenVrDisplayPlugin::activate() { _container->setIsOptionChecked(StandingHMDSensorMode, true); if (!_system) { _system = acquireOpenVrSystem(); } Q_ASSERT(_system); _system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); // Recommended render target size is per-eye, so double the X size for // left + right eyes _renderTargetSize.x *= 2; { Lock lock(_poseMutex); openvr_for_each_eye([&](vr::Hmd_Eye eye) { _eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye)); _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); }); // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes _cullingProjection = _eyeProjections[0]; } _compositor = vr::VRCompositor(); Q_ASSERT(_compositor); HmdDisplayPlugin::activate(); }
void showMinSpecWarning() { auto vrSystem = acquireOpenVrSystem(); auto vrOverlay = vr::VROverlay(); if (!vrOverlay) { qFatal("Unable to initialize SteamVR overlay manager"); } vr::VROverlayHandle_t minSpecFailedOverlay = 0; if (vr::VROverlayError_None != vrOverlay->CreateOverlay(FAILED_MIN_SPEC_OVERLAY_NAME, FAILED_MIN_SPEC_OVERLAY_FRIENDLY_NAME, &minSpecFailedOverlay)) { qFatal("Unable to create overlay"); } // Needed here for PathUtils QCoreApplication miniApp(__argc, __argv); vrSystem->ResetSeatedZeroPose(); QString imagePath = PathUtils::resourcesPath() + "/images/steam-min-spec-failed.png"; vrOverlay->SetOverlayFromFile(minSpecFailedOverlay, imagePath.toLocal8Bit().toStdString().c_str()); vrOverlay->SetHighQualityOverlay(minSpecFailedOverlay); vrOverlay->SetOverlayWidthInMeters(minSpecFailedOverlay, 1.4f); vrOverlay->SetOverlayInputMethod(minSpecFailedOverlay, vr::VROverlayInputMethod_Mouse); vrOverlay->ShowOverlay(minSpecFailedOverlay); QTimer* timer = new QTimer(&miniApp); timer->setInterval(FAILED_MIN_SPEC_UPDATE_INTERVAL_MS); // Qt::CoarseTimer acceptable, we don't need this to be frame rate accurate QObject::connect(timer, &QTimer::timeout, [&] { vr::TrackedDevicePose_t vrPoses[vr::k_unMaxTrackedDeviceCount]; vrSystem->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseSeated, 0, vrPoses, vr::k_unMaxTrackedDeviceCount); auto headPose = toGlm(vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); auto overlayPose = toOpenVr(headPose * glm::translate(glm::mat4(), vec3(0, 0, -1))); vrOverlay->SetOverlayTransformAbsolute(minSpecFailedOverlay, vr::TrackingUniverseSeated, &overlayPose); vr::VREvent_t event; while (vrSystem->PollNextEvent(&event, sizeof(event))) { switch (event.eventType) { case vr::VREvent_Quit: vrSystem->AcknowledgeQuit_Exiting(); QCoreApplication::quit(); break; case vr::VREvent_ButtonPress: // Quit on any button press except for 'putting on the headset' if (event.data.controller.button != vr::k_EButton_ProximitySensor) { QCoreApplication::quit(); } break; default: break; } } }); timer->start(); QTimer::singleShot(FAILED_MIN_SPEC_AUTO_QUIT_INTERVAL_MS, &miniApp, &QCoreApplication::quit); miniApp.exec(); }
bool OpenVrDisplayPlugin::internalActivate() { Parent::internalActivate(); _container->setIsOptionChecked(StandingHMDSensorMode, true); if (!_system) { _system = acquireOpenVrSystem(); } if (!_system) { qWarning() << "Failed to initialize OpenVR"; return false; } _system->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); // Recommended render target size is per-eye, so double the X size for // left + right eyes _renderTargetSize.x *= 2; { Lock lock(_poseMutex); openvr_for_each_eye([&](vr::Hmd_Eye eye) { _eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye)); _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); }); // FIXME Calculate the proper combined projection by using GetProjectionRaw values from both eyes _cullingProjection = _eyeProjections[0]; } _compositor = vr::VRCompositor(); Q_ASSERT(_compositor); // enable async time warp // _compositor->ForceInterleavedReprojectionOn(true); // set up default sensor space such that the UI overlay will align with the front of the room. auto chaperone = vr::VRChaperone(); if (chaperone) { float const UI_RADIUS = 1.0f; float const UI_HEIGHT = 1.6f; float const UI_Z_OFFSET = 0.5; float xSize, zSize; chaperone->GetPlayAreaSize(&xSize, &zSize); glm::vec3 uiPos(0.0f, UI_HEIGHT, UI_RADIUS - (0.5f * zSize) - UI_Z_OFFSET); _sensorResetMat = glm::inverse(createMatFromQuatAndPos(glm::quat(), uiPos)); } else { qDebug() << "OpenVR: error could not get chaperone pointer"; } return true; }
void OpenVrDisplayPlugin::activate() { _container->setIsOptionChecked(StandingHMDSensorMode, true); if (!_hmd) { _hmd = acquireOpenVrSystem(); } Q_ASSERT(_hmd); _hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); // Recommended render target size is per-eye, so double the X size for // left + right eyes _renderTargetSize.x *= 2; openvr_for_each_eye([&](vr::Hmd_Eye eye) { PerEyeData& eyeData = _eyesData[eye]; eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye)); }); _compositor = vr::VRCompositor(); Q_ASSERT(_compositor); WindowOpenGLDisplayPlugin::activate(); }
bool OpenVrDisplayPlugin::isSupported() const { auto hmd = acquireOpenVrSystem(); bool success = nullptr != hmd; releaseOpenVrSystem(); return success; }