void FOSVRHMD::UpdateHeadPose(FQuat& lastHmdOrientation, FVector& lastHmdPosition, FQuat& hmdOrientation, FVector& hmdPosition) { OSVR_Pose3 pose; OSVR_ReturnCode returnCode; auto entryPoint = IOSVR::Get().GetEntryPoint(); FScopeLock lock(entryPoint->GetClientContextMutex()); auto clientContext = entryPoint->GetClientContext(); returnCode = osvrClientUpdate(clientContext); check(returnCode == OSVR_RETURN_SUCCESS); returnCode = osvrClientGetViewerPose(DisplayConfig, 0, &pose); if (returnCode == OSVR_RETURN_SUCCESS) { LastHmdOrientation = CurHmdOrientation; LastHmdPosition = CurHmdPosition; CurHmdPosition = BaseOrientation.Inverse().RotateVector(OSVR2FVector(pose.translation, WorldToMetersScale) - BasePosition); CurHmdOrientation = BaseOrientation.Inverse() * OSVR2FQuat(pose.rotation); lastHmdOrientation = LastHmdOrientation; lastHmdPosition = LastHmdPosition; hmdOrientation = CurHmdOrientation; hmdPosition = CurHmdPosition; } else { lastHmdOrientation = hmdOrientation = FQuat::Identity; lastHmdPosition = hmdPosition = FVector(0.0f, 0.0f, 0.0f); } }
bool FOSVRHMD::GetHMDMonitorInfo(MonitorInfo& MonitorDesc) { auto entryPoint = IOSVR::Get().GetEntryPoint(); FScopeLock lock(entryPoint->GetClientContextMutex()); if (IsInitialized() && osvrClientCheckDisplayStartup(DisplayConfig) == OSVR_RETURN_SUCCESS) { auto leftEye = HMDDescription.GetDisplaySize(OSVRHMDDescription::LEFT_EYE); auto rightEye = HMDDescription.GetDisplaySize(OSVRHMDDescription::RIGHT_EYE); OSVR_ViewportDimension width = (OSVR_ViewportDimension)leftEye.X + (OSVR_ViewportDimension)rightEye.X; OSVR_ViewportDimension height = (OSVR_ViewportDimension)leftEye.Y; float fWidth, fHeight; GetRenderTargetSize_GameThread(width, height, fWidth, fHeight); MonitorDesc.MonitorName = "OSVR-Display"; //@TODO MonitorDesc.MonitorId = 0; //@TODO MonitorDesc.DesktopX = 0; MonitorDesc.DesktopY = 0; MonitorDesc.ResolutionX = fWidth; MonitorDesc.ResolutionY = fHeight; return true; } else { MonitorDesc.MonitorName = ""; MonitorDesc.MonitorId = 0; MonitorDesc.DesktopX = MonitorDesc.DesktopY = MonitorDesc.ResolutionX = MonitorDesc.ResolutionY = 0; } return false; }
TSharedPtr< class IInputDevice > FOSVRInput::CreateInputDevice(const TSharedRef< FGenericApplicationMessageHandler >& InMessageHandler) { auto& osvr = IOSVR::Get(); auto entryPoint = osvr.GetEntryPoint(); auto osvrHMD = osvr.GetHMD(); FScopeLock lock(entryPoint->GetClientContextMutex()); if (entryPoint->IsOSVRConnected()) { FOSVRInputDevice::RegisterNewKeys(); InputDevice = MakeShareable(new FOSVRInputDevice(InMessageHandler, entryPoint, osvrHMD)); return InputDevice; } return nullptr; }
FMatrix FOSVRHMD::GetStereoProjectionMatrix(enum EStereoscopicPass StereoPassType, const float FOV) const { auto entryPoint = IOSVR::Get().GetEntryPoint(); auto mutex = entryPoint->GetClientContextMutex(); FScopeLock lock(mutex); FMatrix ret; if (mCustomPresent) { double left, right, bottom, top; mCustomPresent->GetProjectionMatrix( StereoPassType == eSSP_LEFT_EYE ? 0 : 1, left, right, bottom, top); ret = HMDDescription.GetProjectionMatrix(left, right, bottom, top); } else { ret = HMDDescription.GetProjectionMatrix( StereoPassType == eSSP_LEFT_EYE ? OSVRHMDDescription::LEFT_EYE : OSVRHMDDescription::RIGHT_EYE, DisplayConfig); } return ret; }
FOSVRHMD::~FOSVRHMD() { auto entryPoint = IOSVR::Get().GetEntryPoint(); FScopeLock lock(entryPoint->GetClientContextMutex()); EnablePositionalTracking(false); }
FOSVRHMD::FOSVRHMD() : LastHmdOrientation(FQuat::Identity), CurHmdOrientation(FQuat::Identity), DeltaControlRotation(FRotator::ZeroRotator), DeltaControlOrientation(FQuat::Identity), CurHmdPosition(FVector::ZeroVector), BaseOrientation(FQuat::Identity), BasePosition(FVector::ZeroVector), WorldToMetersScale(100.0f), bHmdPosTracking(false), bHaveVisionTracking(false), bStereoEnabled(true), bHmdEnabled(true), bHmdOverridesApplied(false), DisplayConfig(nullptr) { static const FName RendererModuleName("Renderer"); RendererModule = FModuleManager::GetModulePtr<IRendererModule>(RendererModuleName); auto entryPoint = IOSVR::Get().GetEntryPoint(); FScopeLock lock(entryPoint->GetClientContextMutex()); auto osvrClientContext = entryPoint->GetClientContext(); // Prevents debugger hangs that sometimes occur with only one monitor. #if OSVR_UNREAL_DEBUG_FORCED_WINDOWMODE FSystemResolution::RequestResolutionChange(1280, 720, EWindowMode::Windowed); // bStereo ? WindowedMirror : Windowed #endif EnablePositionalTracking(true); IConsoleVariable* CVScreenPercentage = IConsoleManager::Get().FindConsoleVariable(TEXT("r.screenpercentage")); if (CVScreenPercentage) { mScreenScale = float(CVScreenPercentage->GetInt()) / 100.0f; } StartCustomPresent(); // enable vsync IConsoleVariable* CVSyncVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.VSync")); if (CVSyncVar) { CVSyncVar->Set(false); } // Uncap fps to enable FPS higher than 62 GEngine->bSmoothFrameRate = false; // check if the client context is ok. bool bClientContextOK = entryPoint->IsOSVRConnected(); // get the display context bool bDisplayConfigOK = false; if (bClientContextOK) { bool bFailure = false; auto rc = osvrClientGetDisplay(osvrClientContext, &DisplayConfig); if (rc == OSVR_RETURN_FAILURE) { UE_LOG(OSVRHMDLog, Warning, TEXT("Could not create DisplayConfig. Treating this as if the HMD is not connected.")); } else { auto begin = FDateTime::Now().GetSecond(); auto end = begin + 3; while (!bDisplayConfigOK && FDateTime::Now().GetSecond() < end) { bDisplayConfigOK = osvrClientCheckDisplayStartup(DisplayConfig) == OSVR_RETURN_SUCCESS; if (!bDisplayConfigOK) { bFailure = osvrClientUpdate(osvrClientContext) == OSVR_RETURN_FAILURE; if (bFailure) { UE_LOG(OSVRHMDLog, Warning, TEXT("osvrClientUpdate failed during startup. Treating this as \"HMD not connected\"")); break; } } FPlatformProcess::Sleep(0.2f); } bDisplayConfigOK = bDisplayConfigOK && !bFailure; if (!bDisplayConfigOK) { UE_LOG(OSVRHMDLog, Warning, TEXT("DisplayConfig failed to startup. This could mean that there is nothing mapped to /me/head. Treating this as if the HMD is not connected.")); } } } bool bDisplayConfigMatchesUnrealExpectations = false; if (bDisplayConfigOK) { bool bSuccess = HMDDescription.Init(osvrClientContext, DisplayConfig); if (bSuccess) { bDisplayConfigMatchesUnrealExpectations = HMDDescription.OSVRViewerFitsUnrealModel(DisplayConfig); if (!bDisplayConfigMatchesUnrealExpectations) { UE_LOG(OSVRHMDLog, Warning, TEXT("The OSVR display config does not match the expectations of Unreal. Possibly incompatible HMD configuration.")); } } else { UE_LOG(OSVRHMDLog, Warning, TEXT("Unable to initialize the HMDDescription. Possible failures during initialization.")); } } // our version of connected is that the client context is ok (server is running) // and the display config is ok (/me/head exists and received a pose) bHmdConnected = bClientContextOK && bDisplayConfigOK && bDisplayConfigMatchesUnrealExpectations; }