docs: 消除 Gitea 模棱两可 Unicode 告警(全角标点紧邻 ASCII 时改为半角)
依据 Gitea v1.27.3 modules/charset/escape_stream.go 的判定规则 (analyzeDetectResults:仅当左右相邻字符都不是非 ASCII 时才标记, 且 _common 表恒定生效),把说明文档中会被标记的全角标点 (,:;?!() 等)改为半角,并保证成对括号宽度一致。 中文语境中的全角标点(左右均为中文)保持原样,不动代码与契约语义。
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# T-WIN-001 Godot 项目骨架
|
||||
|
||||
- **状态**:done
|
||||
- **状态**: done
|
||||
- **依赖**:无
|
||||
|
||||
## 目标
|
||||
@@ -22,7 +22,7 @@ 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` | 目录缓存 + 模型下载缓存 + 关键点序列缓存 |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-002 调用 Web 服务端 API
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-001
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-001
|
||||
|
||||
## 目标
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-003 接收 Android 关键点帧
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-001
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-001
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -18,7 +18,7 @@ src/autoload/pose_receiver.gd
|
||||
|
||||
## 交付物
|
||||
|
||||
- `src/net/pose_server.gd`:TCPServer + `WebSocketPeer.accept_stream()` 实现服务端
|
||||
- `src/net/pose_server.gd`: TCPServer + `WebSocketPeer.accept_stream()` 实现服务端
|
||||
- `src/autoload/pose_receiver.gd`:绑定 AppConfig,暴露 `latest_frame` 与统计
|
||||
|
||||
## 能力
|
||||
@@ -36,7 +36,7 @@ src/autoload/pose_receiver.gd
|
||||
|
||||
## 已知限制
|
||||
|
||||
Godot 的 `WebSocketPeer` 不暴露握手请求路径,因此**无法校验 path 是否为 `/pose`**,
|
||||
Godot 的 `WebSocketPeer` 不暴露握手请求路径,因此**无法校验 path 是否为 `/pose`**,
|
||||
实现接受任意 path,仅校验子协议。已记录于 DSH.md 与任务文档。
|
||||
|
||||
## 验收
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-004 239 字节帧反序列化
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-001
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-001
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -24,20 +24,20 @@ src/net/keypoint_frame.gd
|
||||
2 1 version u8 = 1
|
||||
3 1 flags u8 bit0 镜像 bit1 低置信度 bit2 上半身
|
||||
4 4 frame_id u32 LE
|
||||
8 231 keypoints 33 x 7B:s16 x, s16 y, s16 z, u8 conf
|
||||
8 231 keypoints 33 x 7B:s16 x, s16 y, s16 z, u8 conf
|
||||
合计 239
|
||||
```
|
||||
|
||||
## 交付物
|
||||
|
||||
`src/net/keypoint_frame.gd`:`PoseFrame` 内部类 + `decode` / `encode` / `validate` / `from_json_dict`。
|
||||
`src/net/keypoint_frame.gd`: `PoseFrame` 内部类 + `decode` / `encode` / `validate` / `from_json_dict`。
|
||||
|
||||
## 关键实现
|
||||
|
||||
- 归一化系数统一 32767,与 opendance-web 的 TypeScript 参考实现逐位对齐
|
||||
- 编解码往返误差 < 1e-4(定点精度 1/32767 ~ 3.05e-5)
|
||||
- 编解码往返误差 < 1e-4(定点精度 1/32767 ~ 3.05e-5)
|
||||
- `unmirrored_points()` 按 flags.bit0 翻转 x
|
||||
- 低置信度阈值 0.5:`is_reliable()` 与 `compute_low_confidence()`
|
||||
- 低置信度阈值 0.5: `is_reliable()` 与 `compute_low_confidence()`
|
||||
- 极值(±1.0)不溢出 int16
|
||||
|
||||
## 验收
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-005 VRM 模型加载
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-001
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-001
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -19,23 +19,23 @@ src/model/humanoid_map.gd
|
||||
|
||||
## 选型变更
|
||||
|
||||
文档原选型 `godot-vrm`(V-Sekai)GDExtension **不发布任何预编译产物**,
|
||||
文档原选型 `godot-vrm`(V-Sekai)GDExtension **不发布任何预编译产物**,
|
||||
需用 godot-cpp 本地编译原生库,会破坏「Linux 导出 Windows exe」的验收路径。
|
||||
改用 **Godot 内置 GLTFDocument**:VRM 即 glTF 2.0 容器,实测可完整解析
|
||||
改用 **Godot 内置 GLTFDocument**: VRM 即 glTF 2.0 容器,实测可完整解析
|
||||
154 骨骼的 VRoid 模型,且 `GLTFState.json` 可直接读取 VRM 扩展判定版本。
|
||||
|
||||
## 骨骼名映射
|
||||
|
||||
`HumanoidMap` 覆盖 VRoid / VRM 0.x / Mixamo 三类命名,归一化后精确比较:
|
||||
|
||||
- 剥离前缀 `jbip` / `mixamorig` / `bip01`(**归一化之后**的形态)
|
||||
- 生成 compact(left->l)与 expanded(l->left)两种变体比较
|
||||
- **故意不剥离 `J_Aim_` / `J_Roll_` / `J_Sec_`**:VRoid 用它们标记扭转辅助骨,
|
||||
- 剥离前缀 `jbip` / `mixamorig` / `bip01`(**归一化之后**的形态)
|
||||
- 生成 compact(left->l)与 expanded(l->left)两种变体比较
|
||||
- **故意不剥离 `J_Aim_` / `J_Roll_` / `J_Sec_`**: VRoid 用它们标记扭转辅助骨,
|
||||
剥离后 `J_Aim_L_UpperLeg` 会与真正的 `J_Bip_L_UpperLeg` 撞名
|
||||
|
||||
## 验收
|
||||
|
||||
`tests/test_vrm_loader.gd`:
|
||||
`tests/test_vrm_loader.gd`:
|
||||
- 三类命名规范的识别(含辅助骨不遮蔽真骨的回归用例)
|
||||
- 真实 VRM:154 骨骼 / 3 网格 / VRM 1.0,**humanoid 覆盖率 100%**
|
||||
- 真实 VRM: 154 骨骼 / 3 网格 / VRM 1.0, **humanoid 覆盖率 100%**
|
||||
- 缺失文件、普通 glTF 不误判
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-006 关键点 -> VRM 骨骼重定向
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-005、T-WIN-004
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-005、T-WIN-004
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -18,20 +18,20 @@ src/anim/skeleton_retarget.gd
|
||||
## 算法
|
||||
|
||||
1. 每根骨骼指定一条骨链(起点关键点,终点关键点)
|
||||
2. 取骨骼静止朝向 `rest_dir`(由该骨与首个子骨的位置差得出,**不假设模型骨骼轴向**)
|
||||
2. 取骨骼静止朝向 `rest_dir`(由该骨与首个子骨的位置差得出,**不假设模型骨骼轴向**)
|
||||
3. 目标朝向由两个关键点在世界空间的方向得出
|
||||
4. `delta` = rest_dir -> target_dir 的最小旋转四元数(保留扭转/roll)
|
||||
4. `delta` = rest_dir -> target_dir 的最小旋转四元数(保留扭转/roll)
|
||||
5. `desired = Basis(delta) x rest_global_basis`
|
||||
6. `pose_local = parent_global_basis⁻¹ x desired`
|
||||
|
||||
**第 6 步的合成公式是实测标定的**:Godot 文档未写明 rest/pose 的合成顺序,
|
||||
**第 6 步的合成公式是实测标定的**: Godot 文档未写明 rest/pose 的合成顺序,
|
||||
在真实 VRoid 模型上暴力枚举 5 种候选公式,只有该式误差为 1.9e-8(其余 ~0.14)。
|
||||
已有回归测试守护,不得凭记忆改写。
|
||||
|
||||
## 坐标转换
|
||||
|
||||
契约 4 的 MediaPipe 归一化坐标 -> Godot 世界方向:
|
||||
`Vector3(x x aspect, -y, -z x aspect)`(x/z 以图像宽为基准故乘宽高比)。
|
||||
`Vector3(x x aspect, -y, -z x aspect)`(x/z 以图像宽为基准故乘宽高比)。
|
||||
|
||||
## 验收
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-007 DTW 评分引擎
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-004、T-WIN-002
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-004、T-WIN-002
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -30,9 +30,9 @@ src/score/scoring.gd
|
||||
每帧只计算带内一行,总体复杂度 O(n m band) 但摊到每帧 O(m band)
|
||||
- 归一化:代价 / max(i,j)+1,得到「平均每步代价」
|
||||
|
||||
## 评分规则(`scoring.gd`)
|
||||
## 评分规则(`scoring.gd`)
|
||||
|
||||
`score = clamp(1 - cost/tolerance, 0, 1) x 100`,EMA 平滑抑制抖动,
|
||||
`score = clamp(1 - cost/tolerance, 0, 1) x 100`, EMA 平滑抑制抖动,
|
||||
等级 S(>=95) / A(>=85) / B(>=70) / C(>=55) / D,连击阈值 70。
|
||||
|
||||
## 验收
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# T-WIN-008 主界面 + 游戏界面 + 结算
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-002、T-WIN-003、T-WIN-006、T-WIN-007
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-002、T-WIN-003、T-WIN-006、T-WIN-007
|
||||
|
||||
## 目标
|
||||
|
||||
三页式体验:主菜单(选曲/选动作/选模型)-> 游戏页(3D 角色 + 实时评分 HUD)-> 结算页。
|
||||
三页式体验:主菜单(选曲/选动作/选模型)-> 游戏页(3D 角色 + 实时评分 HUD)-> 结算页。
|
||||
|
||||
## load
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-009 来源信息展示
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-008
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-008
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -26,7 +26,7 @@ src/net/catalog_types.gd
|
||||
- 资产名 | 来源名称
|
||||
- 作者
|
||||
- 许可 + **可点击外链**跳转到 `sourceUrl`
|
||||
- **五元组不齐备时显式告警**("⚠ 来源信息不完整,请联系管理员补全后再使用"),不静默展示
|
||||
- **五元组不齐备时显式告警**("⚠ 来源信息不完整,请联系管理员补全后再使用"),不静默展示
|
||||
|
||||
## 使用位置
|
||||
|
||||
@@ -37,4 +37,4 @@ src/net/catalog_types.gd
|
||||
## 验收
|
||||
|
||||
`tests/test_api_integration.gd` 对真实服务端断言曲目与模型的来源五元组齐备
|
||||
(`song.source.is_complete()`),保证展示组件拿到的数据完整。
|
||||
(`song.source.is_complete()`),保证展示组件拿到的数据完整。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# T-WIN-010 关于页面 + 开源声明
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-008
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-008
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -19,7 +19,7 @@ src/ui/credits.gd
|
||||
## 交付物
|
||||
|
||||
- `src/ui/credits.gd`:与 `contracts/open-source-credits.md` 逐条对应的数据表,渲染为 BBCode
|
||||
- `src/ui/about_screen.gd`:应用信息 + 契约版本 + 隐私说明 + 可滚动声明(RichTextLabel)
|
||||
- `src/ui/about_screen.gd`:应用信息 + 契约版本 + 隐私说明 + 可滚动声明(RichTextLabel)
|
||||
|
||||
## 要点
|
||||
|
||||
|
||||
+10
-10
@@ -1,7 +1,7 @@
|
||||
# T-WIN-011 Windows 打包脚本
|
||||
|
||||
- **状态**:done
|
||||
- **依赖**:T-WIN-001 ~ 010
|
||||
- **状态**: done
|
||||
- **依赖**: T-WIN-001 ~ 010
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -20,7 +20,7 @@ export_presets.cfg
|
||||
|
||||
| 文件 | 说明 |
|
||||
|--|--|
|
||||
| `export_presets.cfg` | 导出预设(**必须在项目根目录**,Godot 硬性要求) |
|
||||
| `export_presets.cfg` | 导出预设(**必须在项目根目录**, Godot 硬性要求) |
|
||||
| `build/export-windows.sh` | Linux 导出:定位 Godot -> 检查模板 -> 导入 -> 导出 -> **校验 PE 头** |
|
||||
| `build/export-windows.ps1` | Windows 兜底:同上,产物路径与校验逻辑一致 |
|
||||
|
||||
@@ -28,15 +28,15 @@ export_presets.cfg
|
||||
|
||||
- `GODOT_BIN` 环境变量或 PATH 自动定位 Godot,缺失时给出可执行的安装指引
|
||||
- 导出模板缺失时明确报错并给出下载与安装路径
|
||||
- 导出命令返回非 0 时**仍检查产物是否存在**(Godot 有时非 0 返回但产物有效)
|
||||
- 读取产物前 2 字节校验 `MZ`(PE 头),防止导出静默产出空壳
|
||||
- 导出命令返回非 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,未实机执行 |
|
||||
| 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 可执行文件 |
|
||||
| `THIRD_PARTY.md` 包含所有开源项目与源链接 | ✅ 15 项,与契约表逐条一致 |
|
||||
|
||||
@@ -53,6 +53,6 @@ opendance-windows-v0.1.0.zip
|
||||
|
||||
## 环境记录
|
||||
|
||||
- Godot 4.7.2.stable(`ed1daf0bf`)
|
||||
- 导出模板 `4.7.2.stable`(``windows_release_x86_64.exe``)
|
||||
- Godot 4.7.2.stable(`ed1daf0bf`)
|
||||
- 导出模板 `4.7.2.stable`(``windows_release_x86_64.exe``)
|
||||
- 首次导出失败原因:`export_presets.cfg` 放在 `build/` 下,Godot 只在**项目根目录**查找
|
||||
|
||||
Reference in New Issue
Block a user