背景
出帧台每渲一段动作都会从绑骨模型里读出三样东西,随 SpriteSheet 一路返回:
RigInfo —— 骨数、蒙皮网格数、顶点数、根骨名、加载器
root_motion —— 根骨水平位移轨(bake_stage.html 的 extractRootXZ 就地把 XZ 压平,位移单独抽出来,单位是「1.0 = 角色总高」)
available_clips —— 模型里有哪些预设动作及各自时长
三样都算完就丢。在 origin/main 上核实消费方:
|
消费处 |
sheet.rig |
0 |
available_clips |
0 |
root_motion(出帧台那份) |
0 —— grep 命中的 3 处是 postprocess.rootmotion,那是从交付帧像素反推位移的另一套东西,与出帧台读出的根骨轨无关 |
CharacterOutfit 现在只有 id / name / description / preview_url / model_3d_url / actions。
问题
一、RigInfo 的用途在注释里写着,但没有代码在用。
interfaces.py 的 RigInfo docstring:「已确立(不必每次重验):自动绑骨产出 28 骨 · humanoid 命名 · 无 mixamorig: 前缀。对不上说明拿到的不是我们这条链路的产物,该停下来看,而不是接着渲。」
没有任何一处执行这个「停下来看」。一个不是本链路产出的模型(用户自己传的、或换了绑骨供应商的)会照常渲完并交付。
二、位移轨算了两遍,且用的是次优的那一遍。
出帧台从根骨动画轨直接读出位移,那是作者意图的精确值。postprocess.rootmotion.extract_root_motion 则从交付帧的像素反推——那是在帧已经被对齐成原地之后再猜,信息在对齐那一步就损失了。
三渲二这条路线上,精确值是白送的(模型里就有),却没被存下来。
三、浏览器出帧那条把这三样丢得更干净。
runClientBake 的 completeBake 只回传 clip 与 sampleTimes;BakeStage.rigInfo() 和根骨轨在浏览器里算完就随页面一起销毁,服务端连拿都拿不到。这是 #714 引入的,本 issue 一并收。
方案
落点:CharacterOutfit 增加一个可空的派生资产字段,承载骨架事实与挂点;CharacterAction(或其 sequence)承载该动作的位移轨。两者都是纯加法,不改任何既有字段。
骨架事实取出帧台已经读到的:骨数、根骨名、骨名列表。骨名列表是挂点的来源——自动绑骨保留了挂点骨,武器握持只需按骨名定位,不必重新标定。
位移轨取出帧台那份(根骨轨),不取像素反推那份。两者并存时以前者为准,并在字段注释里写明来源,避免下一个人再算第三遍。
校验:拿到骨架事实之后,RigInfo docstring 里那条「28 骨 · humanoid 命名 · 无 mixamorig: 前缀」才有地方执行。不满足时不静默继续。
浏览器出帧:completeBake 的入参补上 rigInfo 与根骨轨,与服务端渲那条对齐——两条路必须交回同样的东西,否则同一个造型走哪条路存下来的资产不一样。
不包含
验收
备注
#192 的子项把这条写成「无处存放就等于每补一个动作都重做一遍前四段,直接抹掉本路线的成本优势」。该表述不成立:_produce_action 见到 model_3d_url 就直接走出帧,绑骨只在建资产路径上调,动作生成路径碰不到它——成本复用在 #277 落 model_3d_url 时就解决了。本 issue 的实际收益是「已经算出来的数据不再被丢掉」与「已写在注释里的校验能真的执行」,不是省钱。
背景
出帧台每渲一段动作都会从绑骨模型里读出三样东西,随
SpriteSheet一路返回:RigInfo—— 骨数、蒙皮网格数、顶点数、根骨名、加载器root_motion—— 根骨水平位移轨(bake_stage.html的extractRootXZ就地把 XZ 压平,位移单独抽出来,单位是「1.0 = 角色总高」)available_clips—— 模型里有哪些预设动作及各自时长三样都算完就丢。在
origin/main上核实消费方:sheet.rigavailable_clipsroot_motion(出帧台那份)postprocess.rootmotion,那是从交付帧像素反推位移的另一套东西,与出帧台读出的根骨轨无关CharacterOutfit现在只有id / name / description / preview_url / model_3d_url / actions。问题
一、
RigInfo的用途在注释里写着,但没有代码在用。interfaces.py的RigInfodocstring:「已确立(不必每次重验):自动绑骨产出 28 骨 · humanoid 命名 · 无mixamorig:前缀。对不上说明拿到的不是我们这条链路的产物,该停下来看,而不是接着渲。」没有任何一处执行这个「停下来看」。一个不是本链路产出的模型(用户自己传的、或换了绑骨供应商的)会照常渲完并交付。
二、位移轨算了两遍,且用的是次优的那一遍。
出帧台从根骨动画轨直接读出位移,那是作者意图的精确值。
postprocess.rootmotion.extract_root_motion则从交付帧的像素反推——那是在帧已经被对齐成原地之后再猜,信息在对齐那一步就损失了。三渲二这条路线上,精确值是白送的(模型里就有),却没被存下来。
三、浏览器出帧那条把这三样丢得更干净。
runClientBake的completeBake只回传clip与sampleTimes;BakeStage.rigInfo()和根骨轨在浏览器里算完就随页面一起销毁,服务端连拿都拿不到。这是 #714 引入的,本 issue 一并收。方案
落点:
CharacterOutfit增加一个可空的派生资产字段,承载骨架事实与挂点;CharacterAction(或其 sequence)承载该动作的位移轨。两者都是纯加法,不改任何既有字段。骨架事实取出帧台已经读到的:骨数、根骨名、骨名列表。骨名列表是挂点的来源——自动绑骨保留了挂点骨,武器握持只需按骨名定位,不必重新标定。
位移轨取出帧台那份(根骨轨),不取像素反推那份。两者并存时以前者为准,并在字段注释里写明来源,避免下一个人再算第三遍。
校验:拿到骨架事实之后,
RigInfodocstring 里那条「28 骨 · humanoid 命名 · 无mixamorig:前缀」才有地方执行。不满足时不静默继续。浏览器出帧:
completeBake的入参补上 rigInfo 与根骨轨,与服务端渲那条对齐——两条路必须交回同样的东西,否则同一个造型走哪条路存下来的资产不一样。不包含
postprocess.rootmotion(i2v 路线仍然只能从像素反推,那条路上没有骨架)。schema_sync巡检能覆盖;真正的迁移机制是 feat(ops): 引入数据库迁移机制 #633。验收
mixamorig:前缀」时不静默交付备注
#192 的子项把这条写成「无处存放就等于每补一个动作都重做一遍前四段,直接抹掉本路线的成本优势」。该表述不成立:
_produce_action见到model_3d_url就直接走出帧,绑骨只在建资产路径上调,动作生成路径碰不到它——成本复用在 #277 落model_3d_url时就解决了。本 issue 的实际收益是「已经算出来的数据不再被丢掉」与「已写在注释里的校验能真的执行」,不是省钱。