Files
opendance-windows/DSH.md
T

138 lines
6.1 KiB
Markdown
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.
# DSH.md —— opendance-windows(OpenDance Studio 项目二:Windows 客户端)
## 0. 本文件的作用
本文件是 **opendance-windows 仓库内**的 DSH 执行约束。顶层说明书见
《DSH 开发文档:OpenDance Studio》,二者冲突时以顶层文档为准。
## 1. 项目定位
Windows 客户端是核心体验载体:接收 Android 辅助 App 推送的 33 点骨骼关键点,
驱动 VRM 角色,并与 Web 服务端下发的参考动作做实时 DTW 评分。
```
Android 辅助 App ──239 字节关键点帧──▶ 本端(WebSocket 服务端 :8765)
│
Web 服务端 ──GET /api/catalog/export──────┤
──GET /api/motions/:id/keypoints┘
▼
VRM 驱动 + DTW 评分
```
**本端是 WebSocket 的「服务端」,Android 主动连入**(契约 websocket-keypoints.md §1)。
## 2. 技术栈
| 组件 | 选型 | 说明 |
|---|---|---|
| 引擎 | Godot 4.7.2(MIT) | 可在 Linux 上导出 Windows exe |
| VRM 加载 | **Godot 内置 GLTFDocument** | 见 §6 的选型变更说明 |
| 多格式导入 | Godot 内置 glTF 导入器 | FBX 由管理端转 BVH 后下发 |
| 通信 | WebSocketPeer + HTTPRequest | 无第三方依赖 |
| 评分 | DTW + 关节角度差异 | 纯 GDScript 实现 |
| 渲染 | GL Compatibility | 兼容性最好,便于无 GPU 导出 |
## 3. 单次会话加载范围
允许加载:
1. 本文件 `DSH.md`
2. `project.yaml`
3. 当前 `tasks/xxx.md`
4. 该任务文件中 `load` 列出的文件
5. `contracts/` 中被明确引用的**锚点片段**
禁止加载:
- `opendance-web` / `opendance-android` 的任何源码
- 非当前任务的 `tasks/*.md`
- 完整 `contracts/` 目录(只引用锚点)
- `.godot/` 导入缓存、`build/windows/` 导出产物、`_scratch/` 下的模型素材
## 4. 上下文预算
| 项 | 建议值 |
|---|---|
| 单任务文件数 | ≤ 6 |
| 单任务代码行数 | ≤ 1500 |
| 单任务 Token | ≤ 12K |
| 契约引用 | 只引用锚点,不加载全文 |
## 5. 目录结构
```
opendance-windows/
├── project.godot # Godot 工程(autoload、渲染、窗口配置)
├── export_presets.cfg # ★ 必须位于项目根目录(Godot 硬性要求)
├── project.yaml / DSH.md
├── tasks/ # 001~011 单任务说明书
├── contracts/ # 只读契约快照(来源 opendance-web v0.1.0)
├── scenes/main.tscn # 仅一个挂载 main.gd 的根节点
├── src/
│ ├── autoload/ # AppConfig / CatalogStore / PoseReceiver / ScoreService
│ ├── net/ # 239 字节编解码、WebSocket 服务、REST 客户端、NDJSON 解析
│ ├── model/ # VRM 加载、humanoid 骨骼名映射
│ ├── anim/ # 关键点 → 骨骼重定向
│ ├── score/ # 特征提取、DTW、评分规则
│ └── ui/ # 主界面 / 游戏界面 / 结算 / 关于 / 来源展示
├── tests/ # 无头测试框架 + 用例
└── build/ # 导出脚本(sh / ps1)
```
## 6. 界面构建方式与选型变更(重要)
**界面全部用 GDScript 代码构建,不手写 `.tscn`。**
`.tscn` 是带 uid 与节点路径的手写格式,在没有编辑器的情况下极易出错且难以验证;
用代码构建可随脚本一起被无头导入和单元测试覆盖。`scenes/main.tscn` 因此只保留一个根节点。
**VRM 加载改用 Godot 内置 glTF 导入器**(文档 §5.1 原选型为 godot-vrm GDExtension):
- `V-Sekai/godot-vrm` **不发布任何预编译产物**(无 GitHub Release,仅源码,
需用 godot-cpp 本地编译原生库),这会同时破坏「Linux 上导出 Windows exe」的验收路径。
- VRM 本身就是 glTF 2.0 二进制容器:实测内置导入器可完整解析 154 骨骼的 VRoid 模型,
且 `GLTFState.json` 可直接读取 `extensions.VRMC_vrm` / `extensions.VRM` 判定版本。
- humanoid 骨骼按名字映射(`src/model/humanoid_map.gd`),覆盖 VRoid / VRM 0.x / Mixamo 三种命名。
若日后接入 godot-vrm,只需替换 `VrmLoader.load_from_file`,对外接口不变。
## 7. 硬性约束
1. **绝不让视频帧离开设备**:本端只接收 33 个关键点的坐标,不接收也不存储图像。
2. **契约先行**:改交互先改 `opendance-web` 的 `contracts/`,再回本仓库同步快照。
3. **不假设骨骼轴向约定**:重定向基于「静止朝向 → 目标朝向」的最小旋转,
`pose = parent_global_basis⁻¹ × desired` 这一合成公式由真实 VRM 实测标定,
有回归测试守护,不得凭记忆改写。
4. **上传/下载的模型不入库**:真实 VRM 样例仅放在 `_scratch/`(已 gitignore),
版权原因不得提交。
5. **不使用 SMPL 拓扑**,统一 MediaPipe 33 点。
6. 关于页面与 `THIRD_PARTY.md` 必须与 `contracts/open-source-credits.md` 一致。
## 8. 验证(每任务执行)
```bash
GODOT=/path/to/godot # Godot 4.7.x
# 1. 全部脚本编译通过(无输出即通过)
$GODOT --headless --path . --import 2>&1 | grep -E "SCRIPT ERROR|Parse Error"
# 2. 无头单元测试 + 真实 API 集成(API 不可达时相关用例显式跳过)
$GODOT --headless --path . --script res://tests/run_tests.gd
# 3. 应用可启动(autoload + UI 构建无报错)
$GODOT --headless --path . --quit-after 180
# 4. Windows 导出(需先安装 export templates)
bash build/export-windows.sh release
```
## 9. 上下文超标时的拆分策略
| 超标原因 | 拆分方式 |
|---|---|
| 单任务涉及多个界面 | 按界面拆(主/游戏/结算/关于) |
| 单文件过大 | 按类拆,先生成接口再分实现 |
| 契约全文加载 | 改用锚点引用 |
| 需要参考其他项目 | 只读契约,不读源码 |
| UI 与逻辑耦合 | UI 只调用已定义接口(GameScreen 不做 DTW 计算) |
| 测试与实现同任务 | 测试单独任务,共享接口摘要 |