• v0.2.0 b7748a50eb

    zijunchiang released this 2026-09-15 21:53:29 +08:00 | 42 commits to main since this release

    OpenDance Studio — Web 管理服务端 v0.2.0

    三端开发顺序中的阶段一交付物:NestJS + TypeORM + 现有 MySQL 实例。

    v0.2.0 主要变更

    1. GLB / VRM 确定为模型主力格式,服务端与客户端分别落实支持库;
    2. 模型管理:.glb/.vrm 直接导入;.pmx/.fbx 服务端优先转 GLB、其次 VRM;
      压缩包自动搜索包内可用模型;入库自动生成缩略图与模型分析;
    3. 模型审核:上传一律 pending,审核界面含骨骼详细预览(评分基础);
    4. 新增历史模型回填(POST /api/models/:id/reanalyze + scripts/reanalyze-models.mjs);
    5. 契约升至 rest-api/data-models/model-formats 0.4.0、database 0.3.0。

    1. 模型格式策略

    上传 服务端行为
    .glb / .vrm / .gltf 直接导入,不重编码(GLB 含 VRM 扩展会自动识别为 VRM)
    .pmx / .fbx 转换:assimp → .glb →(失败)→ .gltf 后自行打包成 GLB →(MODEL_CONVERT_FORMAT=vrm 时)补 VRMC_vrm 扩展产出 VRM 1.0
    .zip 自动搜索包内可用模型:.vrm → .glb → .gltf(直接导入)优先,其次 .pmx → .fbx(转换)。同优先级内:指名字 → 目录最浅 → 文件最大

    每一步都用 assimp info 回读校验(Assimp 会写出损坏文件),贴图内嵌进 GLB;
    压缩包原件作为 model-archive 资产留存溯源。

    客户端支持库:Windows 客户端用 Godot 内置 GLTFDocument 加载 glTF/GLB/VRM;
    服务端的 humanoid 候选表与客户端 humanoid_map.gd 逐字对齐,并有单测断言两边一致。

    2. 自动缩略图与模型分析

    • 缩略图(model-thumbnail.ts):纯 TypeScript 软件光栅化(z-buffer + Lambert +
      完整蒙皮矩阵),零原生依赖。512×512 PNG 写入 models.thumbnail_asset_id。
    • 模型分析(model-inspector.ts):面数 / 顶点 / 网格 / 材质 / 贴图 / 形变目标 /
      动画 / 节点 / 骨骼与骨骼树 / humanoid 覆盖 / 可驱动性,写入 models.stats。
    • 两者失败都不阻断入库。

    3. 模型审核(本次重点)

    • 上传的模型状态一律 pending:不再自动发布、不再自动设默认。
    • 审核界面新增模型面板:体积、格式、容器、VRM 版本、面数/顶点/网格/材质/贴图/
      骨骼/节点/形变目标/动画、humanoid 覆盖进度、可驱动性结论(缺哪些必需骨骼)、
      warnings,以及骨骼详细预览(层级缩进、蒙皮/humanoid 徽章、子节点数、
      搜索保留祖先链、仅看蒙皮、限高滚动 + 只渲染前 400 行)。
    • 通过审核时可勾选**「同时设为全局默认模型」**(setPrimary=true);单独设置用
      POST /api/models/:id/primary(仅 published,否则 409)。

    为什么骨骼是审核重点:客户端按骨骼名映射 humanoid 规范(22 根,16 根为驱动
    33 点所必需)。实测日文 MMD 骨名的 PMX 转 GLB 后覆盖 0/22 → 无法驱动;
    某 VRM 只有 7/22;Bip001* 命名的 FBX 转 GLB 后 17/22。审核时就能拦下来。

    4. 历史模型回填(升级必做一次)

    升级后旧模型还没有分析与预览图:

    cd /opt/opendance/web-server
    node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000            # 回填全部缺 stats 的
    node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 --dry-run  # 只列清单
    node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000 --force    # 全部重算
    

    实测(真实 21 MB VRM / 290 骨骼):回填出面数 53552、顶点 44662、骨骼 290、
    humanoid 7/22,并重建 512×512 缩略图。
    文件在存储中丢失时接口返回 409 并说明原因(不会用全 0 结果覆盖已有数据);
    StorageService.persistBuffer 在 sha256 去重命中但文件不存在时会自愈补写
    (避免换过 STORAGE_DIR、或只恢复数据库后出现"静默全 0 分析")。

    5. 实测数据

    上传 MMD 压缩包(含 Hatsune Miku.pmx)
      → HTTP 201 / 0.86s / format=glb / status=pending
      → conversionNote = Hatsune Miku.pmx → GLB,已内嵌 2 张贴图
      → 分析:vertices=7155 triangles=9071 bones=238 humanoid=0/22 drivable=false
      → 缩略图:512×512 PNG / 15,043 字节(目视确认为带蒙皮的 T-pose 角色图)
    
    直接上传 GLB
      → HTTP 201 / 0.36s / conversionNote = 直接导入(GLB,未做重编码)
      → 入库文件 sha256 与源文件完全一致(证明没有重编码)
    
    审核
      → POST /api/reviews/model/22/approve { setPrimary: true } → 200
      → status=published、isPrimary=true;源码种子写入 sourceSha256=72eb6882…
      → 重建后 GET /api/catalog/export 的 defaultModelId 由 VRM 变为 22
    
    缩略图性能(真实 10MB VRM / 83 关节 / 5307 顶点):60–121ms(中位 79ms)
    
    契约校验 ✓ rest-api/data-models/model-formats 0.4.0、database 0.3.0;路由 30 条一致
    类型检查 ✓ tsc --noEmit 通过(strict)
    单元测试 ✓ 168 / 168 通过(10 个文件)
    生产构建 ✓ nest build + vite build 通过
    

    6. 部署更新

    cd /root
    curl -LO https://gitea.kasugano.cn/zijunchiang/opendance-web/releases/download/v0.2.0/opendance-web-v0.2.0.tar.gz
    curl -LO https://gitea.kasugano.cn/zijunchiang/opendance-web/releases/download/v0.2.0/SHA256SUMS
    sha256sum -c SHA256SUMS
    cp /opt/opendance/deploy/.env /root/opendance-env.bak.$(date +%s)      # 先备份现网配置
    tar -xzf opendance-web-v0.2.0.tar.gz && cd opendance-web-v0.2.0
    cp /opt/opendance/deploy/.env deploy/.env
    grep -q '^ADMIN_PORT=' deploy/.env || echo 'ADMIN_PORT=3001' >> deploy/.env
    grep -q '^HOST=' deploy/.env || echo 'HOST=0.0.0.0' >> deploy/.env
    grep -q '^MODEL_CONVERT_FORMAT=' deploy/.env || echo 'MODEL_CONVERT_FORMAT=glb' >> deploy/.env
    bash deploy/install.sh        # 会执行新迁移 AddModelStats
    # 回填历史模型(一次即可)
    cd /opt/opendance/web-server && node scripts/reanalyze-models.mjs --url http://127.0.0.1:3000
    

    前置:PMX/FBX 转换需要 Assimp(apt-get install -y assimp-utils libassimp6);
    .glb/.vrm 直接导入不需要 Assimp。

    已知事项

    • 缩略图是纯色块着色的 T-pose 轮廓图,用于列表页快速辨识;精细预览由管理端
      three.js 实时渲染(已放开 vrm/glb/gltf,FBX 仍不支持)。
    • PMX → GLB 会丢失物理、IK、toon/sphere 贴图、面部表情等 MMD 专有特性,
      属格式能力差异(见 contracts/model-formats.md §1.1)。
    • 模型授权信息需部署方核实后再通过审核。
    Downloads