Files
planet/ue_client/Source/PlanetClient/StereoRenderingManager.cpp
linkong 1e6f4b338b feat: add UE5 LED display client — backend API, C++ source, stereo framework
Backend:
- Add /api/v1/ue/* endpoints (compute-points, cables, landing-points, satellites, status)
  returning flat JSON optimised for UE5 C++ parsing

UE5 client (ue_client/):
- PlanetDataManager: HTTP fetch + local mock JSON loader, spawns ComputePointActors
- ComputePointActor / InteractiveObjectBase: hover/select state, material switching
- GlobeInteractionComponent: drag-to-rotate via CesiumGeoreference origin shift, inertia, zoom
- StereoRenderingManager: runtime SbS/TbB stereo toggle, IPD control (format TBD)
- MotionCaptureInterface: protocol-agnostic gesture/rotate/zoom delegate interface (impl TBD)
- PlanetPlayerController: unified mouse + motion-capture input routing
- PlanetGameMode, Build.cs, Config, mock data

Docs:
- ue5_mvp_fused_plan.md updated to v3.0 for LED display context
- ue_client_setup_guide.md: step-by-step editor setup guide
- ue_todo.md: pending items blocked on vendor answers (stereo format + mocap protocol)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 18:39:05 +08:00

132 lines
4.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "StereoRenderingManager.h"
#include "Engine/Engine.h"
#include "Engine/World.h"
AStereoRenderingManager::AStereoRenderingManager()
{
PrimaryActorTick.bCanEverTick = false;
}
void AStereoRenderingManager::BeginPlay()
{
Super::BeginPlay();
if (bAutoEnableOnPlay)
{
EnableStereo(DefaultStereoMode);
}
else
{
UE_LOG(LogTemp, Log,
TEXT("StereoRenderingManager: 立体渲染未自动启动。"
"确认视频处理器格式后,在 Details 面板勾选 bAutoEnableOnPlay。"));
}
}
// ---------------------------------------------------------------------------
// 公开 API
// ---------------------------------------------------------------------------
void AStereoRenderingManager::EnableStereo(EStereoOutputMode Mode)
{
if (Mode == EStereoOutputMode::Off)
{
DisableStereo();
return;
}
// TODO供应商回复后检查这里的命令是否与视频处理器匹配:
//
// UE5 内置立体模式通过以下方式启用。
// 如果视频处理器需要特殊格式,可能需要修改 stereo mode 参数。
//
// 参考命令:
// stereo on —— 开启立体渲染(需要 VR 设备或自定义立体设备)
// r.StereoRendering 1 —— 软件层立体渲染标志
// vr.StereoMode <n> —— 0=SbS full, 1=SbS half, 2=TbB full, 3=TbB half
//
// 目前使用 r.StereoRendering 的"双视口"方式,兼容性最好。
switch (Mode)
{
case EStereoOutputMode::SideBySide:
// Side-by-Side左半=左眼,右半=右眼,总分辨率 2x 宽
ExecConsoleCommand(TEXT("r.StereoRendering 1"));
ExecConsoleCommand(TEXT("stereo on"));
ExecConsoleCommand(TEXT("vr.StereoMode 0")); // TODO: 根据实际效果调整
break;
case EStereoOutputMode::TopBottom:
// Top-Bottom上半=左眼,下半=右眼,总分辨率 2x 高
ExecConsoleCommand(TEXT("r.StereoRendering 1"));
ExecConsoleCommand(TEXT("stereo on"));
ExecConsoleCommand(TEXT("vr.StereoMode 2")); // TODO: 根据实际效果调整
break;
case EStereoOutputMode::FrameSequential:
// 本项目屏幕 60Hz帧序列需要 120Hz暂不支持
UE_LOG(LogTemp, Warning,
TEXT("StereoRenderingManager: Frame Sequential 需要 120Hz 输出,"
"当前屏幕规格不支持,已忽略。"));
return;
default: break;
}
// 设置 IPD
SetIPD(IPDCm);
bStereoActive = true;
CurrentMode = Mode;
UE_LOG(LogTemp, Log, TEXT("StereoRenderingManager: 立体渲染已开启,模式=%sIPD=%.1fcm"),
*ModeToString(Mode), IPDCm);
}
void AStereoRenderingManager::DisableStereo()
{
ExecConsoleCommand(TEXT("stereo off"));
ExecConsoleCommand(TEXT("r.StereoRendering 0"));
bStereoActive = false;
CurrentMode = EStereoOutputMode::Off;
UE_LOG(LogTemp, Log, TEXT("StereoRenderingManager: 立体渲染已关闭,切回 2D"));
}
void AStereoRenderingManager::ToggleStereo()
{
if (bStereoActive)
DisableStereo();
else
EnableStereo(DefaultStereoMode);
}
void AStereoRenderingManager::SetIPD(float NewIPDCm)
{
IPDCm = FMath::Clamp(NewIPDCm, 1.f, 10.f);
// UE5 以米为单位设置 IPD
FString Cmd = FString::Printf(TEXT("vr.HMDIPDInMeters %.4f"), IPDCm / 100.f);
ExecConsoleCommand(Cmd);
}
// ---------------------------------------------------------------------------
// 内部工具
// ---------------------------------------------------------------------------
void AStereoRenderingManager::ExecConsoleCommand(const FString& Cmd)
{
if (GEngine)
{
GEngine->Exec(GetWorld(), *Cmd);
}
}
FString AStereoRenderingManager::ModeToString(EStereoOutputMode Mode)
{
switch (Mode)
{
case EStereoOutputMode::SideBySide: return TEXT("SideBySide");
case EStereoOutputMode::TopBottom: return TEXT("TopBottom");
case EStereoOutputMode::FrameSequential: return TEXT("FrameSequential");
default: return TEXT("Off");
}
}