坐标系¶
三个应用,三套关于"哪边朝上"和"一个单位有多大"的想法。本页解释 OTS 对此做了什么 — 以及它存在的意义所在的那一个错误。
你不需要读这一页就能用 OTS。当某个东西到达时旋转得很怪,或者当你想知道为什么这个工具信任文件而不是发送方时,再来读它。
规范空间¶
磁盘上的一切都存放在同一个空间里:
| 朝上 | Y |
| 手性 | 右 |
| 单位 | 米 |
| 旋转(动画) | Euler XYZ,度 |
| 旋转(静置) | Quaternion,w x y z |
这就是 Harmony 的 OGL 惯例,这也让 Harmony 成为那个恒等情形。其他每个应用都声明自己的空间,并在边界处转换。
| 应用 | 原生空间 | 到规范空间的转换 |
|---|---|---|
| Harmony | Y-up 右手系,米(OGL) | 恒等,外加一个运行时的 field ↔ OGL 缩放 |
| Blender | Z-up 右手系,米 | 调换为 (x, z, −y) |
| Maya | Y-up 右手系,厘米 | ×0.01,不换轴(Z-up 场景也会调换) |
文件头¶
每个文件都携带一个 coordinate_system 块,描述它是在什么空间下被写出的。每个读取方都会查看这个块并据此转换。
这就是为什么六条路径全都能用而不需要按路径分支的代码。读取方既不知道也不关心是哪个应用写的这个文件 — 它只关心文件声明了什么空间。新增一个应用,就是新增一个空间。
这也是为什么磁盘上的数值在版本之间从不改变含义:数字永远是规范的,而文件头永远在那里说明它们是相对于什么而言的。
四种通道,四种转换¶
有意思的地方在于,这四类数据的转换方式 各不相同。
带符号的轴向排列,然后是单位缩放。
一个 Blender 位置 (x, y, z) 会变成规范的 (x, z, −y)。一个 Maya 位置会被乘以 0.01。
w 分量保持不变;向量部分像位置一样被排列。
没有单位缩放 — 旋转没有长度。
一次 无符号 的排列,也没有单位缩放。
Scale 是一个量值。给它取负会把对象镜像,而那绝不是改变轴向惯例所应有的含义。
不是 排列。这就是那个会坑到人的地方。
见下文。
Euler 陷阱¶
下面就是那个错误,直白地说出来,因为它正是 OTS 之所以长成现在这个样子的原因:
一次旋转的基变换,不是对它的 Euler 角做一次排列。
它看起来就该是那样。如果位置会调换成 (x, y, z) → (x, z, −y),那旋转肯定也一样,对吧?而且在单位基底的情况下它碰巧是对的,这就让这个 bug 挺过了测试。
但为了 Z-up ↔ Y-up 的变换而排列 Euler 角,会产生一个 绕着错误的轴 的旋转。物体转了 — 所以没什么明显坏掉的迹象 — 但它转错了,而且这个误差会沿着一条 chain 累积。这正是手搓 3D 桥接的经典症状:"旋转是传过来了,但就是不对。"
正确的变换是对 旋转本身做一次共轭:
- 把 Euler 角转换为 quaternion。
- 用那个带符号的排列去旋转该 quaternion 的轴。
- 再转换回 Euler XYZ。
OTS 在所有地方都这么做,并带一条快速路径:当排列就是恒等时直接跳过这些计算(这也是为什么在 Y-up 场景下 Harmony ↔ Maya 一点开销都没有)。
只要能,旋转就以 quaternion 形式传递
除了 Euler 角,每个动画关键帧还携带一个由烘焙出的 world matrix 计算而来的真正 quaternion。它是 与顺序无关的,因此彻底绕开了 Euler 顺序的歧义 — 而且只要它存在,每个导入方都会优先用它。Euler 数值则作为人类可读的备选保留下来。
单位¶
| Harmony | 米,通过一个 OTS 向活动场景询问的 运行时 field ↔ OGL 缩放。它不是常数 — 它取决于分辨率、视野和宽高比 |
| Blender | 米。不转换 |
| Maya | 厘米。出去 ×0.01,进来 ×100 |
.pvt 的 Scale 选项是一个 独立的、面向用户的乘数,用于那些以奇怪工作尺寸创作的 rig。它不是应用之间的单位转换 — 后者是自动且不可见的。
Harmony 的"假 quaternion"¶
Harmony 有一个叫 QUATERNIONPATH 的 column 类型,而它 不是 quaternion。它是 3D-path column 的一个子类,存的是三个 Euler 角 分量加上一个速度。
所以一个 Harmony peg 的旋转在所有 peg 模式下都始终以 Euler XYZ 度数来读写,无论那个 column 叫什么名字。把它当作 (w, x, y, z) quaternion 来读会得到一堆垃圾。
参见 在 Harmony 中。
摄像机朝向¶
摄像机会多得到一次修正,因为"摄像机朝哪边看"是一个各应用各有约定的问题:
| 应用 | 摄像机沿哪个方向看 | 导入时 |
|---|---|---|
| Harmony | 它自己的 −Z — 已经是规范前方向 | 只有 roll |
| Maya | 它自己的 −Z — 已经是规范前方向 | 只有 roll |
| Blender | 在一个 Z-up 世界里沿 −Z | X 上 +90°,再加 roll |
Blender 的这个倾斜在导出时又会被去掉,所以一台朝前的摄像机往返之后会回到一个单位 peg,而不是每次都累积 90° 的漂移。
FOV 以 垂直 角度携带,与 Harmony 的场景设置一致,并且每个应用都被显式设为垂直 sensor fit。参见 摄像机。
已知限制¶
Z-up 的 Maya 场景只输出插值类型的 handle。 Keyframe 数值转换是正确的,但逐关键帧的 bezier tangent 会被简化。如果精确的 tangent 形状对你重要,就在 Maya 里用 Y-up 工作。