2 Commits
Author SHA1 Message Date
zijunchiang 06c2fd688b docs: 全角 | / ? 改 ASCII(Gitea 混淆字符检测的剩余触发项) 2026-09-15 21:36:41 +08:00
zijunchiang 6913e181b5 docs: 其余易混淆字符改 ASCII(× − ≥ ≤ ≈ ✓ 等),消除 Gitea 告警
实测确认 Gitea 的「模棱两可 Unicode」检测覆盖:— – … § → × − ≥ ≤ ≈ ✓。
三库 .md/.txt 全部替换为 x - >= <= ~ OK;contracts 三库同源保持一致。
重新打包 v0.2.0。
2026-09-15 21:35:10 +08:00
8 changed files with 24 additions and 24 deletions
+7 -7
View File
@@ -35,7 +35,7 @@ opendance-web ←── 本仓库
| 模型检查 / 缩略图 | `models/model-inspector.ts`(面数 / 顶点 / 贴图 / **骨骼树** / humanoid 覆盖 / 可驱动性)、`models/model-thumbnail.ts`(纯 TS 光栅化 PNG,零原生依赖) | | 模型检查 / 缩略图 | `models/model-inspector.ts`(面数 / 顶点 / 贴图 / **骨骼树** / humanoid 覆盖 / 可驱动性)、`models/model-thumbnail.ts`(纯 TS 光栅化 PNG,零原生依赖) |
| 模型压缩包 | 纯 TS ZIP 读取器(`common/zip-reader.ts`)+ 自动搜索包内模型 + 外部 Assimp 转换(`models/model-convert.ts`);GLB 打包 `models/gltf-packer.ts`、贴图内嵌 `models/glb-textures.ts`、GLB->VRM 封装 `models/vrm-writer.ts` | | 模型压缩包 | 纯 TS ZIP 读取器(`common/zip-reader.ts`)+ 自动搜索包内模型 + 外部 Assimp 转换(`models/model-convert.ts`);GLB 打包 `models/gltf-packer.ts`、贴图内嵌 `models/glb-textures.ts`、GLB->VRM 封装 `models/vrm-writer.ts` |
| 默认模型种子 | `web-server/src/config/default-model.ts`(服务端/CLI 写入,运行期只读) | | 默认模型种子 | `web-server/src/config/default-model.ts`(服务端/CLI 写入,运行期只读) |
| 认证 | **本版本不含认证**(内网部署);上线前须补 ≥ T-WEB-011 | | 认证 | **本版本不含认证**(内网部署);上线前须补 >= T-WEB-011 |
## 3. 单次会话加载范围 ## 3. 单次会话加载范围
@@ -58,9 +58,9 @@ opendance-web ←── 本仓库
| 项 | 建议值 | | 项 | 建议值 |
|--|--| |--|--|
| 单任务文件数 | ≤ 6 | | 单任务文件数 | <= 6 |
| 单任务代码行数 | ≤ 1500 | | 单任务代码行数 | <= 1500 |
| 单任务 Token | ≤ 12K | | 单任务 Token | <= 12K |
| 契约引用 | 只引用锚点,不加载全文 | | 契约引用 | 只引用锚点,不加载全文 |
## 5. 目录结构 ## 5. 目录结构
@@ -88,7 +88,7 @@ opendance-web/
│ │ │ ├── glb-textures.ts # 把外部贴图内嵌进 GLB 的 BIN chunk │ │ │ ├── glb-textures.ts # 把外部贴图内嵌进 GLB 的 BIN chunk
│ │ │ ├── vrm-writer.ts # GLB -> VRM 1.0(写 VRMC_vrm 扩展) │ │ │ ├── vrm-writer.ts # GLB -> VRM 1.0(写 VRMC_vrm 扩展)
│ │ │ ├── model-inspector.ts # 面数 / 顶点 / 骨骼树 / humanoid 覆盖 / 可驱动性 │ │ │ ├── model-inspector.ts # 面数 / 顶点 / 骨骼树 / humanoid 覆盖 / 可驱动性
│ │ │ ├── model-thumbnail.ts # 纯 TS 光栅化 512×512 PNG(含蒙皮,零原生依赖) │ │ │ ├── model-thumbnail.ts # 纯 TS 光栅化 512x512 PNG(含蒙皮,零原生依赖)
│ │ │ ├── default-model-source.ts # 渲染 / 写入 src/config/default-model.ts │ │ │ ├── default-model-source.ts # 渲染 / 写入 src/config/default-model.ts
│ │ │ └── vrm-inspector.ts │ │ │ └── vrm-inspector.ts
│ │ ├── config/default-model.ts # 默认模型种子(由审核 / CLI 写入,运行期只读) │ │ ├── config/default-model.ts # 默认模型种子(由审核 / CLI 写入,运行期只读)
@@ -270,7 +270,7 @@ POST /api/models ─┬─.glb /.vrm /.gltf ─▶ importModelFile() 直接导
不做任何几何/材质损失。 不做任何几何/材质损失。
- `models/model-inspector.ts`:解析 GLB/VRM,算面数 / 顶点 / 贴图 / **骨骼树** / - `models/model-inspector.ts`:解析 GLB/VRM,算面数 / 顶点 / 贴图 / **骨骼树** /
humanoid 覆盖 / 可驱动性(缺哪些必需骨骼)/ warnings。 humanoid 覆盖 / 可驱动性(缺哪些必需骨骼)/ warnings。
- `models/model-thumbnail.ts`:纯 TS 软件光栅化 512×512 PNG(含蒙皮),零原生依赖。 - `models/model-thumbnail.ts`:纯 TS 软件光栅化 512x512 PNG(含蒙皮),零原生依赖。
- `models/default-model-source.ts`:渲染 / 写入 `src/config/default-model.ts`。 - `models/default-model-source.ts`:渲染 / 写入 `src/config/default-model.ts`。
- `config/default-model.ts`:默认模型种子(审核 / CLI 写入,运行期只读)。 - `config/default-model.ts`:默认模型种子(审核 / CLI 写入,运行期只读)。
- **压缩包自动搜索**:优先级 `.vrm` -> `.glb` -> `.gltf` -> `.pmx` -> `.fbx`;同一优先级内 - **压缩包自动搜索**:优先级 `.vrm` -> `.glb` -> `.gltf` -> `.pmx` -> `.fbx`;同一优先级内
@@ -329,7 +329,7 @@ POST /api/models ─┬─.glb /.vrm /.gltf ─▶ importModelFile() 直接导
maxBoneDepth=23`,`missingRequiredBones` 为全部 16 根(日文 MMD 骨名无法映射)。 maxBoneDepth=23`,`missingRequiredBones` 为全部 16 根(日文 MMD 骨名无法映射)。
- 直接上传 `.glb`:**HTTP 201 / 0.36s**、`conversionNote=直接导入(GLB,未做重编码)`, - 直接上传 `.glb`:**HTTP 201 / 0.36s**、`conversionNote=直接导入(GLB,未做重编码)`,
入库文件 sha256 与源文件**一致**。 入库文件 sha256 与源文件**一致**。
- 缩略图:512×512 PNG / 15,043 字节,纯 TS 光栅化(含蒙皮),目视确认为居中的 - 缩略图:512x512 PNG / 15,043 字节,纯 TS 光栅化(含蒙皮),目视确认为居中的
T-pose 角色图;真实 10MB VRM(83 关节、5307 顶点)单张耗时 60-121ms(中位 79ms)。 T-pose 角色图;真实 10MB VRM(83 关节、5307 顶点)单张耗时 60-121ms(中位 79ms)。
- 管理端 3D 预览放开到 `vrm/glb/gltf`(`fbx` 仍提示"仅归档,请先转换为 GLB/VRM"); - 管理端 3D 预览放开到 `vrm/glb/gltf`(`fbx` 仍提示"仅归档,请先转换为 GLB/VRM");
列表页显示 40px 缩略图。 列表页显示 40px 缩略图。
+5 -5
View File
@@ -54,9 +54,9 @@ rejected 已驳回
| 字段 | 类型 | 必填 | 说明 | | 字段 | 类型 | 必填 | 说明 |
|--|--|--|--| |--|--|--|--|
| `id` | number | 读 | | | `id` | number | 读 | |
| `title` | string | ✅ | 曲名,≤200 | | `title` | string | ✅ | 曲名,<=200 |
| `artist` | string | ✅ | 演唱者,≤200 | | `artist` | string | ✅ | 演唱者,<=200 |
| `album` | string | | 专辑,≤200 | | `album` | string | | 专辑,<=200 |
| `language` | string | | `zh` / `en` / `ja` / `ko` / `instrumental` | | `language` | string | | `zh` / `en` / `ja` / `ko` / `instrumental` |
| `durationMs` | number | | 时长毫秒 | | `durationMs` | number | | 时长毫秒 |
| `bpm` | number | | 节拍 | | `bpm` | number | | 节拍 |
@@ -74,7 +74,7 @@ rejected 已驳回
|--|--|--|--| |--|--|--|--|
| `id` | number | 读 | | | `id` | number | 读 | |
| `songId` | number\|null | | 关联曲目 | | `songId` | number\|null | | 关联曲目 |
| `name` | string | ✅ | 动作名称,≤200 | | `name` | string | ✅ | 动作名称,<=200 |
| `format` | enum | ✅ | `bvh` / `vmd` / `fbx` / `gltf` / `glb` / `keypoints-json` | | `format` | enum | ✅ | `bvh` / `vmd` / `fbx` / `gltf` / `glb` / `keypoints-json` |
| `fileUrl` | string | 读 | 原始动作文件 | | `fileUrl` | string | 读 | 原始动作文件 |
| `fileSize` | number | 读 | 字节 | | `fileSize` | number | 读 | 字节 |
@@ -95,7 +95,7 @@ rejected 已驳回
| 字段 | 类型 | 必填 | 说明 | | 字段 | 类型 | 必填 | 说明 |
|--|--|--|--| |--|--|--|--|
| `id` | number | 读 | | | `id` | number | 读 | |
| `name` | string | ✅ | 模型名称,≤200 | | `name` | string | ✅ | 模型名称,<=200 |
| `format` | enum | ✅ | `glb` / `vrm`(主力)/ `gltf` / `fbx`(历史数据)。上传的 PMX/FBX 会被服务端转换成 glb 或 vrm 再入库,见 model-formats.md 1.1 | | `format` | enum | ✅ | `glb` / `vrm`(主力)/ `gltf` / `fbx`(历史数据)。上传的 PMX/FBX 会被服务端转换成 glb 或 vrm 再入库,见 model-formats.md 1.1 |
| `vrmVersion` | string\|null | 读 | `0.x` / `1.0`,非 VRM 为 null | | `vrmVersion` | string\|null | 读 | `0.x` / `1.0`,非 VRM 为 null |
| `isPrimary` | boolean | | 全局默认模型;**同一时刻全库至多一个 `true`** | | `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 字节, VMD 是二进制格式:文件头 `Vocaloid Motion Data 0002`(30 字节)+ 模型名(20 字节,
Shift-JIS)+ 骨骼关键帧数组(每条 **111 字节**:15 字节骨骼名、uint32 帧号、 Shift-JIS)+ 骨骼关键帧数组(每条 **111 字节**:15 字节骨骼名、uint32 帧号、
float32×3 位移、float32×4 旋转四元数、64 字节贝塞尔插值参数)+ morph / 相机 / float32x3 位移、float32x4 旋转四元数、64 字节贝塞尔插值参数)+ morph / 相机 /
灯光 / 自阴影 / IK / 可见性段落。**VMD 不含骨骼长度**,只有旋转(少数骨骼带位移), 灯光 / 自阴影 / IK / 可见性段落。**VMD 不含骨骼长度**,只有旋转(少数骨骼带位移),
因此服务端必须自带一套标准 MMD 骨架才能做 FK。 因此服务端必须自带一套标准 MMD 骨架才能做 FK。
@@ -161,7 +161,7 @@ FK 旋转)。两份示例文件分别命中两种路径。
**标准骨架数值来源**:解析参考模型的 PMX 骨骼段实测得到(而非凭经验估计), **标准骨架数值来源**:解析参考模型的 PMX 骨骼段实测得到(而非凭经验估计),
再去掉模型自身原点偏移并抹平左右不对称。关键比例:足首 1.43 / ひざ 6.57 / 再去掉模型自身原点偏移并抹平左右不对称。关键比例:足首 1.43 / ひざ 6.57 /
髋 11.50 / センター 10.88 / 首 16.21 / 頭 17.16(总高约 19.4,髋高比约 59%); 髋 11.50 / センター 10.88 / 首 16.21 / 頭 17.16(总高约 19.4,髋高比约 59%);
大腿 4.94 + 小腿 5.15 ≈ 腿长 10.07。 大腿 4.94 + 小腿 5.15 ~ 腿长 10.07。
## 3. 上传限制 ## 3. 上传限制
+1 -1
View File
@@ -121,5 +121,5 @@ spine = angle(neck, pelvis, midpoint(left_ankle, right_ankle))
`angle(a, b, c)` = 向量 `ba` 与 `bc` 的夹角余弦,即 `angle(a, b, c)` = 向量 `ba` 与 `bc` 的夹角余弦,即
`dot(normalize(a-b), normalize(c-b))`,落在 `[-1, 1]`。 `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`)在插值阶段由相邻帧线性补全,不参与代价计算。 低置信度点(`visibility < 0.5`)在插值阶段由相邻帧线性补全,不参与代价计算。
+1 -1
View File
@@ -27,7 +27,7 @@ ws://<windows-host>:8765/pose
bit2 = 上半身模式(仅 0..22 有效) bit2 = 上半身模式(仅 0..22 有效)
bit3-7 保留,必须为 0 bit3-7 保留,必须为 0
4 4 frame_id u32 LE 单调递增,从 0 开始 4 4 frame_id u32 LE 单调递增,从 0 开始
8 231 keypoints 33 × 7B 见下 8 231 keypoints 33 x 7B 见下
-- --
合计 239 合计 239
``` ```
+5 -5
View File
@@ -74,7 +74,7 @@ web-server/scripts/import-default-model.mjs
| ZIP 读取 | `common/zip-reader.ts` | 中央目录/EOCD、STORE(0)+DEFLATE(8)、ZIP64 大小字段、Shift-JIS/GBK 文件名回退;拒绝 zip-slip 与加密条目;不支持的压缩方式报错 | | ZIP 读取 | `common/zip-reader.ts` | 中央目录/EOCD、STORE(0)+DEFLATE(8)、ZIP64 大小字段、Shift-JIS/GBK 文件名回退;拒绝 zip-slip 与加密条目;不支持的压缩方式报错 |
| 选主模型 | `model-convert.ts` | 格式优先级 `.vrm` -> `.glb` -> `.gltf` -> `.pmx` -> `.fbx`;同一优先级内"`MODEL_CONVERT_PMX` 指名字(默认 `Hatsune Miku.pmx`,大小写不敏感)-> 目录最浅 -> 文件最大" | | 选主模型 | `model-convert.ts` | 格式优先级 `.vrm` -> `.glb` -> `.gltf` -> `.pmx` -> `.fbx`;同一优先级内"`MODEL_CONVERT_PMX` 指名字(默认 `Hatsune Miku.pmx`,大小写不敏感)-> 目录最浅 -> 文件最大" |
| 直接导入 | `importModelFile()` | `.vrm`/`.glb`/`.gltf` 原样入库;`.glb` 若含 `VRMC_vrm`/`VRM` 扩展会被识别为 VRM | | 直接导入 | `importModelFile()` | `.vrm`/`.glb`/`.gltf` 原样入库;`.glb` 若含 `VRMC_vrm`/`VRM` 扩展会被识别为 VRM |
| 转换 | `convertModelFile()` / `convertModelArchive()` | `MODEL_CONVERT_FORMAT=glb`(默认)|`vrm`;超时 `MODEL_CONVERT_TIMEOUT_MS`(默认 180000) | | 转换 | `convertModelFile()` / `convertModelArchive()` | `MODEL_CONVERT_FORMAT=glb`(默认)|`vrm`;超时 `MODEL_CONVERT_TIMEOUT_MS`(默认 180000) |
| 回读校验 | `exportAndValidate()` | 每步产物**必须** `assimp info` 回读;退出码 0 但产物损坏也判失败 | | 回读校验 | `exportAndValidate()` | 每步产物**必须** `assimp info` 回读;退出码 0 但产物损坏也判失败 |
| GLB 打包 | `gltf-packer.ts` | GLB 直出失败时导出 `.gltf`,把 `.bin` 与外部贴图自行合成单文件 GLB | | GLB 打包 | `gltf-packer.ts` | GLB 直出失败时导出 `.gltf`,把 `.bin` 与外部贴图自行合成单文件 GLB |
| VRM 封装 | `vrm-writer.ts` | `MODEL_CONVERT_FORMAT=vrm` 时只改 JSON chunk 补 `extensions.VRMC_vrm`;humanoid 骨骼不全 -> **回退交付 GLB**,缺失骨骼写进说明 | | VRM 封装 | `vrm-writer.ts` | `MODEL_CONVERT_FORMAT=vrm` 时只改 JSON chunk 补 `extensions.VRMC_vrm`;humanoid 骨骼不全 -> **回退交付 GLB**,缺失骨骼写进说明 |
@@ -89,7 +89,7 @@ web-server/scripts/import-default-model.mjs
| 项 | 实现 | 说明 | | 项 | 实现 | 说明 |
|--|--|--| |--|--|--|
| 分析 | `model-inspector.ts` -> `models.stats` | 面数 / 顶点 / 网格 / 材质 / 贴图 / 节点 / 形变目标 / 动画 / 蒙皮骨骼数 / **骨骼树** / humanoid 覆盖 / **可驱动性(缺哪些必需骨骼)** / warnings;迁移 `AddModelStats1789460000000` 新增 `models.stats TEXT` | | 分析 | `model-inspector.ts` -> `models.stats` | 面数 / 顶点 / 网格 / 材质 / 贴图 / 节点 / 形变目标 / 动画 / 蒙皮骨骼数 / **骨骼树** / humanoid 覆盖 / **可驱动性(缺哪些必需骨骼)** / warnings;迁移 `AddModelStats1789460000000` 新增 `models.stats TEXT` |
| 缩略图 | `model-thumbnail.ts` -> `models.thumbnail_asset_id` | 纯 TS 软件光栅化 512×512 PNG(读 GLB/glTF -> 节点层级与蒙皮 -> 包围盒构图 -> 透视投影 -> z-buffer 平面着色 -> 手写 PNG),**零原生依赖**;失败或非 glTF 容器留空,前端退化为格式占位图 | | 缩略图 | `model-thumbnail.ts` -> `models.thumbnail_asset_id` | 纯 TS 软件光栅化 512x512 PNG(读 GLB/glTF -> 节点层级与蒙皮 -> 包围盒构图 -> 透视投影 -> z-buffer 平面着色 -> 手写 PNG),**零原生依赖**;失败或非 glTF 容器留空,前端退化为格式占位图 |
## 状态与默认模型(硬性) ## 状态与默认模型(硬性)
@@ -129,7 +129,7 @@ web-server/scripts/import-default-model.mjs
`missingRequiredBones` 为**全部 16 根**(日文 MMD 骨名无法映射到 humanoid)。 `missingRequiredBones` 为**全部 16 根**(日文 MMD 骨名无法映射到 humanoid)。
- 直接上传 `.glb` -> **HTTP 201 / 0.36s**、`conversionNote=直接导入(GLB,未做重编码)`, - 直接上传 `.glb` -> **HTTP 201 / 0.36s**、`conversionNote=直接导入(GLB,未做重编码)`,
入库文件 sha256 与源文件**一致**(不重编码)。 入库文件 sha256 与源文件**一致**(不重编码)。
- 缩略图:512×512 PNG / 15,043 字节,服务端纯 TS 光栅化(含蒙皮),目视确认为居中的 - 缩略图:512x512 PNG / 15,043 字节,服务端纯 TS 光栅化(含蒙皮),目视确认为居中的
T-pose 角色图;真实 10MB VRM(83 关节、5307 顶点)单张耗时 60-121ms(中位 79ms)。 T-pose 角色图;真实 10MB VRM(83 关节、5307 顶点)单张耗时 60-121ms(中位 79ms)。
- 审核:`POST /api/reviews/model/22/approve` 带 `setPrimary:true` -> 200, - 审核:`POST /api/reviews/model/22/approve` 带 `setPrimary:true` -> 200,
模型 `status=published`、`isPrimary=true`,源码种子写入 `sourceSha256=72eb6882...`; 模型 `status=published`、`isPrimary=true`,源码种子写入 `sourceSha256=72eb6882...`;
@@ -172,7 +172,7 @@ npm run test:smoke # 冒烟 [4] 段落
| GLB 失败回退 glTF->GLB 打包 | ✅ GLB 直出失败时 `gltf-packer.ts` 自行打包;每步 `assimp info` 回读校验 | | GLB 失败回退 glTF->GLB 打包 | ✅ GLB 直出失败时 `gltf-packer.ts` 自行打包;每步 `assimp info` 回读校验 |
| `MODEL_CONVERT_FORMAT=vrm` 封装 | ✅ `vrm-writer.ts` 补 `VRMC_vrm`;humanoid 不全回退 GLB | | `MODEL_CONVERT_FORMAT=vrm` 封装 | ✅ `vrm-writer.ts` 补 `VRMC_vrm`;humanoid 不全回退 GLB |
| 自动分析写入 `models.stats` | ✅ 实测 `triangles=9071 bones=238 humanoidMapped=0/22 drivable=false` | | 自动分析写入 `models.stats` | ✅ 实测 `triangles=9071 bones=238 humanoidMapped=0/22 drivable=false` |
| 缩略图生成且不影响入库 | ✅ 512×512 / 15,043 B;失败只告警 | | 缩略图生成且不影响入库 | ✅ 512x512 / 15,043 B;失败只告警 |
| 上传一律 pending、不自动设默认 | ✅ `create()` 固定 `PublishStatus.Pending` + `isPrimary=false` | | 上传一律 pending、不自动设默认 | ✅ `create()` 固定 `PublishStatus.Pending` + `isPrimary=false` |
| `setPrimary` 审核通过时生效 | ✅ `POST /api/reviews/model/22/approve` + `setPrimary:true` -> 200、`isPrimary=true` | | `setPrimary` 审核通过时生效 | ✅ `POST /api/reviews/model/22/approve` + `setPrimary:true` -> 200、`isPrimary=true` |
| 非 published 设默认 | ✅ `POST /api/models/:id/primary` -> 409 | | 非 published 设默认 | ✅ `POST /api/models/:id/primary` -> 409 |
@@ -199,7 +199,7 @@ node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 --dry-run # 只列
``` ```
实测(真实 21MB VRM,290 骨骼):回填出面数 53552 / 顶点 44662 / 骨骼 290 / 实测(真实 21MB VRM,290 骨骼):回填出面数 53552 / 顶点 44662 / 骨骼 290 /
humanoid 7/22,并重建 512×512 缩略图。 humanoid 7/22,并重建 512x512 缩略图。
文件在存储中丢失时返回 **409** 并说明原因,不会用全 0 结果覆盖既有分析数据。 文件在存储中丢失时返回 **409** 并说明原因,不会用全 0 结果覆盖既有分析数据。
另外 `StorageService.persistBuffer` 在 sha256 去重命中但文件不存在时会**自愈补写**, 另外 `StorageService.persistBuffer` 在 sha256 去重命中但文件不存在时会**自愈补写**,
避免换过 `STORAGE_DIR` 或只恢复数据库后出现"静默全 0 分析"。 避免换过 `STORAGE_DIR` 或只恢复数据库后出现"静默全 0 分析"。
+2 -2
View File
@@ -43,7 +43,7 @@ web-server/src/preprocess/*
- 33 点顺序与父节点表来自 `contracts/skeleton-topology.md`,虚拟关节 - 33 点顺序与父节点表来自 `contracts/skeleton-topology.md`,虚拟关节
`neck=33`、`pelvis=34` 只参与关节角计算,**不进入输出序列**。 `neck=33`、`pelvis=34` 只参与关节角计算,**不进入输出序列**。
- 投影:`x_img = 0.5 + x·s`,`y_img = 0.5 − y·s`,`z_img = −z·s`, - 投影:`x_img = 0.5 + x s`,`y_img = 0.5 - y s`,`z_img = -z s`,
`s = 0.35 / max(|x|,|y|,|z|)`(按整段动作自适应,保证不出画)。 `s = 0.35 / max(|x|,|y|,|z|)`(按整段动作自适应,保证不出画)。
- 置信度分层:直接映射 **1.0**、按层级推算 **0.5**、无法推算 **0.0**。 - 置信度分层:直接映射 **1.0**、按层级推算 **0.5**、无法推算 **0.0**。
@@ -84,7 +84,7 @@ npm run test # 85 例(含 31 例 VMD):解析 / FK / 重定向 /
npm run test:smoke # 冒烟 [3] 段落 npm run test:smoke # 冒烟 [3] 段落
``` ```
覆盖:60 帧样例经预处理后 **60 帧 × 33 点 × 9 关节角**、坐标落在 覆盖:60 帧样例经预处理后 **60 帧 x 33 点 x 9 关节角**、坐标落在
MediaPipe 归一化范围、置信度分层、时间戳按帧率推进、序列随时间变化、 MediaPipe 归一化范围、置信度分层、时间戳按帧率推进、序列随时间变化、
NDJSON 往返、解码器拒绝错误长度与 magic。 NDJSON 往返、解码器拒绝错误长度与 magic。
+1 -1
View File
@@ -181,7 +181,7 @@ install.sh 检测到缺 deploy/.env
- **模型转换配置**(`deploy/.env.example` 已写入): - **模型转换配置**(`deploy/.env.example` 已写入):
- `ASSIMP_BIN=assimp`:上传 `.zip` 模型包或 `.pmx`/`.fbx` 单文件时**必须**能调用到, - `ASSIMP_BIN=assimp`:上传 `.zip` 模型包或 `.pmx`/`.fbx` 单文件时**必须**能调用到,
否则转换失败 **422** 否则转换失败 **422**
- `MODEL_CONVERT_FORMAT=glb`(默认)|`vrm`:只影响需要转换的 PMX/FBX 的交付格式。 - `MODEL_CONVERT_FORMAT=glb`(默认)|`vrm`:只影响需要转换的 PMX/FBX 的交付格式。
`glb` 通用,两个客户端都原生加载;`vrm` 在 GLB 之上补 `VRMC_vrm` 扩展 `glb` 通用,两个客户端都原生加载;`vrm` 在 GLB 之上补 `VRMC_vrm` 扩展
(humanoid 骨骼 / 表情语义),**humanoid 骨骼名映射不全时自动回退交付 GLB** (humanoid 骨骼 / 表情语义),**humanoid 骨骼名映射不全时自动回退交付 GLB**
并写进 `models.conversion_note`。产物一律 `assimp info` 回读校验 并写进 `models.conversion_note`。产物一律 `assimp info` 回读校验