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>
This commit is contained in:
linkong
2026-04-14 18:39:05 +08:00
parent d9adaf4134
commit 1e6f4b338b
28 changed files with 2781 additions and 949 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,319 @@
# UE5 客户端手动操作指南
> 本指南对应 `ue_client/` 目录下已生成的所有代码和配置。
> 代码已写好,你只需要做编辑器里的点击操作。
> 遇到红色错误先看文末"常见问题"章节。
---
## 前置条件
| 软件 | 版本 | 下载地址 |
|------|------|---------|
| Unreal Engine | **5.3** | Epic Games Launcher → Library → 5.3 |
| Cesium for Unreal | 最新 | 直接在下一步从 Marketplace 安装 |
| Visual Studio | 2022 Community | visualstudio.microsoft.com安装 C++ 游戏开发工作负载) |
> **注意**Cesium for Unreal 必须先安装,否则代码会编译失败。
---
## 第一阶段Phase A本地演示版不需要后端
### 步骤 1安装 Cesium for Unreal
1. 打开 **Epic Games Launcher**
2. 顶部切换到 **Unreal Engine** 选项卡
3. 左侧点击 **Marketplace** → 搜索 `Cesium for Unreal`
4. 点击 **免费获取**Free然后点击 **安装到引擎** → 选择 5.3
5. 等待安装完成
---
### 步骤 2打开项目
1. 打开 **Epic Games Launcher****Unreal Engine****Library**
2. 找到 5.3,点击右侧 **Launch** 旁边的下拉箭头 → **Browse**
3. 导航到 `planet/ue_client/`,选择 `PlanetClient.uproject`,点击打开
4. UE 会提示"缺少模块,需要重新编译" → 点击 **Yes**
5. 等待编译完成(首次约 5-10 分钟)
> 如果编译报错:见文末"常见问题 → 编译错误"
---
### 步骤 3创建新关卡
1. 菜单栏 → **File****New Level**
2. 选择 **Empty Level**(空关卡)
3. 保存:**File** → **Save Current Level As**
路径:`Content/Maps/`,名称:`EarthMap`
4. 点击 **Save**
---
### 步骤 4添加 Cesium 地球
1. 顶部菜单栏 → **Cesium**如果没有此菜单说明插件未激活Edit → Plugins → 搜索 Cesium → 勾选 Enable → 重启)
2. 在 Cesium 面板里点击 **Add Blank 3D Tiles Tileset** — 这会自动在场景里添加:
- `CesiumGeoreference` Actor
- `Cesium3DTileset` Actor地球瓦片
3. 再点击 **Add Cesium ion Bing Maps Aerial** 添加卫星影像底图(需要免费 Cesium ion 账号)
> 如果没有 Cesium ion 账号Cesium 菜单 → Connect to Cesium ion → 注册免费账号
---
### 步骤 5添加相机 Pawn
1. 菜单栏 → **Cesium** → 找到 **Dynamic Pawn**(名称可能是 `CesiumFlyToComponent` 相关的 Blueprint
**或者**Content Browser → 顶部搜索框输入 `DynamicPawn` → 找到插件内容里的 `DynamicPawn` → 拖入场景
2.**Outliner** 面板里点击刚拖入的 `DynamicPawn`
3.**Details** 面板里,找到 **Auto Possess Player** → 改为 **Player 0**
> 这样游戏启动时摄像机会自动使用这个可飞行的地球相机。
---
### 步骤 6配置 GameMode
1. 菜单栏 → **Window****World Settings**(如果没有,也可以在 Details Panel 里找)
2.**World Settings** 面板里找到 **Game Mode Override**
3. 点击下拉框 → 搜索 `PlanetGameMode` → 选择它
4. 找到 **Default Pawn Class** → 改为上一步拖入的 `DynamicPawn`
---
### 步骤 7创建 ComputePoint Blueprint
这步把我写的 C++ 类包装成可以在编辑器里配置材质的 Blueprint。
1. **Content Browser** → 空白处右键 → **Blueprint Class**
2. 搜索父类:输入 `ComputePointActor` → 找到 `AComputePointActor` → 点击 **Select**
3. 命名为 `BP_ComputePointActor`,保存到 `Content/Blueprints/`
**配置 BP_ComputePointActor 的网格和材质:**
4. 双击打开 `BP_ComputePointActor`
5. 在左侧 **Components** 面板里点击 `SphereMesh`
6. 在右侧 **Details** 面板里找到 **Static Mesh** → 点击下拉 → 搜索 `Sphere` → 选择 **Engine/BasicShapes/Sphere**
7. 找到 **Material** → 点击下拉 → 搜索 `M_Basic_Wall` 或者创建新材质(见下方)
**创建三种状态的材质(颜色点即可):**
8. Content Browser → 右键 → **Material** → 命名 `M_PointNormal`
- 双击打开 → 右键空白区域 → 搜索 `Constant3Vector` → 连接到 `Base Color`
- 颜色设为橙色:`(1.0, 0.4, 0.0)`
- 保存
9. 同样方式创建 `M_PointHovered`(颜色白色 `1,1,1`)和 `M_PointSelected`(颜色青色 `0,1,1`
**回到 BP_ComputePointActor**
10.**Details** 面板里:
- **Normal Material** → 选 `M_PointNormal`
- **Hovered Material** → 选 `M_PointHovered`
- **Selected Material** → 选 `M_PointSelected`
- **Point Scale** → `80000`(根据实际效果调整)
11. 点击左上角 **Compile****Save**
---
### 步骤 8放置 DataManager 并配置
1. **Content Browser** → 右键 → **Blueprint Class** → 父类搜索 `PlanetDataManager` → 选择 `APlanetDataManager`
2. 命名为 `BP_PlanetDataManager`,保存到 `Content/Blueprints/`
3.`BP_PlanetDataManager` **拖入场景**Outliner 里会出现它)
4. 在 Outliner 里点击它 → 在 **Details** 面板里配置:
- **Use Local Mock Data** → ✅ **勾选**Phase A 不需要后端)
- **Mock Data Path** → 留空(代码会自动找 `Content/Data/mock_compute_points.json`
- **Compute Point Class** → 选择 `BP_ComputePointActor`
- **Point Altitude Meters** → `50000`(海拔 50km可调
---
### 步骤 9测试 Phase A
1. 点击顶部工具栏绿色 **Play** 按钮(或 Alt+P
2. 地球应该加载卫星影像
3. 应该看到 10 个橙色球体分布在地球上(对应 mock JSON 里的 TOP500 超算)
4. 鼠标移到球体上 → 变白色Hover
5. 点击球体 → 变青色Selected
**验证通过标准:**
- [x] 地球可见
- [x] 橙色球体出现在正确位置(美国、日本、荷兰、芬兰等)
- [x] 悬停变色
- [x] 点击变色
---
## 第二阶段Phase B连接真实后端
### 步骤 10确认后端新接口可用
后端代码已添加新路由,先验证它已经运行:
```bash
# 在 WSL 或终端里
curl http://localhost:8000/api/v1/ue/status
```
应该返回类似:
```json
{"ok": true, "server_time": "...", "compute_points_count": 500, ...}
```
如果 curl 失败:
- 检查 `planet.sh` 是否在运行(`./planet.sh start`
- 检查 WSL2 → Windows 的网络:在 UE 里使用 `172.x.x.x`WSL 网关地址)而不是 `localhost`
---
### 步骤 11获取 WSL2 → Windows 的正确 IP
在 WSL 终端里运行:
```bash
cat /etc/resolv.conf | grep nameserver | awk '{print $2}'
```
记下这个 IP例如 `172.22.32.1`)。
---
### 步骤 12切换 DataManager 到实时模式
1. 在 Outliner 里点击 `BP_PlanetDataManager`
2. Details 面板里:
- **Use Local Mock Data** → **取消勾选**
- **Backend Base URL** → 填入 `http://172.22.32.1:8000`(你的实际 WSL IP
3. 重新 Play → DataManager 会通过 HTTP 拉取真实数据
---
### 步骤 13绑定点击事件显示信息卡可选需要 UMG
这步是可选的,需要创建一个 Widget Blueprint 来显示选中点的信息。
1. Content Browser → 右键 → **User Interface****Widget Blueprint**
2. 命名为 `WBP_PointInfo`
**设计 Widget 布局:**
3. 双击打开 `WBP_PointInfo`
4. 从左侧 **Palette** 拖入以下控件到画布:
- `Canvas Panel`(容器,设置为全屏)
- `Border`(右下角定位,用作信息卡背景,宽 300高 200
- `Text Block` × 4名称、排名、算力、国家
**绑定事件Blueprint 里操作):**
5. 打开 `BP_PlanetDataManager` 的 Event Graph
6. 找到 **BeginPlay** 节点
7. 拖出线 → 搜索 **Bind Event to On Point Selected**(这是我在 PlayerController 里定义的委托)
> 具体蓝图连线:从 PlayerController 获取 OnPointSelected → Bind → 在回调里 Create Widget WBP_PointInfo → Add to Viewport → Set 各个文本
---
## 文件结构总览
```
ue_client/
PlanetClient.uproject ← UE 项目入口
Config/
DefaultGame.ini ← GameMode 配置
DefaultEngine.ini ← 渲染/引擎设置
DefaultInput.ini ← 键鼠输入绑定
Content/
Data/
mock_compute_points.json ← Phase A 本地测试数据10个超算
Maps/
EarthMap.umap ← 你在步骤3创建的关卡
Blueprints/
BP_ComputePointActor ← 步骤7创建
BP_PlanetDataManager ← 步骤8创建
Source/
PlanetClient/
PlanetClient.Build.cs ← 模块依赖HTTP、JSON、Cesium
PlanetClient.h/.cpp ← 模块入口
PlanetDataTypes.h ← 数据结构定义FComputePoint 等)
PlanetDataManager.h/.cpp ← HTTP 拉取 + 生成 Actor
ComputePointActor.h/.cpp ← 单个超算点的可视化 Actor
PlanetPlayerController.h/.cpp ← 鼠标点击、悬停、相机控制
PlanetGameMode.h/.cpp ← GameMode 入口
```
---
## 后端新接口一览
后端已新增以下接口(无需认证,直接访问):
| 接口 | 说明 |
|------|------|
| `GET /api/v1/ue/status` | 健康检查 + 各数据源数量 |
| `GET /api/v1/ue/compute-points` | TOP500 超算数据(平铺 JSON |
| `GET /api/v1/ue/landing-points` | 海缆登陆点(平铺 JSON |
| `GET /api/v1/ue/cables` | 海缆路由几何segments 数组) |
| `GET /api/v1/ue/satellites` | 卫星 TLE 数据 |
---
## 常见问题
### Q: 编译报错 "Cannot open include file: CesiumGeoreference.h"
**A:** Cesium for Unreal 没有正确安装,或者没有在 `.uproject` 里启用。检查:
1. Epic Launcher → 插件是否安装到 5.3
2. `PlanetClient.uproject``Plugins` 数组是否有 `CesiumForUnreal: true`
3. UE 编辑器 → Edit → Plugins → 搜索 Cesium → 确认已勾选 Enabled
### Q: Play 之后没有看到橙色球体
**A:** 按以下顺序排查:
1. Output LogWindow → Output Log里搜索 `PlanetDataManager` — 查看是否有报错
2. 检查 `BP_PlanetDataManager` 的 Details → **Compute Point Class** 是否已设置为 `BP_ComputePointActor`
3. 检查 **Mock Data Path** 是否正确(留空则自动用 `Content/Data/mock_compute_points.json`
4. 检查 **Use Local Mock Data** 是否已勾选
### Q: 地球是灰色的没有卫星影像
**A:** 需要 Cesium ion 账号:
1. Cesium 菜单 → Connect to Cesium ion
2. 注册免费账号并授权
3. 重新添加 **Cesium ion Bing Maps Aerial** tileset
### Q: WSL2 里的后端 UE 无法访问Phase B
**A:** WSL2 和 Windows 是不同网络命名空间。方法:
1. 在 WSL 里运行 `ip route show default | awk '{print $3}'` — 这是 Windows 主机的 IP
2. 后端绑定到 `0.0.0.0:8000`(检查 `uvicorn` 启动参数,应已如此配置)
3. 在 UE 的 DataManager 里填写这个 IP 而不是 `localhost`
### Q: TransformLongitudeLatitudeHeightPositionToUnreal 不存在
**A:** Cesium for Unreal API 在不同版本有变化。如果编译报此错,将 `PlanetDataManager.cpp` 里的调用改为:
```cpp
// Cesium for Unreal v1.x 的旧 API
FVector WorldPos = Georeference->TransformLongitudeLatitudeHeightToUnreal(
Pt.Longitude, Pt.Latitude, PointAltitudeMeters);
// 或者通过 GeoTransforms
#include "CesiumGlobeAnchorComponent.h"
// ... 见 Cesium 文档
```
### Q: 点击球体没有反应
**A:**
1. 确认 `SphereMesh`**Collision Presets** 不是 `NoCollision`
- 打开 `BP_ComputePointActor` → 点击 `SphereMesh` → Details → Collision → 改为 `BlockAllDynamic`
2. 确认 PlayerController 的 `bEnableClickEvents = true`(代码里已设置)
3. Output Log 里搜索是否有输入相关报错
---
## 下一步(一期完成后)
| 功能 | 说明 |
|------|------|
| 海缆路径渲染 | `/api/v1/ue/cables` 已就绪,需要在 UE 里用 Spline 绘制 |
| 信息卡 UMG | 创建 Widget Blueprint 并在 PlayerController OnPointSelected 里显示 |
| WebSocket 实时更新 | 后端已有 WebSocketUE 端需要使用 WebSockets 插件 |
| 卫星轨迹 | TLE 数据已就绪,需要在 UE 里做轨道传播计算 |

62
docs/ue_todo.md Normal file
View File

@@ -0,0 +1,62 @@
# UE5 客户端 — 待供应商回复的 TODO
> 以下两个问题答复后,对应代码可在一天内完成。
> 其余所有代码均已写好,不依赖这两个答案。
---
## TODO-1视频处理器输入格式
**等待信息**LED 屏配套视频处理器(如诺瓦星云)接受什么 3D 信号格式?
| 可能答案 | 对应操作 |
|---------|---------|
| Side-by-Side左右并排 | `StereoRenderingManager.cpp``EnableStereo``SideBySide` 分支已写好,直接启用 |
| Top-Bottom上下叠加 | 同上,切换到 `TopBottom` 分支 |
| 行交错(行偏振直驱) | 需要新写一个 PostProcess Material把左右眼奇偶行合并输出 |
| 私有协议 | 需要供应商提供 UE5 插件或信号格式文档 |
**代码位置**
```
ue_client/Source/PlanetClient/StereoRenderingManager.h — 第 8-18 行 TODO 注释
ue_client/Source/PlanetClient/StereoRenderingManager.cpp — EnableStereo() 函数
```
**需要同时确认**
- 视频处理器品牌和型号
- 屏幕物理分辨率(用于配置 UE5 输出分辨率)
- 3D 启用时是否需要特殊信号时序(如 3D Frame Packing
---
## TODO-2动捕中间件协议
**等待信息**:光学姿态识别系统用什么协议输出数据给 UE5
| 可能答案 | 对应操作 |
|---------|---------|
| **Live Link**(首选) | 在 UE5 编辑器里添加 Live Link Source零代码接入约 2 小时完成 |
| **OSC over UDP** | 新建 `MotionCaptureReceiverOSC.h/.cpp`,实现 UDP 监听和 OSC 解析,约 1 天 |
| 私有 SDK提供 .dll | 需要 SDK 文档,封装成 UE5 插件,约 2-3 天 |
| 私有 SDK提供 UE5 插件) | 直接安装插件,对接事件接口,约 0.5 天 |
**代码位置(已预留接口,填协议实现即可)**
```
ue_client/Source/PlanetClient/MotionCaptureInterface.h — UMotionCaptureReceiver 基类
ue_client/Source/PlanetClient/PlanetPlayerController.cpp — BindMotionCaptureEvents() 函数TODO 注释处取消注释)
ue_client/Source/PlanetClient/PlanetClient.Build.cs — TODO 注释的 LiveLink/Sockets 依赖
```
**需要同时确认**
- 手势集合(供应商能识别哪些具体手势,用于填写 `EMotionGesture` 枚举)
- 数据刷新频率(帧率)
- 是否支持持续输出旋转增量,还是只能输出离散手势事件
---
## 答复到位后的操作清单
拿到答案后告诉我,我来:
1. **视频处理器格式** → 配置 `StereoRenderingManager`,把 `bAutoEnableOnPlay` 改为 `true`,写进 setup guide
2. **动捕协议** → 实现对应的 `UMotionCaptureReceiver` 子类,更新 `Build.cs` 依赖,在 `PlayerController::BeginPlay` 里取消注释绑定代码