docs: 新增「初次部署(从零跑起来)」;去混淆字符与真实内网信息

- README.md / README.txt 新增初次部署章节:前置条件、获取代码、首次运行、
  配置服务端地址(API 3000 / 管理端 3001 分离)、与 Android 的 WebSocket 联通、
  打包导出、自检清单、常见问题
- 三库同源契约:':=' 写法修回、去掉真实 MariaDB 版本串
- 全文去除易被 Gitea 判为「模棱两可 Unicode」的字符(- - ... -> 取代 — – … § →)
- 真实内网地址与库名改占位符
This commit is contained in:
2026-09-15 21:33:27 +08:00
parent baec8fce97
commit 9f7b926a9a
21 changed files with 387 additions and 181 deletions
+4 -4
View File
@@ -20,9 +20,9 @@ scenes/main.tscn
## 交付物
| 文件 | 说明 |
|---|---|
|--|--|
| `project.godot` | 工程配置;autoload = AppConfig / CatalogStore / PoseReceiver / ScoreService |
| `scenes/main.tscn` | 只含一个挂载 `src/ui/main.gd` 的 Control 根节点(界面用代码构建,见 DSH.md §6) |
| `scenes/main.tscn` | 只含一个挂载 `src/ui/main.gd` 的 Control 根节点(界面用代码构建,见 DSH.md 6) |
| `src/ui/main.gd` | 应用外壳:构建布局、切换页面、启动接收服务 |
| `src/autoload/app_config.gd` | 客户端配置,持久化到 `user://opendance.cfg` |
| `src/autoload/catalog_store.gd` | 目录缓存 + 模型下载缓存 + 关键点序列缓存 |
@@ -32,8 +32,8 @@ scenes/main.tscn
## 验收
```bash
GODOT --headless --path . --import # 无 SCRIPT ERROR
GODOT --headless --path . --quit-after 180 # 应用可启动,UI 构建无报错
GODOT --headless --path. --import # 无 SCRIPT ERROR
GODOT --headless --path. --quit-after 180 # 应用可启动,UI 构建无报错
```
## 结果
+3 -3
View File
@@ -12,7 +12,7 @@
```
DSH.md
contracts/rest-api.yaml # 锚点:#/paths/~1api~1catalog
contracts/data-models.md # 锚点:§2 Song、§3 Motion、§4 Model、§6 CatalogBundle
contracts/data-models.md # 锚点:2 Song、3 Motion、4 Model、6 CatalogBundle
src/net/api_client.gd
src/net/catalog_types.gd
src/autoload/catalog_store.gd
@@ -21,10 +21,10 @@ src/autoload/catalog_store.gd
## 交付物
| 文件 | 说明 |
|---|---|
|--|--|
| `src/net/api_client.gd` | HTTPRequest 封装;统一返回 `{ok,status,data,error}`,不抛异常 |
| `src/net/catalog_types.gd` | Song / Motion / Model / CatalogBundle / SourceInfo 类型化解析 |
| `src/net/keypoint_sequence.gd` | NDJSON 关键点序列 → 特征向量序列 |
| `src/net/keypoint_sequence.gd` | NDJSON 关键点序列 -> 特征向量序列 |
| `src/autoload/catalog_store.gd` | 目录刷新、模型文件下载缓存、序列缓存 |
## 关键实现
+3 -3
View File
@@ -11,7 +11,7 @@
```
DSH.md
contracts/websocket-keypoints.md # 锚点:§1 端点与子协议、§3 文本控制帧
contracts/websocket-keypoints.md # 锚点:1 端点与子协议、3 文本控制帧
src/net/pose_server.gd
src/autoload/pose_receiver.gd
```
@@ -24,9 +24,9 @@ src/autoload/pose_receiver.gd
## 能力
| 项 | 说明 |
|---|---|
|--|--|
| 子协议 | 协商 `opendance.pose.v1`,客户端选择不符时告警 |
| 控制帧 | `hello` → 回 `welcome`(含 sessionId);`bye` → 关闭 |
| 控制帧 | `hello` -> 回 `welcome`(含 sessionId);`bye` -> 关闭 |
| 协议不匹配 | 回 `bye{reason: protocol_mismatch}` 并以 1002 关闭 |
| 二进制帧 | 严格校验 239 字节与 magic,畸形帧计数但不影响连接 |
| 丢包统计 | 按 `frame_id` 跳号计数(含 u32 回绕保护) |
+2 -2
View File
@@ -11,8 +11,8 @@
```
DSH.md
contracts/websocket-keypoints.md # 锚点:§2 二进制帧(冻结)
contracts/skeleton-topology.md # 锚点:§4 坐标系
contracts/websocket-keypoints.md # 锚点:2 二进制帧(冻结)
contracts/skeleton-topology.md # 锚点:4 坐标系
src/net/keypoint_frame.gd
```
+3 -3
View File
@@ -11,8 +11,8 @@
```
DSH.md
contracts/model-formats.md # 锚点:§1 角色模型
contracts/data-models.md # 锚点:§4.1 VRM 优先规则
contracts/model-formats.md # 锚点:1 角色模型
contracts/data-models.md # 锚点:4.1 VRM 优先规则
src/model/vrm_loader.gd
src/model/humanoid_map.gd
```
@@ -29,7 +29,7 @@ src/model/humanoid_map.gd
`HumanoidMap` 覆盖 VRoid / VRM 0.x / Mixamo 三类命名,归一化后精确比较:
- 剥离前缀 `jbip` / `mixamorig` / `bip01`(**归一化之后**的形态)
- 生成 compact(left→l)与 expanded(l→left)两种变体比较
- 生成 compact(left->l)与 expanded(l->left)两种变体比较
- **故意不剥离 `J_Aim_` / `J_Roll_` / `J_Sec_`**:VRoid 用它们标记扭转辅助骨,
剥离后 `J_Aim_L_UpperLeg` 会与真正的 `J_Bip_L_UpperLeg` 撞名
+6 -6
View File
@@ -1,4 +1,4 @@
# T-WIN-006 关键点 → VRM 骨骼重定向
# T-WIN-006 关键点 -> VRM 骨骼重定向
- **状态**:done
- **依赖**:T-WIN-005、T-WIN-004
@@ -11,7 +11,7 @@
```
DSH.md
contracts/skeleton-topology.md # 锚点:§1 33 点、§2 虚拟关节、§4 坐标系
contracts/skeleton-topology.md # 锚点:1 33 点、2 虚拟关节、4 坐标系
src/anim/skeleton_retarget.gd
```
@@ -20,7 +20,7 @@ src/anim/skeleton_retarget.gd
1. 每根骨骼指定一条骨链(起点关键点,终点关键点)
2. 取骨骼静止朝向 `rest_dir`(由该骨与首个子骨的位置差得出,**不假设模型骨骼轴向**)
3. 目标朝向由两个关键点在世界空间的方向得出
4. `delta` = rest_dir → target_dir 的最小旋转四元数(保留扭转/roll)
4. `delta` = rest_dir -> target_dir 的最小旋转四元数(保留扭转/roll)
5. `desired = Basis(delta) × rest_global_basis`
6. `pose_local = parent_global_basis⁻¹ × desired`
@@ -30,15 +30,15 @@ src/anim/skeleton_retarget.gd
## 坐标转换
契约 §4 的 MediaPipe 归一化坐标 → Godot 世界方向:
契约 4 的 MediaPipe 归一化坐标 -> Godot 世界方向:
`Vector3(x × aspect, −y, −z × aspect)`(x/z 以图像宽为基准故乘宽高比)。
## 验收
`tests/test_retarget.gd` —— 最关键的是**功能性**断言:
`tests/test_retarget.gd` -- 最关键的是**功能性**断言:
```
→ 左上臂方向点积 1.0000,左前臂方向点积 1.0000
-> 左上臂方向点积 1.0000,左前臂方向点积 1.0000
```
即:给定一组关键点,重定向后骨骼在世界空间的**实际指向**与关键点方向一致;
+3 -3
View File
@@ -11,14 +11,14 @@
```
DSH.md
contracts/skeleton-topology.md # 锚点:§5 派生特征
contracts/model-formats.md # 锚点:§2.1 预处理产物
contracts/skeleton-topology.md # 锚点:5 派生特征
contracts/model-formats.md # 锚点:2.1 预处理产物
src/score/pose_features.gd
src/score/dtw.gd
src/score/scoring.gd
```
## 特征(契约 §5 冻结)
## 特征(契约 5 冻结)
每帧 = `[33 × (x,y,z), 9 个关节角余弦]` = **108 维**。
低置信度点(conf < 0.5)对应维度**权重置 0**,不参与代价计算。
+4 -4
View File
@@ -5,7 +5,7 @@
## 目标
三页式体验:主菜单(选曲/选动作/选模型)→ 游戏页(3D 角色 + 实时评分 HUD)→ 结算页。
三页式体验:主菜单(选曲/选动作/选模型)-> 游戏页(3D 角色 + 实时评分 HUD)-> 结算页。
## load
@@ -21,14 +21,14 @@ src/ui/ui_kit.gd
## 页面
| 页面 | 能力 |
|---|---|
|--|--|
| 主菜单 | 三栏选择(曲目 / 可评分动作 / 模型)、服务端地址编辑与测试、目录刷新、接收服务状态与重启 |
| 游戏页 | SubViewport 3D 角色、自动定机位、实时分数/等级/连击、进度条、连接状态提示、来源展示 |
| 结算 | 等级大字、平均/最终分、完成度、最高单帧、最长连击、评语、来源展示 |
## 关键实现
- 界面全部代码构建(见 DSH.md §6),主菜单只列出 `preprocessState == "done"` 的动作
- 界面全部代码构建(见 DSH.md 6),主菜单只列出 `preprocessState == "done"` 的动作
- 游戏页订阅 `PoseReceiver.frame_received` 驱动骨骼,`ScoreService` 独立订阅做评分
- 未连接设备时给出明确提示而非静默失败;模型/序列拉取失败时显示可读原因并允许重试
- 参考序列走完自动结算
@@ -36,5 +36,5 @@ src/ui/ui_kit.gd
## 验收
`GODOT --headless --path . --quit-after 180` 启动无运行时错误;
`GODOT --headless --path. --quit-after 180` 启动无运行时错误;
主菜单、游戏页、结算页的构造路径均被该启动流程覆盖。
+1 -1
View File
@@ -11,7 +11,7 @@
```
DSH.md
contracts/data-models.md # 锚点:§1 来源五元组
contracts/data-models.md # 锚点:1 来源五元组
src/ui/source_panel.gd
src/net/catalog_types.gd
```
+4 -4
View File
@@ -19,9 +19,9 @@ export_presets.cfg
## 交付物
| 文件 | 说明 |
|---|---|
|--|--|
| `export_presets.cfg` | 导出预设(**必须在项目根目录**,Godot 硬性要求) |
| `build/export-windows.sh` | Linux 导出:定位 Godot → 检查模板 → 导入 → 导出 → **校验 PE 头** |
| `build/export-windows.sh` | Linux 导出:定位 Godot -> 检查模板 -> 导入 -> 导出 -> **校验 PE 头** |
| `build/export-windows.ps1` | Windows 兜底:同上,产物路径与校验逻辑一致 |
## 脚本健壮性
@@ -31,10 +31,10 @@ export_presets.cfg
- 导出命令返回非 0 时**仍检查产物是否存在**(Godot 有时非 0 返回但产物有效)
- 读取产物前 2 字节校验 `MZ`(PE 头),防止导出静默产出空壳
## 验收(文档 §5.4)
## 验收(文档 5.4)
| 验收项 | 结果 |
|---|---|
|--|--|
| Linux:`bash build/export-windows.sh` 成功生成 exe | ✅ 生成 `OpenDance.exe` 104 MB + `OpenDance.pck` 107 KB,PE 头校验通过 |
| Windows:`powershell build/export-windows.ps1` 成功生成 exe | ⚠️ 脚本就绪,本环境无 Windows,未实机执行 |
| 生成的 exe 在 Windows 10/11 可运行 | ⚠️ 本环境无 Windows;已校验为合法 PE32+ x86_64 可执行文件 |