void UpdateOVRParams() { m_data.eyeFov[0] = m_device->DefaultEyeFov[0]; m_data.eyeFov[1] = m_device->DefaultEyeFov[1]; float DesiredPixelDensity = 1; // Configure Stereo settings. Default pixel density is 1.0f. Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(m_device, ovrEye_Left, m_data.eyeFov[0], DesiredPixelDensity); Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(m_device, ovrEye_Right, m_data.eyeFov[1], DesiredPixelDensity); Sizei rtSize(recommenedTex0Size.w + recommenedTex1Size.w, Alg::Max(recommenedTex0Size.h, recommenedTex1Size.h)); m_data.texSize.set(rtSize.w, rtSize.h); Sizei eyeRenderSize[2]; // Don't draw more then recommended size; this also ensures that resolution reported // in the overlay HUD size is updated correctly for FOV/pixel density change. eyeRenderSize[0] = Sizei::Min(Sizei(rtSize.w / 2, rtSize.h), recommenedTex0Size); eyeRenderSize[1] = Sizei::Min(Sizei(rtSize.w / 2, rtSize.h), recommenedTex1Size); m_data.eyeRenderSize[0].set(eyeRenderSize[0].w, eyeRenderSize[0].h); m_data.eyeRenderSize[1].set(eyeRenderSize[1].w, eyeRenderSize[1].h); m_data.hmdResolution.x = m_device->Resolution.w; m_data.hmdResolution.y = m_device->Resolution.h; bool IsLowPersistence = true; bool DynamicPrediction = false; bool VsyncEnabled = false; // Hmd caps. unsigned hmdCaps = (VsyncEnabled ? 0 : ovrHmdCap_NoVSync); if (IsLowPersistence) hmdCaps |= ovrHmdCap_LowPersistence; // ovrHmdCap_DynamicPrediction - enables internal latency feedback if (DynamicPrediction) hmdCaps |= ovrHmdCap_DynamicPrediction; // ovrHmdCap_DisplayOff - turns off the display //if (DisplaySleep) hmdCaps |= ovrHmdCap_DisplayOff; //if (!MirrorToWindow) hmdCaps |= ovrHmdCap_NoMirrorToWindow; ovrHmd_SetEnabledCaps(m_device, hmdCaps); unsigned sensorCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection; if (!IsTrackingConnected()) printf("Oculus tracking device not detected!\n"); sensorCaps |= ovrTrackingCap_Position; if (StartTrackingCaps != sensorCaps) { ovrHmd_ConfigureTracking(m_device, sensorCaps, 0); StartTrackingCaps = sensorCaps; } }
void OculusWorldDemoApp::CalculateHmdValues() { // Initialize eye rendering information for ovrHmd_Configure. // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations. ovrFovPort eyeFov[2]; eyeFov[0] = HmdDesc.DefaultEyeFov[0]; eyeFov[1] = HmdDesc.DefaultEyeFov[1]; // Clamp Fov based on our dynamically adjustable FovSideTanMax. // Most apps should use the default, but reducing Fov does reduce rendering cost. eyeFov[0] = FovPort::Min(eyeFov[0], FovPort(FovSideTanMax)); eyeFov[1] = FovPort::Min(eyeFov[1], FovPort(FovSideTanMax)); if (ForceZeroIpd) { // ForceZeroIpd does three things: // 1) Sets FOV to maximum symmetrical FOV based on both eyes // 2) Sets eye ViewAdjust values to 0.0 (effective IPD == 0) // 3) Uses only the Left texture for rendering. eyeFov[0] = FovPort::Max(eyeFov[0], eyeFov[1]); eyeFov[1] = eyeFov[0]; Sizei recommenedTexSize = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left, eyeFov[0], DesiredPixelDensity); Sizei textureSize = EnsureRendertargetAtLeastThisBig(Rendertarget_Left, recommenedTexSize); EyeRenderSize[0] = Sizei::Min(textureSize, recommenedTexSize); EyeRenderSize[1] = EyeRenderSize[0]; // Store texture pointers that will be passed for rendering. EyeTexture[0] = RenderTargets[Rendertarget_Left].Tex; EyeTexture[0].Header.TextureSize = textureSize; EyeTexture[0].Header.RenderViewport = Recti(EyeRenderSize[0]); // Right eye is the same. EyeTexture[1] = EyeTexture[0]; } else { // Configure Stereo settings. Default pixel density is 1.0f. Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left, eyeFov[0], DesiredPixelDensity); Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Right, eyeFov[1], DesiredPixelDensity); if (RendertargetIsSharedByBothEyes) { Sizei rtSize(recommenedTex0Size.w + recommenedTex1Size.w, Alg::Max(recommenedTex0Size.h, recommenedTex1Size.h)); // Use returned size as the actual RT size may be different due to HW limits. rtSize = EnsureRendertargetAtLeastThisBig(Rendertarget_BothEyes, rtSize); // Don't draw more then recommended size; this also ensures that resolution reported // in the overlay HUD size is updated correctly for FOV/pixel density change. EyeRenderSize[0] = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex0Size); EyeRenderSize[1] = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex1Size); // Store texture pointers that will be passed for rendering. // Same texture is used, but with different viewports. EyeTexture[0] = RenderTargets[Rendertarget_BothEyes].Tex; EyeTexture[0].Header.TextureSize = rtSize; EyeTexture[0].Header.RenderViewport = Recti(Vector2i(0), EyeRenderSize[0]); EyeTexture[1] = RenderTargets[Rendertarget_BothEyes].Tex; EyeTexture[1].Header.TextureSize = rtSize; EyeTexture[1].Header.RenderViewport = Recti(Vector2i((rtSize.w+1)/2, 0), EyeRenderSize[1]); } else { Sizei tex0Size = EnsureRendertargetAtLeastThisBig(Rendertarget_Left, recommenedTex0Size); Sizei tex1Size = EnsureRendertargetAtLeastThisBig(Rendertarget_Right, recommenedTex1Size); EyeRenderSize[0] = Sizei::Min(tex0Size, recommenedTex0Size); EyeRenderSize[1] = Sizei::Min(tex1Size, recommenedTex1Size); // Store texture pointers and viewports that will be passed for rendering. EyeTexture[0] = RenderTargets[Rendertarget_Left].Tex; EyeTexture[0].Header.TextureSize = tex0Size; EyeTexture[0].Header.RenderViewport = Recti(EyeRenderSize[0]); EyeTexture[1] = RenderTargets[Rendertarget_Right].Tex; EyeTexture[1].Header.TextureSize = tex1Size; EyeTexture[1].Header.RenderViewport = Recti(EyeRenderSize[1]); } } // Hmd caps. unsigned hmdCaps = (VsyncEnabled ? 0 : ovrHmdCap_NoVSync) | ovrHmdCap_LatencyTest; if (IsLowPersistence) hmdCaps |= ovrHmdCap_LowPersistence; if (DynamicPrediction) hmdCaps |= ovrHmdCap_DynamicPrediction; ovrHmd_SetEnabledCaps(Hmd, hmdCaps); ovrRenderAPIConfig config = pRender->Get_ovrRenderAPIConfig(); unsigned distortionCaps = ovrDistortionCap_Chromatic; if (TimewarpEnabled) distortionCaps |= ovrDistortionCap_TimeWarp; if (!ovrHmd_ConfigureRendering( Hmd, &config, distortionCaps, eyeFov, EyeRenderDesc )) { // Fail exit? TBD return; } if (ForceZeroIpd) { // Remove IPD adjust EyeRenderDesc[0].ViewAdjust = Vector3f(0); EyeRenderDesc[1].ViewAdjust = Vector3f(0); } // ovrHmdCap_LatencyTest - enables internal latency feedback unsigned sensorCaps = ovrSensorCap_Orientation|ovrSensorCap_YawCorrection; if (PositionTrackingEnabled) sensorCaps |= ovrSensorCap_Position; if (StartSensorCaps != sensorCaps) { ovrHmd_StartSensor(Hmd, sensorCaps, 0); StartSensorCaps = sensorCaps; } // Calculate projections Projection[0] = ovrMatrix4f_Projection(EyeRenderDesc[0].Fov, 0.01f, 10000.0f, true); Projection[1] = ovrMatrix4f_Projection(EyeRenderDesc[1].Fov, 0.01f, 10000.0f, true); float orthoDistance = 0.8f; // 2D is 0.8 meter from camera Vector2f orthoScale0 = Vector2f(1.0f) / Vector2f(EyeRenderDesc[0].PixelsPerTanAngleAtCenter); Vector2f orthoScale1 = Vector2f(1.0f) / Vector2f(EyeRenderDesc[1].PixelsPerTanAngleAtCenter); OrthoProjection[0] = ovrMatrix4f_OrthoSubProjection(Projection[0], orthoScale0, orthoDistance, EyeRenderDesc[0].ViewAdjust.x); OrthoProjection[1] = ovrMatrix4f_OrthoSubProjection(Projection[1], orthoScale1, orthoDistance, EyeRenderDesc[1].ViewAdjust.x); }