4.1 KiB
4.1 KiB
contracts/model-formats.md — 模型与动作格式契约 v0.1.0
1. 角色模型(models)
| 格式 | 扩展名 | 支持级别 | 说明 |
|---|---|---|---|
| VRM | .vrm |
首选(P0) | glTF 2.0 二进制 + VRM 扩展;Windows 端 godot-vrm 直接加载 |
| glTF Binary | .glb |
P1 | 需含骨骼(skin);无骨骼则仅作静态展示 |
| glTF | .gltf (+ .bin, 贴图) |
P2 | 多文件,管理端需打包为 zip 上传 |
| FBX | .fbx |
P2 | 需 Assimp 转换,管理端仅归档,不保证重定向质量 |
VRM 优先的选取顺序见 data-models.md §4.1。
VRM 版本识别:读取 GLB 的 JSON chunk,检查 extensions.VRM(0.x)或
extensions.VRMC_vrm(1.0),写入 models.vrm_version。
2. 动作数据(motions)
| 格式 | 扩展名 | 预处理支持 | 说明 |
|---|---|---|---|
| BVH | .bvh |
✅ 内置纯 TS 解析器 | 文本格式,服务端直接解析 → FK → MediaPipe33 |
| FBX | .fbx |
⚠️ 需 Assimp | 服务端调用 assimp 可执行文件导出为 BVH/glTF 后再解析;未安装则 preprocessState=failed |
| glTF/GLB | .gltf / .glb |
⚠️ 需 Assimp | 同上 |
| 关键点 JSON | .json |
✅ 直通校验 | 已是 mediapipe33@0.1.0 结构,仅做校验与归一化 |
2.1 预处理产物(冻结)
- 格式:NDJSON(
application/x-ndjson),每行一帧,UTF-8 无 BOM - 一行结构:
{"frame":0,"timeMs":0.0,"points":[[0.5,0.5,0.0,1.0],"…33 项"],"angles":[1.0,"…9 项"]}
points[i] = [x, y, z, confidence],语义与websocket-keypoints.md解码后完全一致angles为skeleton-topology.md§5 定义的 9 个关节角余弦,顺序固定:[shoulder_L, shoulder_R, elbow_L, elbow_R, hip_L, hip_R, knee_L, knee_R, spine]- 帧率:保留源帧率;
fps写入motions.fps,缺省 30 - 坐标系换算:所有 3D 动作数据统一转到 Y 轴向上、右手系、骨盆为原点,
再投影到 MediaPipe 归一化图像空间:
x_img = 0.5 + x_world * scale,y_img = 0.5 - y_world * scale,z_img = -z_world * scale,scale = 0.35 / max(|x|,|y|,|z|)(按整段动作的最大范围自适应,保证不出画) - 缺失关节(BVH 中不存在对应骨骼):
confidence = 0.0,坐标沿用最近可用父节点
2.2 BVH 关节名映射(默认表,可在 web-server/src/preprocess/joint-map.ts 扩展)
| MediaPipe 点 | 常见 BVH 关节名(不区分大小写,按序匹配) |
|---|---|
| 0 nose | Head, Neck1, Head_Nub |
| 11 left_shoulder | LeftShoulder, LeftArm, LShoulder |
| 12 right_shoulder | RightShoulder, RightArm, RShoulder |
| 13 left_elbow | LeftForeArm, LeftElbow, LElbow |
| 14 right_elbow | RightForeArm, RightElbow, RElbow |
| 15 left_wrist | LeftHand, LeftWrist, LHand |
| 16 right_wrist | RightHand, RightWrist, RHand |
| 23 left_hip | LeftUpLeg, LeftHip, LHipJoint |
| 24 right_hip | RightUpLeg, RightHip, RHipJoint |
| 25 left_knee | LeftLeg, LeftKnee, LKnee |
| 26 right_knee | RightLeg, RightKnee, RKnee |
| 27 left_ankle | LeftFoot, LeftAnkle, LAnkle |
| 28 right_ankle | RightFoot, RightAnkle, RAnkle |
| 31 left_foot_index | LeftToeBase, LeftToe, LToe |
| 32 right_foot_index | RightToeBase, RightToe, RToe |
未映射到的点按 skeleton-topology.md §5 的层级由父节点推算,
并置 confidence 降低(0.5),表示估算而非实测。
3. 上传限制
| 项 | 值 |
|---|---|
| 单文件上限 | 512 MiB(UPLOAD_MAX_BYTES 可覆盖) |
| 允许扩展名 | 上表全部;其他一律 422 |
| 存储路径 | ${STORAGE_DIR}/{kind}/{yyyy}/{mm}/{sha256前2位}/{sha256}.{ext} |
| 去重 | 相同 sha256 复用同一 assets 记录,不重复落盘 |
| 文件名 | 服务端不使用原始文件名做路径,只存 assets.original_name |
4. 开源依赖与许可证(引用 open-source-credits.md)
bvh(MIT)— BVH 解析参考实现Assimp(BSD-3-Clause)— FBX/glTF 转换,可选外部依赖@pixiv/three-vrm(MIT)— 管理端 VRM 预览three(MIT)— 管理端 3D 预览