Unity / Unreal / Godot / Blender / Maya / glTF / OpenGL / Direct3D — ツール間で「同じ向き・同じ位置」を保つための座標変換行列を学ぶUnity / Unreal / Godot / Blender / Maya / glTF / OpenGL / Direct3D — learn the conversion matrices that keep the same orientation and position across tools
✈ 紙飛行機:機首=前方(Forward)/垂直尾翼=上(Up)/オレンジの翼=右(Right)。 ドラッグで回転・ホイールでズーム(両ビュー連動)。点線は変換対象の点を各エンジンの軸成分に分解した経路です。✈ Paper plane: nose = Forward / tail fin = Up / orange wing = Right. Drag to rotate, scroll to zoom (both views are linked). The dashed lines decompose the converted point into each engine's axis components.
各ツールの座標系は「右(Right)・上(Up)・前(Forward)がどの軸か」で決まります。
ツールごとに、意味方向(右・上・前)を各エンジン座標で表した列ベクトルを並べた行列
S = [ R U F ] を作ると、任意の意味的な方向 v は各ツールで S·v と表せます。
変換元 A から変換先 B への変換は「A の座標 → 意味空間 → B の座標」の合成で、
M = SB · SA−1 です。
S は符号付き置換行列(直交行列)なので S−1 = ST となり、
M も必ず「成分が 0, ±1 だけの行列」になります。つまり座標変換の実体は軸の入れ替えと符号反転です。
Each tool's coordinate system is defined by which axes mean Right, Up, and Forward.
For each tool, build the matrix S = [ R U F ] whose columns express those semantic
directions in that engine's coordinates; any semantic direction v is then S·v in that tool.
The conversion from tool A to tool B is the composition "A coordinates → semantic space → B coordinates":
M = SB · SA−1.
Since S is a signed permutation (orthogonal) matrix, S−1 = ST,
so M always contains only 0 and ±1 — a coordinate conversion is really just axis swaps and sign flips.
右手系⇔左手系の変換では det(M) = −1 になります。これは鏡映(反転)を含む変換で、純粋な回転では実現できません。実務では次の影響があります:
T′ = M · T · M−1 とすれば利き手系の違いも含めて正しく変換できるConverting between right- and left-handed systems gives det(M) = −1. The transform includes a reflection and cannot be achieved by pure rotation. In practice this means:
T′ = M · T · M−1, which correctly handles the handedness change too軸だけでなく1単位の長さもツールごとに違います: Unity = 1m、Godot = 1m、Blender = 1m(既定)、Unreal = 1cm、Maya = 1cm(既定)。 位置座標には単位換算の係数を掛けます(例: Unity→Unreal は ×100)。 上のチェックボックスをオンにすると 4×4 同次変換行列としてスケール込みで表示します。 方向ベクトルや法線には単位換算を掛けません。
Beyond axes, the length of one unit also differs per tool: Unity = 1 m, Godot = 1 m, Blender = 1 m (default), Unreal = 1 cm, Maya = 1 cm (default). Positions must be multiplied by the unit-conversion factor (e.g. Unity→Unreal is ×100). Turn on the checkbox above to show a 4×4 homogeneous matrix with the scale included. Never apply unit conversion to direction vectors or normals.
Blender はフロントビュー(テンキー1)が −Y 方向からモデルを見るため、 「キャラクターの正面を −Y に向ける」流儀が一般的です。一方、変換レシピとしては 単純に Y と Z を入れ替える(前方=+Y とみなす)方法が広く使われています。 どちらが正しいというものではなく、エクスポート設定(FBX/glTFの Forward/Up 指定)と 合わせて一貫させることが重要です。上のセレクタで両方試して、行列がどう変わるか比べてみてください。
Blender's front view (numpad 1) looks at the model from the −Y direction, so the convention of pointing a character's front toward −Y is common. As a conversion recipe, though, simply swapping Y and Z (treating forward as +Y) is widely used. Neither is "correct" — what matters is staying consistent with your export settings (the Forward/Up options in FBX/glTF export). Try both with the selector above and compare the matrices.
glTF 仕様は「右手系・+Y up・アセットの正面は +Z を向く・右は −X」と定めています。 一方 OpenGL の「前方 −Z」はカメラの視線方向の慣習です。glTF の +Z は 「モデルがカメラの方を向く」向きなので、両者の「前方」は意味が逆向きです。 本アプリは「前・上・右」の意味を保存するため、glTF ⇔ OpenGL の変換は恒等行列ではなく 上軸まわりの180°回転相当になります。軸ラベルを機械的にそろえるだけなら恒等変換ですが、 「モデルの正面をどちらに向けるか」という規約の違いが残る——Blender の ±Y 問題と同型の罠です。
実務での検算: Blender(前方 = −Y)→ glTF は公式エクスポータどおり
(x, y, z) ↦ (x, z, −y)、Unity → glTF は X 反転
(x, y, z) ↦ (−x, y, z) になります(上のセレクタで確認できます)。
The glTF spec says: right-handed, +Y up, assets face +Z, right is −X. OpenGL's "forward −Z", on the other hand, is a camera view-direction convention. glTF's +Z means the model faces the camera, so the two "forwards" point in opposite directions. This app preserves the meaning of forward/up/right, so glTF ⇔ OpenGL is not the identity but a 180° rotation about the up axis. Mechanically aligning axis labels would give the identity, yet the convention of which way the model faces still differs — the same trap as Blender's ±Y problem.
Sanity checks: Blender (forward = −Y) → glTF matches the official exporter,
(x, y, z) ↦ (x, z, −y), and Unity → glTF is an X flip,
(x, y, z) ↦ (−x, y, z) (verify with the selectors above).