系列: 与 AI 一起学编程

Meshy 流水线,以及那件搞垮姿态估计的长袍

Meshy.ai 和引擎之间的七阶段资产流水线。

Text Prompt to Content Pack Seven stages, eight genres shipped, survives a 404 and a robe Text-to-3D PBR maps LOD0 Remesh LOD1 Organize Pack graceful degradation: LOD0-only on 404
一项资产,七个阶段,一个无论厂商 API 怎么样,SDK 都能加载的内容包。

生成式 3D 的好坏,取决于把一个提示词变成运行时可用资产的那条流水线有多好。RakuAI 搭建了一条能扛住厂商端点消失、Unicode 崩溃,以及演示视频从不会展示给你看的那些摩擦的流水线。

资产流水线是引擎里那种不起眼却承重的部分之一。它把设计师的一个想法(「我想要塔防包里有二十个敌人」)变成一个文件夹,里面装着贴好图、绑好骨骼、分好 LOD 的 3D 资产,供运行时加载。过去六周里,负责这项工作的流水线是 Meshy.ai,通过一个七阶段脚本接入,这个脚本位于运行时仓库中的 scripts/meshy_asset_pipeline.py

这个周六早上,Meshy 流水线和 SDK 包格式之间的 v1 桥接已经足够稳定,可以把我们学到的东西写下来了。三件事,没有一件写在 API 文档里。

这七个阶段实际做的是什么

按顺序,对每一项资产:

  1. 预览模式下的文本转 3D 生成。
  2. PBR 贴图生成:反照率(albedo)、金属度(metallic)、粗糙度(roughness)、法线(normal)。
  3. LOD0 轮询与下载。
  4. 针对 v1 API 创建重新网格化(remesh)任务。
  5. LOD1 重新网格化轮询与下载。
  6. 磁盘上的资产文件整理。
  7. 内容包组装。

流水线会把一项资产一路推到底,再处理下一项。它不做批处理。为什么不做批处理,答案痛苦地出现在下面第三条教训里。

教训一:长袍会搞垮姿态估计

对于大范围的类人形设计,Meshy 的文本转 3D 输出效果不错。骷髅、士兵、骑士、赤臂的法师,流水线给他们绑骨骼,骨骼能用,资产能发布。

但对重度着袍的类人形角色就不行了。RPG 内容包在 Sprint 2 撞上了这个问题。四项本该干净绑骨的资产,在姿态估计阶段的轮廓提取上失败了。其中两项是意料之中的(slime 和 wolf_enemy 不是类人形,姿态估计器本来就不该在它们身上找到手臂)。另外两项则出乎意料:mage_heroblacksmith,两个都是类人形,两个都失败了。

失败模式在于轮廓。Meshy 的姿态估计器通过观察模型渲染出的轮廓外形来寻找肢体。一个穿长袍的法师,轮廓里看不到腿,所以没有腿部关键点可以用来锚定骨骼。一个系围裙的铁匠,轮廓里胸部和臀部之间看不到躯干接缝,所以脊柱关节猜错了位置。模型本身没问题,骨骼绑定错了。

流水线里的修复方式是记录这次失败,保存未绑骨的几何体,并在资产清单里标出一个标志,写明「这一项需要人工绑骨」。提示词上的修复方式是,对任何需要自动绑骨的类人形角色,在文本提示词里明确写上「贴身衣物,肢体外露」。更根本的修复要靠 Meshy 那边,不是我们能做的。

在十三种类型里,失败率参差不齐。塔防是五分之一次绑骨失败,平台跳跃是六分之一次,RPG 是十一分之四次,而这四次里有三次都是服装几何体的问题。这个教训可以推广:当一个生成式模型出问题时,这个问题通常不是随机的,失败模式本身会告诉你一些关于这个模型训练数据的信息。

教训二:Unicode 会让任何把 stdout 导入文件的东西崩溃

RPG 包里的 Oni 阵营使用日文角色名。風代表风,雷代表雷,金剛代表金刚。这些就是 Meshy 任务提交时使用的资产名称。这条流水线在后台运行,把 stdout 重定向到一个日志文件,之后再解析这份日志来判断哪些资产成功了。

