void OculusVRDebug::OnRender(const ovrSession session, const ovrTrackingState &trackingState, const ovrEyeRenderDesc *eyeRenderDescs, const ovrSizei &eyeTextureSize) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glActiveTexture(GL_TEXTURE0); static const float xPos = -0.3f; static const float ySpacing = 0.05f; std::stringstream statsStream; char buf[128]; float hmdYaw, hmdPitch, hmdRoll; ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session); OVR::Quatf headOrientation(trackingState.HeadPose.ThePose.Orientation); headOrientation.GetEulerAngles<OVR::Axis_Y, OVR::Axis_X, OVR::Axis_Z>(&hmdYaw, &hmdPitch, &hmdRoll); OVR::OVR_sprintf(buf, sizeof(buf), "HMD YPR:%2.0f %2.0f %2.0f HMD: %s", hmdYaw * PIdiv180inv, hmdPitch * PIdiv180inv, hmdRoll * PIdiv180inv, hmdDesc.ProductName); m_font->drawText(buf, xPos, 0.1f, 0.f); OVR::OVR_sprintf(buf, sizeof(buf), "FPS: %.1f ms/frame: %.1f Frame: %03d %d", m_fps, m_secondsPerFrame * 1000.0f, m_frameCounter, m_totalFrameCounter % 2); m_font->drawText(buf, xPos, 0.1f - ySpacing, 0.f); OVR::OVR_sprintf(buf, sizeof(buf), "Pos: %2.2f %2.2f %2.2f Tracking: %s", g_cameraDirector.GetActiveCamera()->Position().m_x, g_cameraDirector.GetActiveCamera()->Position().m_y, g_cameraDirector.GetActiveCamera()->Position().m_z, trackingState.StatusFlags & ovrStatus_PositionTracked ? "YES" : "NO"); m_font->drawText(buf, xPos, 0.1f - ySpacing * 2.f, 0.f); OVR::OVR_sprintf(buf, sizeof(buf), "EyeHeight: %2.2f IPD: %2.1fmm", ovr_GetFloat(session, OVR_KEY_EYE_HEIGHT, 0.f), ovr_GetFloat(session, OVR_KEY_IPD, 0.f) * 1000.f); m_font->drawText(buf, xPos, 0.1f - ySpacing * 3.f, 0.f); // Average FOVs OVR::FovPort leftFov = eyeRenderDescs[0].Fov; OVR::FovPort rightFov = eyeRenderDescs[1].Fov; // Rendered size changes based on selected options & dynamic rendering. OVR::OVR_sprintf(buf, sizeof(buf), "FOV %2.1fx%2.1f, Resolution: %ix%i", (leftFov.GetHorizontalFovDegrees() + rightFov.GetHorizontalFovDegrees()) * 0.5f, (leftFov.GetVerticalFovDegrees() + rightFov.GetVerticalFovDegrees()) * 0.5, eyeTextureSize.w, eyeTextureSize.h); m_font->drawText(buf, xPos, 0.1f - ySpacing * 4.f, 0.f); // latency readings float latencies[5] = {}; if (ovr_GetFloatArray(session, "DK2Latency", latencies, 5) == 5) { char text[5][32]; for (int i = 0; i < 5; ++i) { FormatLatencyReading(text[i], sizeof(text[i]), latencies[i]); } statsStream.str(""); statsStream << "M2P Latency Ren: " << text[0] << " TWrp: " << text[1]; m_font->drawText(statsStream.str(), xPos, 0.1f - ySpacing * 5.f, 0.f); statsStream.str(""); statsStream << "PostPresent: " << text[2] << " Err: " << text[3] << " " << text[4]; m_font->drawText(statsStream.str(), xPos, 0.1f - ySpacing * 6.f, 0.f); } }
void FOculusRiftHMD::DrawDebug(UCanvas* Canvas) { #if !UE_BUILD_SHIPPING check(IsInGameThread()); const auto frame = GetFrame(); if (frame) { FSettings* FrameSettings = frame->GetSettings(); if (FrameSettings->Flags.bDrawGrid) { bool bStereo = Canvas->Canvas->IsStereoRendering(); Canvas->Canvas->SetStereoRendering(false); bool bPopTransform = false; if (FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.w != FMath::CeilToInt(Canvas->ClipX) || FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.h != Canvas->ClipY) { // scale if resolution of the Canvas does not match the viewport bPopTransform = true; Canvas->Canvas->PushAbsoluteTransform(FScaleMatrix( FVector((Canvas->ClipX) / float(FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.w), Canvas->ClipY / float(FrameSettings->EyeRenderDesc[0].DistortedViewport.Size.h), 1.0f))); } const FColor cNormal(255, 0, 0); const FColor cSpacer(255, 255, 0); const FColor cMid(0, 128, 255); for (int eye = 0; eye < 2; ++eye) { int lineStep = 1; int midX = 0; int midY = 0; int limitX = 0; int limitY = 0; int renderViewportX = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Pos.x; int renderViewportY = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Pos.y; int renderViewportW = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Size.w; int renderViewportH = FrameSettings->EyeRenderDesc[eye].DistortedViewport.Size.h; lineStep = 48; OVR::Vector2f rendertargetNDC = OVR::FovPort(FrameSettings->EyeRenderDesc[eye].Fov).TanAngleToRendertargetNDC(OVR::Vector2f(0.0f)); midX = (int)((rendertargetNDC.x * 0.5f + 0.5f) * (float)renderViewportW + 0.5f); midY = (int)((rendertargetNDC.y * 0.5f + 0.5f) * (float)renderViewportH + 0.5f); limitX = FMath::Max(renderViewportW - midX, midX); limitY = FMath::Max(renderViewportH - midY, midY); int spacerMask = (lineStep << 1) - 1; for (int xp = 0; xp < limitX; xp += lineStep) { float x[4]; float y[4]; x[0] = (float)(midX + xp) + renderViewportX; y[0] = (float)0 + renderViewportY; x[1] = (float)(midX + xp) + renderViewportX; y[1] = (float)renderViewportH + renderViewportY; x[2] = (float)(midX - xp) + renderViewportX; y[2] = (float)0 + renderViewportY; x[3] = (float)(midX - xp) + renderViewportX; y[3] = (float)renderViewportH + renderViewportY; if (xp == 0) { RenderLines(Canvas->Canvas, 1, cMid, x, y); } else if ((xp & spacerMask) == 0) { RenderLines(Canvas->Canvas, 2, cSpacer, x, y); } else { RenderLines(Canvas->Canvas, 2, cNormal, x, y); } } for (int yp = 0; yp < limitY; yp += lineStep) { float x[4]; float y[4]; x[0] = (float)0 + renderViewportX; y[0] = (float)(midY + yp) + renderViewportY; x[1] = (float)renderViewportW + renderViewportX; y[1] = (float)(midY + yp) + renderViewportY; x[2] = (float)0 + renderViewportX; y[2] = (float)(midY - yp) + renderViewportY; x[3] = (float)renderViewportW + renderViewportX; y[3] = (float)(midY - yp) + renderViewportY; if (yp == 0) { RenderLines(Canvas->Canvas, 1, cMid, x, y); } else if ((yp & spacerMask) == 0) { RenderLines(Canvas->Canvas, 2, cSpacer, x, y); } else { RenderLines(Canvas->Canvas, 2, cNormal, x, y); } } } if (bPopTransform) { Canvas->Canvas->PopTransform(); // optional scaling } Canvas->Canvas->SetStereoRendering(bStereo); } if (IsStereoEnabled() && FrameSettings->Flags.bShowStats) { static const FColor TextColor(0,255,0); // Pick a larger font on console. UFont* const Font = FPlatformProperties::SupportsWindowedMode() ? GEngine->GetSmallFont() : GEngine->GetMediumFont(); const int32 RowHeight = FMath::TruncToInt(Font->GetMaxCharHeight() * 1.1f); float ClipX = Canvas->ClipX; float ClipY = Canvas->ClipY; float LeftPos = 0; ClipX -= 100; //ClipY = ClipY * 0.60; LeftPos = ClipX * 0.3f; float TopPos = ClipY * 0.4f; int32 X = (int32)LeftPos; int32 Y = (int32)TopPos; FString Str, StatusStr; // First row // Str = FString::Printf(TEXT("TimeWarp: %s"), (FrameSettings->Flags.bTimeWarp) ? TEXT("ON") : TEXT("OFF")); // Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); // // Y += RowHeight; //Str = FString::Printf(TEXT("VSync: %s"), (FrameSettings->Flags.bVSync) ? TEXT("ON") : TEXT("OFF")); //Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); //Y += RowHeight; Str = FString::Printf(TEXT("Upd on GT/RT: %s / %s"), (!FrameSettings->Flags.bDoNotUpdateOnGT) ? TEXT("ON") : TEXT("OFF"), (FrameSettings->Flags.bUpdateOnRT) ? TEXT("ON") : TEXT("OFF")); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; // static IConsoleVariable* CFinishFrameVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.FinishCurrentFrame")); // int finFr = CFinishFrameVar->GetInt(); // Str = FString::Printf(TEXT("FinFr: %s"), (finFr || FrameSettings->Flags.bTimeWarp) ? TEXT("ON") : TEXT("OFF")); // Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); // // Y += RowHeight; Str = FString::Printf(TEXT("PD: %.2f"), FrameSettings->PixelDensity); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("QueueAhead: %s"), (FrameSettings->bQueueAheadEnabled) ? TEXT("ON") : TEXT("OFF")); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("FOV V/H: %.2f / %.2f deg"), FMath::RadiansToDegrees(FrameSettings->VFOVInRadians), FMath::RadiansToDegrees(FrameSettings->HFOVInRadians)); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("W-to-m scale: %.2f uu/m"), frame->WorldToMetersScale); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); if ((FrameSettings->SupportedHmdCaps & ovrHmdCap_DynamicPrediction) != 0) { float latencies[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; const int numOfEntries = sizeof(latencies) / sizeof(latencies[0]); if (ovrHmd_GetFloatArray(Hmd, "DK2Latency", latencies, numOfEntries) == numOfEntries) { Y += RowHeight; char buf[numOfEntries][20]; char destStr[100]; FCStringAnsi::Snprintf(destStr, sizeof(destStr), "Latency, ren: %s tw: %s pp: %s err: %s %s", FormatLatencyReading(buf[0], sizeof(buf[0]), latencies[0]), FormatLatencyReading(buf[1], sizeof(buf[1]), latencies[1]), FormatLatencyReading(buf[2], sizeof(buf[2]), latencies[2]), FormatLatencyReading(buf[3], sizeof(buf[3]), latencies[3]), FormatLatencyReading(buf[4], sizeof(buf[4]), latencies[4])); Str = ANSI_TO_TCHAR(destStr); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); } } // Second row X = (int32)LeftPos + 200; Y = (int32)TopPos; StatusStr = ((FrameSettings->SupportedTrackingCaps & ovrTrackingCap_Position) != 0) ? ((FrameSettings->Flags.bHmdPosTracking) ? TEXT("ON") : TEXT("OFF")) : TEXT("UNSUP"); Str = FString::Printf(TEXT("PosTr: %s"), *StatusStr); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("Vision: %s"), (frame->Flags.bHaveVisionTracking) ? TEXT("ACQ") : TEXT("LOST")); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; Str = FString::Printf(TEXT("IPD: %.2f mm"), FrameSettings->InterpupillaryDistance*1000.f); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; StatusStr = ((FrameSettings->SupportedHmdCaps & ovrHmdCap_LowPersistence) != 0) ? ((FrameSettings->Flags.bLowPersistenceMode) ? TEXT("ON") : TEXT("OFF")) : TEXT("UNSUP"); Str = FString::Printf(TEXT("LowPers: %s"), *StatusStr); Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); Y += RowHeight; // StatusStr = ((FrameSettings->SupportedDistortionCaps & ovrDistortionCap_Overdrive) != 0) ? // ((FrameSettings->Flags.bOverdrive) ? TEXT("ON") : TEXT("OFF")) : TEXT("UNSUP"); // Str = FString::Printf(TEXT("Overdrive: %s"), *StatusStr); // Canvas->Canvas->DrawShadowedString(X, Y, *Str, Font, TextColor); // Y += RowHeight; } //TODO: Where can I get context!? UWorld* MyWorld = GWorld; if (FrameSettings->Flags.bDrawTrackingCameraFrustum) { DrawDebugTrackingCameraFrustum(MyWorld, Canvas->SceneView->ViewRotation, Canvas->SceneView->ViewLocation); } if (Canvas && Canvas->SceneView) { DrawSeaOfCubes(MyWorld, Canvas->SceneView->ViewLocation); } } #endif // #if !UE_BUILD_SHIPPING }
void OculusWorldDemoApp::RenderTextInfoHud(float textHeight) { // View port & 2D ortho projection must be set before call. float hmdYaw, hmdPitch, hmdRoll; switch(TextScreen) { case Text_Info: { char buf[512], gpustat[256]; // Average FOVs. FovPort leftFov = EyeRenderDesc[0].Fov; FovPort rightFov = EyeRenderDesc[1].Fov; // Rendered size changes based on selected options & dynamic rendering. int pixelSizeWidth = EyeTexture[0].Header.RenderViewport.Size.w + ((!ForceZeroIpd) ? EyeTexture[1].Header.RenderViewport.Size.w : 0); int pixelSizeHeight = ( EyeTexture[0].Header.RenderViewport.Size.h + EyeTexture[1].Header.RenderViewport.Size.h ) / 2; // No DK2, no message. char latency2Text[128] = ""; { //float latency2 = ovrHmd_GetMeasuredLatencyTest2(Hmd) * 1000.0f; // show it in ms //if (latency2 > 0) // OVR_sprintf(latency2Text, sizeof(latency2Text), "%.2fms", latency2); float latencies[3] = { 0.0f, 0.0f, 0.0f }; if (ovrHmd_GetFloatArray(Hmd, "DK2Latency", latencies, 3) == 3) { char latencyText0[32], latencyText1[32], latencyText2[32]; FormatLatencyReading(latencyText0, sizeof(latencyText0), latencies[0]); FormatLatencyReading(latencyText1, sizeof(latencyText1), latencies[1]); FormatLatencyReading(latencyText2, sizeof(latencyText2), latencies[2]); OVR_sprintf(latency2Text, sizeof(latency2Text), " DK2 Latency Ren: %s TWrp: %s\n" " PostPresent: %s ", latencyText0, latencyText1, latencyText2); } } ThePlayer.HeadPose.Rotation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&hmdYaw, &hmdPitch, &hmdRoll); OVR_sprintf(buf, sizeof(buf), " HMD YPR:%4.0f %4.0f %4.0f Player Yaw: %4.0f\n" " FPS: %.1f ms/frame: %.1f Frame: %d\n" " Pos: %3.2f, %3.2f, %3.2f HMD: %s\n" " EyeHeight: %3.2f, IPD: %3.1fmm\n" //", Lens: %s\n" " FOV %3.1fx%3.1f, Resolution: %ix%i\n" "%s", RadToDegree(hmdYaw), RadToDegree(hmdPitch), RadToDegree(hmdRoll), RadToDegree(ThePlayer.BodyYaw.Get()), FPS, SecondsPerFrame * 1000.0f, FrameCounter, ThePlayer.BodyPos.x, ThePlayer.BodyPos.y, ThePlayer.BodyPos.z, //GetDebugNameHmdType ( TheHmdRenderInfo.HmdType ), HmdDesc.ProductName, ThePlayer.UserEyeHeight, ovrHmd_GetFloat(Hmd, OVR_KEY_IPD, 0) * 1000.0f, //( EyeOffsetFromNoseLeft + EyeOffsetFromNoseRight ) * 1000.0f, //GetDebugNameEyeCupType ( TheHmdRenderInfo.EyeCups ), // Lens/EyeCup not exposed (leftFov.GetHorizontalFovDegrees() + rightFov.GetHorizontalFovDegrees()) * 0.5f, (leftFov.GetVerticalFovDegrees() + rightFov.GetVerticalFovDegrees()) * 0.5f, pixelSizeWidth, pixelSizeHeight, latency2Text ); size_t texMemInMB = pRender->GetTotalTextureMemoryUsage() / 1058576; if (texMemInMB) { OVR_sprintf(gpustat, sizeof(gpustat), " GPU Tex: %u MB", texMemInMB); OVR_strcat(buf, sizeof(buf), gpustat); } DrawTextBox(pRender, 0.0f, 0.0f, textHeight, buf, DrawText_Center); } break; case Text_Timing: Profiler.DrawOverlay(pRender); break; case Text_Help1: DrawTextBox(pRender, 0.0f, 0.0f, textHeight, HelpText1, DrawText_Center); break; case Text_Help2: DrawTextBox(pRender, 0.0f, 0.0f, textHeight, HelpText2, DrawText_Center); break; case Text_None: break; default: OVR_ASSERT ( !"Missing text screen" ); break; } }