docs: 其余易混淆字符(x/>=/<=/~/OK 取代 × − ≥ ≤ ≈ ✓)

This commit is contained in:
2026-09-15 21:34:50 +08:00
parent 9f7b926a9a
commit 68a5ca0a87
10 changed files with 35 additions and 35 deletions
+4 -4
View File
@@ -53,9 +53,9 @@ Web 服务端 ──GET /api/catalog/export──────┤
| 项 | 建议值 |
|--|--|
| 单任务文件数 | ≤ 6 |
| 单任务代码行数 | ≤ 1500 |
| 单任务 Token | ≤ 12K |
| 单任务文件数 | <= 6 |
| 单任务代码行数 | <= 1500 |
| 单任务 Token | <= 12K |
| 契约引用 | 只引用锚点,不加载全文 |
## 5. 目录结构
@@ -100,7 +100,7 @@ opendance-windows/
1. **绝不让视频帧离开设备**:本端只接收 33 个关键点的坐标,不接收也不存储图像。
2. **契约先行**:改交互先改 `opendance-web` 的 `contracts/`,再回本仓库同步快照。
3. **不假设骨骼轴向约定**:重定向基于「静止朝向 -> 目标朝向」的最小旋转,
`pose = parent_global_basis⁻¹ × desired` 这一合成公式由真实 VRM 实测标定,
`pose = parent_global_basis⁻¹ x desired` 这一合成公式由真实 VRM 实测标定,
有回归测试守护,不得凭记忆改写。
4. **上传/下载的模型不入库**:真实 VRM 样例仅放在 `_scratch/`(已 gitignore),
版权原因不得提交。
+7 -7
View File
@@ -13,13 +13,13 @@ OpenDance Studio **阶段二**:Windows 客户端(Godot 4)。
| 验收项 | 结果 |
|--|--|
| 脚本编译 | ✓ 全部通过(无 SCRIPT ERROR) |
| 无头测试 | ✓ **580 项全部通过**(8 个测试套件) |
| 应用启动 | ✓ 180 帧无运行时错误 |
| Windows 导出 | ✓ 生成 `OpenDance.exe`(104 MB,PE 头校验通过)+ `OpenDance.pck` |
| 真实 VRM 验证 | ✓ 154 骨骼 VRoid 模型,humanoid 覆盖率 **100%** |
| 骨骼重定向 | ✓ 关键点方向与骨骼实际指向点积 **1.0000** |
| 跨实现交叉校验 | ✓ 关节角与 Web 服务端 TypeScript 实现**逐帧一致** |
| 脚本编译 | OK 全部通过(无 SCRIPT ERROR) |
| 无头测试 | OK **580 项全部通过**(8 个测试套件) |
| 应用启动 | OK 180 帧无运行时错误 |
| Windows 导出 | OK 生成 `OpenDance.exe`(104 MB,PE 头校验通过)+ `OpenDance.pck` |
| 真实 VRM 验证 | OK 154 骨骼 VRoid 模型,humanoid 覆盖率 **100%** |
| 骨骼重定向 | OK 关键点方向与骨骼实际指向点积 **1.0000** |
| 跨实现交叉校验 | OK 关节角与 Web 服务端 TypeScript 实现**逐帧一致** |
## 快速开始
+5 -5
View File
@@ -173,7 +173,7 @@ OpenDance.exe 的用户看第一节即可。
listen_host WebSocket 监听地址(默认 0.0.0.0)
listen_port WebSocket 监听端口(默认 8765)
ws_subprotocol 子协议(默认 opendance.pose.v1)
dtw_band DTW 带宽,单位帧(默认 15 ≈ 0.5 秒抖动容忍)
dtw_band DTW 带宽,单位帧(默认 15 ~ 0.5 秒抖动容忍)
score_tolerance 评分容差:平均每步代价达到该值即 0 分(默认 0.25)
mirror_preview 镜像预览
@@ -193,12 +193,12 @@ OpenDance.exe 的用户看第一节即可。
六、评分说明
--
- 每帧特征 = 33 点 × (x,y,z) + 9 个关节角余弦 = 108 维
- 每帧特征 = 33 点 x (x,y,z) + 9 个关节角余弦 = 108 维
(与 Web 服务端预处理产物、Android 端推流结构完全一致)
- 置信度低于 0.5 的关键点不参与代价计算,避免遮挡导致误判
- 采用带约束 DTW(|i−j| ≤ band)对齐,能吸收一定的节奏快慢差异
- 得分 = clamp(1 − 平均代价 / 容差, 0, 1) × 100,并做指数平滑
- 等级:S ≥ 95,A ≥ 85,B ≥ 70,C ≥ 55,D 其余
- 采用带约束 DTW(|i-j| <= band)对齐,能吸收一定的节奏快慢差异
- 得分 = clamp(1 - 平均代价 / 容差, 0, 1) x 100,并做指数平滑
- 等级:S >= 95,A >= 85,B >= 70,C >= 55,D 其余
--
七、从源码构建
+5 -5
View File
@@ -54,9 +54,9 @@ rejected 已驳回
| 字段 | 类型 | 必填 | 说明 |
|--|--|--|--|
| `id` | number | 读 | |
| `title` | string | ✅ | 曲名,≤200 |
| `artist` | string | ✅ | 演唱者,≤200 |
| `album` | string | | 专辑,≤200 |
| `title` | string | ✅ | 曲名,<=200 |
| `artist` | string | ✅ | 演唱者,<=200 |
| `album` | string | | 专辑,<=200 |
| `language` | string | | `zh` / `en` / `ja` / `ko` / `instrumental` |
| `durationMs` | number | | 时长毫秒 |
| `bpm` | number | | 节拍 |
@@ -74,7 +74,7 @@ rejected 已驳回
|--|--|--|--|
| `id` | number | 读 | |
| `songId` | number\|null | | 关联曲目 |
| `name` | string | ✅ | 动作名称,≤200 |
| `name` | string | ✅ | 动作名称,<=200 |
| `format` | enum | ✅ | `bvh` / `vmd` / `fbx` / `gltf` / `glb` / `keypoints-json` |
| `fileUrl` | string | 读 | 原始动作文件 |
| `fileSize` | number | 读 | 字节 |
@@ -95,7 +95,7 @@ rejected 已驳回
| 字段 | 类型 | 必填 | 说明 |
|--|--|--|--|
| `id` | number | 读 | |
| `name` | string | ✅ | 模型名称,≤200 |
| `name` | string | ✅ | 模型名称,<=200 |
| `format` | enum | ✅ | `glb` / `vrm`(主力)/ `gltf` / `fbx`(历史数据)。上传的 PMX/FBX 会被服务端转换成 glb 或 vrm 再入库,见 model-formats.md 1.1 |
| `vrmVersion` | string\|null | 读 | `0.x` / `1.0`,非 VRM 为 null |
| `isPrimary` | boolean | | 全局默认模型;**同一时刻全库至多一个 `true`** |
+2 -2
View File
@@ -126,7 +126,7 @@ VRM 版本识别:读取 GLB 的 JSON chunk,检查 `extensions.VRM`(0.x)
VMD 是二进制格式:文件头 `Vocaloid Motion Data 0002`(30 字节)+ 模型名(20 字节,
Shift-JIS)+ 骨骼关键帧数组(每条 **111 字节**:15 字节骨骼名、uint32 帧号、
float32×3 位移、float32×4 旋转四元数、64 字节贝塞尔插值参数)+ morph / 相机 /
float32x3 位移、float32x4 旋转四元数、64 字节贝塞尔插值参数)+ morph / 相机 /
灯光 / 自阴影 / IK / 可见性段落。**VMD 不含骨骼长度**,只有旋转(少数骨骼带位移),
因此服务端必须自带一套标准 MMD 骨架才能做 FK。
@@ -161,7 +161,7 @@ FK 旋转)。两份示例文件分别命中两种路径。
**标准骨架数值来源**:解析参考模型的 PMX 骨骼段实测得到(而非凭经验估计),
再去掉模型自身原点偏移并抹平左右不对称。关键比例:足首 1.43 / ひざ 6.57 /
髋 11.50 / センター 10.88 / 首 16.21 / 頭 17.16(总高约 19.4,髋高比约 59%);
大腿 4.94 + 小腿 5.15 ≈ 腿长 10.07。
大腿 4.94 + 小腿 5.15 ~ 腿长 10.07。
## 3. 上传限制
+1 -1
View File
@@ -121,5 +121,5 @@ spine = angle(neck, pelvis, midpoint(left_ankle, right_ankle))
`angle(a, b, c)` = 向量 `ba` 与 `bc` 的夹角余弦,即
`dot(normalize(a-b), normalize(c-b))`,落在 `[-1, 1]`。
**DTW 序列结构(冻结)**:每帧 = `[33 × (x, y, z), 9 个关节角余弦] = 108 维`。
**DTW 序列结构(冻结)**:每帧 = `[33 x (x, y, z), 9 个关节角余弦] = 108 维`。
低置信度点(`visibility < 0.5`)在插值阶段由相邻帧线性补全,不参与代价计算。
+1 -1
View File
@@ -27,7 +27,7 @@ ws://<windows-host>:8765/pose
bit2 = 上半身模式(仅 0..22 有效)
bit3-7 保留,必须为 0
4 4 frame_id u32 LE 单调递增,从 0 开始
8 231 keypoints 33 × 7B 见下
8 231 keypoints 33 x 7B 见下
--
合计 239
```
+2 -2
View File
@@ -24,7 +24,7 @@ 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 × 7B:s16 x, s16 y, s16 z, u8 conf
8 231 keypoints 33 x 7B:s16 x, s16 y, s16 z, u8 conf
合计 239
```
@@ -35,7 +35,7 @@ src/net/keypoint_frame.gd
## 关键实现
- 归一化系数统一 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()`
- 极值(±1.0)不溢出 int16
+3 -3
View File
@@ -21,8 +21,8 @@ src/anim/skeleton_retarget.gd
2. 取骨骼静止朝向 `rest_dir`(由该骨与首个子骨的位置差得出,**不假设模型骨骼轴向**)
3. 目标朝向由两个关键点在世界空间的方向得出
4. `delta` = rest_dir -> target_dir 的最小旋转四元数(保留扭转/roll)
5. `desired = Basis(delta) × rest_global_basis`
6. `pose_local = parent_global_basis⁻¹ × desired`
5. `desired = Basis(delta) x rest_global_basis`
6. `pose_local = parent_global_basis⁻¹ x desired`
**第 6 步的合成公式是实测标定的**:Godot 文档未写明 rest/pose 的合成顺序,
在真实 VRoid 模型上暴力枚举 5 种候选公式,只有该式误差为 1.9e-8(其余 ~0.14)。
@@ -31,7 +31,7 @@ src/anim/skeleton_retarget.gd
## 坐标转换
契约 4 的 MediaPipe 归一化坐标 -> Godot 世界方向:
`Vector3(x × aspect, −y, −z × aspect)`(x/z 以图像宽为基准故乘宽高比)。
`Vector3(x x aspect, -y, -z x aspect)`(x/z 以图像宽为基准故乘宽高比)。
## 验收
+5 -5
View File
@@ -20,20 +20,20 @@ src/score/scoring.gd
## 特征(契约 5 冻结)
每帧 = `[33 × (x,y,z), 9 个关节角余弦]` = **108 维**。
每帧 = `[33 x (x,y,z), 9 个关节角余弦]` = **108 维**。
低置信度点(conf < 0.5)对应维度**权重置 0**,不参与代价计算。
## DTW
- Sakoe-Chiba 带状约束 `|i − j| ≤ band`(默认 15 帧 ≈ 0.5 秒)
- Sakoe-Chiba 带状约束 `|i - j| <= band`(默认 15 帧 ~ 0.5 秒)
- `DtwMatcher.compute_full()` 离线段;`StreamingDtw` 逐帧流式推进,
每帧只计算带内一行,总体复杂度 O(n·m·band) 但摊到每帧 O(m·band)
每帧只计算带内一行,总体复杂度 O(n m band) 但摊到每帧 O(m band)
- 归一化:代价 / max(i,j)+1,得到「平均每步代价」
## 评分规则(`scoring.gd`)
`score = clamp(1 − cost/tolerance, 0, 1) × 100`,EMA 平滑抑制抖动,
等级 S(≥95) / A(≥85) / B(≥70) / C(≥55) / D,连击阈值 70。
`score = clamp(1 - cost/tolerance, 0, 1) x 100`,EMA 平滑抑制抖动,
等级 S(>=95) / A(>=85) / B(>=70) / C(>=55) / D,连击阈值 70。
## 验收