Oni 阵营的资产第一次运行时,全部失败了。错误是 Python stdout 抛出的一个 UnicodeEncodeError。构建机器上,当 stdout 不是一个 TTY 时,stdout 的默认编码是 ASCII。日文字符不是 ASCII。print 语句在资产还没提交给 Meshy 之前就崩溃了。

修复方式是在启动脚本里加一行:PYTHONIOENCODING=utf-8。一旦设置了这个环境变量,print 语句就能正常工作,资产也就能生成了。

这个教训比我年纪还大:任何把 Unicode 通过一个被重定向到 stdout 的流水线传递的东西,都需要显式设置编码。为一个已经被记录了二十年的问题损失了两天时间,记进了行为日志,在启动脚本里修好了。Meshy 没有修,因为这不是 Meshy 该修的问题。

教训三:厂商的 API 会消失

Sprint 2 进行到一半,Meshy v2 的 /remesh 端点开始返回 404。不是针对某个特定资产,而是每一次调用都这样。

重新网格化阶段的作用,是把 LOD0(高多边形、渲染成本高)转换成 LOD1(低多边形、渲染成本低)。没有重新网格化,资产就只能以 LOD0 形式发布。它们在开发者机器上渲染没问题,但会拖垮 AR 眼镜目标设备的帧率。

我不知道这个端点是被弃用了,还是被限制在了一个更高等级的付费方案后面,还是被搬走了却没设重定向,又或者只是暂时宕机。Meshy 的文档仍然引用着它,而调用它就是 404。流水线等不起厂商去搞清楚到底是哪种情况。

修复方式落在 meshy_asset_pipeline.py 的重新网格化阶段。在重新网格化调用外面包一层 try/except。失败时,把该资产记录为「仅 LOD0」,把这个事实写进资产清单,然后继续跑流水线的其余部分。每一项资产都有 LOD0,有些还有 LOD1。无论哪种情况,内容包都能发布。

这个教训是每一个依赖厂商 API 的项目迟早都会学到的那个教训:你所依赖的这个 API 不属于你,它可能在你不知情的情况下发生变化,唯一的防御手段就是优雅降级。我们现在有了。

流水线现在进展到哪了

十三种类型中的八种已经完成:太空射击、益智、卡牌对战、跑酷、平台跳跃、赛车、塔防、RPG。剩下五种(体育、模拟、沙盒、格斗、轻量级 MMO)排在队列里。

积分预算是个意外的惊喜。Sprint 2 对这两个阵营的类型内容,估算是大约 510 积分。实际花费持续低于估算 25% 到 35%。这给了这个项目足够的余量,可以推进剩下五种类型而不需要再讨论预算。

这个月初落地的 v1 桥接——scripts/generate_rakupack.py 配上二十四个一致性测试——正是让这一切在 SDK 那一侧变得可寻址的关键。一个使用 SDK 的开发者不需要知道某项资产是出自 Meshy 还是出自手工建模的流水线。内容包格式就是契约,Meshy 流水线产出内容包,SDK 加载内容包。

我为什么要把这些写下来

两个原因。

第一,上面这三个教训正是那种不会出现在厂商演示里、也不会出现在营销页面上的摩擦。长袍与姿态估计,Unicode 与 stdout,重新网格化与 404。如果你正在评估一家生成式 3D 厂商,读到这里说「这正是我在投入之前就想知道的那种事」,那这篇文章就物有所值了。

第二,这条流水线现在已经足够稳定,下一场对话不再是「Meshy 对我们管不管用」,而是「我们希望这个资产库变成什么样」。这是一场设计师的对话,不是工程的对话。工程这一侧已经通过退到幕后完成了它的工作。

八种类型完成,五种待办。流水线扛住了一次 404,扛住了一个日文字符。流水线目前还没能扛住一件长袍。这个周六过得很值。

生成你的 AI 真正能运行的世界

RakuAI 把生成式资产变成运行时可用的内容包——一份契约,任意来源,能抵御厂商演示视频不会给你看的那些摩擦。把你的创作带进一个为交付而生的空间运行时。

← 所有文章