需求 1:系统确定以 GLB / VRM 为模型主力格式
- 服务端新增支持库:
- model-inspector.ts:解析 GLB/VRM 的面数、顶点、材质、贴图、形变目标、
**骨骼树(名称/层级/是否蒙皮/humanoid 映射/子节点数)**、humanoid 覆盖率与可驱动性
- model-thumbnail.ts:**纯 TS 软件光栅化**(z-buffer + Lambert + 完整蒙皮矩阵)
生成 512×512 PNG 缩略图,零原生依赖、不装 headless-gl
- vrm-writer.ts:GLB → VRM 1.0(写入 VRMC_vrm 扩展与 humanoid 映射)
- gltf-packer.ts:glTF(.gltf + .bin + 贴图)→ 单文件 GLB
- humanoid 候选表与 Godot 客户端 humanoid_map.gd **逐字对齐**,并有单测断言两边一致
(服务端判定的"可驱动" = 客户端实际能否驱动)
需求 2:模型管理
- .glb / .vrm / .gltf **直接导入**(不重编码,GLB 含 VRM 扩展会自动识别为 VRM)
- .pmx / .fbx 服务端转换:assimp → .glb →(失败)→ .gltf 后自行打包成 GLB
→(MODEL_CONVERT_FORMAT=vrm 时)补 VRMC_vrm 产出 VRM 1.0;每步 assimp info 回读校验
- .zip **自动搜索包内可用模型**:.vrm → .glb → .gltf(直接导入)优先,
其次 .pmx → .fbx(转换);同优先级内按"指名字 → 目录最浅 → 文件最大"
- 入库后自动分析(models.stats)与生成缩略图(models.thumbnail_asset_id),
失败均不阻断入库;管理端列表显示小缩略图、预览放开到 vrm/glb/gltf
需求 3:审核功能
- 上传的模型状态**一律 pending**(不再自动发布、不再自动设默认)
- 审核界面新增模型面板:体积、面数、顶点、材质、贴图、骨骼、形变目标等指标,
humanoid 覆盖进度、可驱动性结论(缺哪些必需骨骼)、warnings,以及
**骨骼详细预览**(层级缩进、蒙皮/Humanoid 徽章、子节点数、搜索保留祖先链、
仅看蒙皮、限高滚动 + 只渲染前 400 行)
- 审核通过可带 setPrimary=true 一并设为默认模型(此时才写源码种子);
POST /api/models/:id/primary 仅允许 published(否则 409)
- scripts/import-default-model.mjs 改为"上传 → 审核通过 + 设默认"流程
其它:
- models 新增 stats 列(迁移 AddModelStats1789460000000,已在真实库执行)
- 契约升至 rest-api/data-models/model-formats 0.4.0、database 0.3.0(另两库已同步)
- 版本号 0.1.0 → 0.2.0(package.json ×2 + lockfile + project.yaml)
- 文档:README.txt / DSH.md / project.yaml / tasks 005·007·010 全面更新;
顶层开发书更新为 v1.4
验证:168 项单测通过(10 文件);契约 6 项与 29 条路由一致;typecheck/build 通过;
真实端到端:MMD 压缩包 → GLB + 分析(面数 9071/骨骼 238/humanoid 0-22) + 缩略图(15KB PNG);
GLB 直接导入 sha256 与源文件一致;审核通过后 defaultModelId 由 VRM 变为该模型
62 lines
2.6 KiB
Bash
62 lines
2.6 KiB
Bash
# ============================================================
|
||
# OpenDance Studio Web 服务端 —— 环境变量样例
|
||
# 复制为 .env 后填写。.env 已被 .gitignore 忽略,禁止提交。
|
||
# ============================================================
|
||
|
||
# ---- 服务 ----
|
||
NODE_ENV=production
|
||
# 软件 API 端口:Windows/Godot 客户端、Android App 调用,
|
||
# 只提供 /api、/health、/static、/contracts,不提供管理端页面
|
||
PORT=3000
|
||
# 管理端端口:浏览器访问,提供管理端 SPA 页面 + 上面全部接口。
|
||
# 默认取 PORT + 1;与 PORT 设为相同值即为单端口兼容模式(管理页面与接口同端口)。
|
||
ADMIN_PORT=3001
|
||
# 监听地址(软件 API 端口)。本地开发用 0.0.0.0(便于同网段设备联调);
|
||
# 生产环境若反代与后端同机,建议改为 127.0.0.1
|
||
HOST=0.0.0.0
|
||
# 管理端监听地址,默认与 HOST 相同。
|
||
# 需要"接口对外、管理端只对本机开放"时可单独设置,例如 ADMIN_HOST=127.0.0.1
|
||
# ADMIN_HOST=0.0.0.0
|
||
|
||
# 管理端静态站点目录(默认取 ../admin)。管理端页面只在 ADMIN_PORT 上提供,
|
||
# 反向代理把浏览器请求转发到 ADMIN_PORT、客户端接口请求转发到 PORT,
|
||
# 见 deploy/proxy/README.md
|
||
ADMIN_DIR=../admin
|
||
|
||
# ---- 现有 MySQL 实例(外部提供,本项目不部署 MySQL)----
|
||
# 当前部署:MariaDB 10.11 @ 192.168.150.10
|
||
DB_HOST=192.168.150.10
|
||
DB_PORT=3306
|
||
DB_USER=dpendance
|
||
DB_PASS=<部署方提供>
|
||
DB_NAME=dpendance
|
||
# 生产环境必须为 false,表结构一律走 TypeORM migration
|
||
DB_SYNCHRONIZE=false
|
||
DB_LOGGING=false
|
||
|
||
# ---- 文件存储 ----
|
||
# 上传文件的落盘目录(本机路径,生产环境建议用部署脚本的默认值
|
||
# /var/lib/opendance/storage,并确保服务用户可写)
|
||
STORAGE_DIR=/data/storage
|
||
# 单文件上传上限(字节),默认 512 MiB
|
||
UPLOAD_MAX_BYTES=536870912
|
||
|
||
# ---- 可选的 Assimp(FBX/glTF 动作预处理 + 压缩包模型转换)----
|
||
# 未安装时 FBX 动作的预处理会以失败状态返回,不影响 BVH/VMD;
|
||
# 但上传 .zip 模型包时必须能调用到它
|
||
ASSIMP_BIN=assimp
|
||
# PMX/FBX 的交付格式:glb(默认)| vrm
|
||
MODEL_CONVERT_FORMAT=glb
|
||
# 压缩包里优先选用的 PMX 文件名
|
||
MODEL_CONVERT_PMX=Hatsune Miku.pmx
|
||
# 单次转换超时(毫秒)
|
||
MODEL_CONVERT_TIMEOUT_MS=180000
|
||
|
||
# ---- 默认模型(可选)----
|
||
# DEFAULT_MODEL_ID=1
|
||
|
||
# ---- 契约目录(可选)----
|
||
# 设置后 /health 与 /api/catalog/version 会读取该目录下的 VERSION 文件;
|
||
# 未设置时使用编译进代码的契约版本常量
|
||
# CONTRACTS_DIR=/opt/opendance/contracts
|