# Nodes（ノード）

## 概要

****Nodes（ノード）****（`<span class="editor-theme-code">ufbx_node</span>`<span style="white-space: pre-wrap;">）は、FBX ファイルの </span>****シーングラフ（Scene Graph）****<span style="white-space: pre-wrap;"> を構成する要素です。</span>  
ノード自体は、変換情報（`<span class="editor-theme-code">ufbx_node.local_transform</span>`）と階層構造（`<span class="editor-theme-code">ufbx_node.parent</span>`<span style="white-space: pre-wrap;"> / </span>`<span class="editor-theme-code">ufbx_node.children[]</span>`）を保持します。

<span style="white-space: pre-wrap;">ノードは </span>****属性（attribute）****<span style="white-space: pre-wrap;"> によって機能が拡張されます。たとえば、</span>`<span class="editor-theme-code">ufbx_mesh</span>`<span style="white-space: pre-wrap;"> や </span>`<span class="editor-theme-code">ufbx_light</span>`<span style="white-space: pre-wrap;"> などです。</span>  
1つの属性が複数のノードに参照されることもあり、同じメッシュを異なるトランスフォームでインスタンス化することができます。

ノードは共通属性を直接保持しており、たとえば：

- `<span class="editor-theme-code">ufbx_node.mesh</span>`
- `<span class="editor-theme-code">ufbx_node.light</span>`

などを通じてアクセスできます。  
<span style="white-space: pre-wrap;">より珍しい属性は </span>`<span class="editor-theme-code">ufbx_node.attrib</span>`<span style="white-space: pre-wrap;"> に格納されており、</span>`<span class="editor-theme-code">ufbx_as_bone()</span>`<span style="white-space: pre-wrap;"> のようなヘルパ関数で具体的な型へキャスト（または </span>`<span class="editor-theme-code">NULL</span>`）できます。

逆に、「ノードがどの属性を持つか」を列挙する代わりに、「ある属性がどのノードで使用されているか」を調べることもできます。  
各属性（例：`<span class="editor-theme-code">ufbx_mesh</span>`<span style="white-space: pre-wrap;">）には </span>`<span class="editor-theme-code">ufbx_element.instances[]</span>`<span style="white-space: pre-wrap;"> フィールドがあり、それを参照しているすべてのノードを取得できます。</span>

---

## Transforms（変換）

ノードのローカル変換は、****平行移動（translation）・回転（rotation）・スケール（scale）****<span style="white-space: pre-wrap;"> の組み合わせで表されます。</span>  
<span style="white-space: pre-wrap;">これらは </span>`<span class="editor-theme-code">ufbx_node.local_transform</span>`<span style="white-space: pre-wrap;"> に格納され、</span>****親ノードに対する相対的な変換****<span style="white-space: pre-wrap;"> を表します。</span>

ノードはさらに以下のような便利フィールドも持っています：

- `<span class="editor-theme-code">ufbx_node.node_to_parent</span>`（親ノード座標系への行列）
- `<span class="editor-theme-code">ufbx_node.node_to_world</span>`（ワールド座標系への行列）

FBX の内部変換は非常に複雑ですが、ufbx ではこれを隠蔽するための機能を数多く備えています。  
`<span class="editor-theme-code">ufbx_node</span>`<span style="white-space: pre-wrap;"> のフィールドや </span>`<span class="editor-theme-code">ufbx_evaluate_transform()</span>`、`<span class="editor-theme-code">ufbx_bake_anim()</span>`<span style="white-space: pre-wrap;"> などを利用すれば、複雑さを意識せずに扱えます。</span>

（FBX の内部的な変換構造については「Node Transforms」セクションで詳細に説明されています。）

---

## Coordinate Spaces（座標系）

FBX ファイルは任意の座標系（軸向きや単位スケール）で保存されている場合があります。  
たとえば、前方／右／上方向の軸や単位長（1.0 の意味）が異なるケースです。

これに対応するため、`<span class="editor-theme-code">ufbx_scene.settings</span>`<span style="white-space: pre-wrap;"> から </span>****軸（axes）****<span style="white-space: pre-wrap;"> と </span>****単位メートル値（unit\_meters）****<span style="white-space: pre-wrap;"> を取得できます。</span>

また、`<span class="editor-theme-code">ufbx_load_opts.target_axes</span>`<span style="white-space: pre-wrap;"> および </span>`<span class="editor-theme-code">ufbx_load_opts.target_unit_meters</span>`<span style="white-space: pre-wrap;"> を設定することで、</span>  
読み込んだシーンを希望の座標系に変換することも可能です。

<span style="white-space: pre-wrap;">変換方法は </span>`<span class="editor-theme-code">ufbx_load_opts.space_conversion</span>`<span style="white-space: pre-wrap;"> によって指定します：</span>

<table id="bkmrk-%E5%AE%9A%E6%95%B0%E5%90%8D%E5%86%85%E5%AE%B9ufbx_space_conv"><colgroup><col></col><col></col></colgroup><tbody><tr><th>定数名

</th><th>内容

</th></tr><tr><td>`<span class="editor-theme-code">UFBX_SPACE_CONVERSION_TRANSFORM_ROOT</span>`

</td><td>ルートノードで空間変換を行う

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS</span>`

</td><td>各ノードのトランスフォームを補正する

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY</span>`

</td><td>ジオメトリにスケールを焼き込み、軸変換は ADJUST\_TRANSFORMS と同様に行う

</td></tr></tbody></table>

ufbx では、`<span class="editor-theme-code">ufbx_load_opts.handedness_conversion_axis</span>`<span style="white-space: pre-wrap;"> を使用して </span>****左右座標系（右手／左手）****<span style="white-space: pre-wrap;"> の変換も可能です。</span>  
通常、FBX は右手座標系が主流なので、右手系を使用する場合は不要です。  
左手座標系でシーンをロードする場合は、ミラー変換が必要になります。

また、カメラ（ローカル +X 向き）やライト（デフォルトではローカル -Y 向き）の軸を修正する機能もあります。  
<span style="white-space: pre-wrap;">これには </span>`<span class="editor-theme-code">ufbx_load_opts.target_camera_axes</span>`<span style="white-space: pre-wrap;"> および </span>`<span class="editor-theme-code">ufbx_load_opts.target_light_axes</span>`<span style="white-space: pre-wrap;"> を使用します。</span>

---

## Coordinate Spaces in Files（ファイル内の座標系）

FBX の座標系やエクスポータの違いは、多くのユーザーを混乱させてきました。  
（例：「FBX scale 100」「FBX scale 0.01」で検索するとよく出てきます。）

これは ufbx にも影響しますが、いくつかの方法で軽減可能です。

- ****Blender****<span style="white-space: pre-wrap;">：通常 Z-up メートル単位で動作しますが、FBX 書き出し時に </span>****Y-up / cm単位（100倍）****<span style="white-space: pre-wrap;"> に変換します。</span>  
    `<span class="editor-theme-code">UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS</span>`<span style="white-space: pre-wrap;"> を使うと、この100倍スケールを打ち消し、不要なスケーリングを取り除けます。</span>  
    一方、`<span class="editor-theme-code">UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY</span>`<span style="white-space: pre-wrap;"> はジオメトリ自体を0.01倍にスケールして正しい形状を維持しますが、中間ノードにスケール要素が残ります。</span>
- ****Maya****：多くの場合 cm 単位がネイティブです。  
    <span style="white-space: pre-wrap;">こちらでは </span>`<span class="editor-theme-code">UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY</span>`<span style="white-space: pre-wrap;"> の方が適しており、ノードスケールを変更せずにシーンを正しいスケールへ変換できます。</span>

結論として、****すべてのケースで完全に一貫した変換方法は存在しません。****  
ユーザーに変換方法を選択させるオプションを提供するのが望ましいです。

また、軽量ロード（`<span class="editor-theme-code">ufbx_load_opts.ignore_all_content = true</span>`）を使ってシーンを一度読み込み、  
`<span class="editor-theme-code">ufbx_metadata.exporter</span>`<span style="white-space: pre-wrap;"> を確認することで、エクスポータ（Blender / Maya 等）を特定し、</span>  
最適な変換方法を事前設定することも可能です。

> 💡 Blender でエクスポートする場合は、****「Apply Scalings」を “FBX Units Scale” に設定****するのが推奨です。  
> これにより、追加スケールなしのメートル単位（unit\_meters = 1.0）でエクスポートされます。

---

## サンプルコード

```c
// シーンをメートル単位・右手Y-upに変換してロード
ufbx_load_opts opts = { 0 };
opts.target_axes = ufbx_axes_right_handed_y_up;
opts.target_unit_meters = 1.0f;
opts.target_camera_axes = ufbx_axes_right_handed_y_up;
opts.target_light_axes = ufbx_axes_right_handed_y_up;

if (prefer_blender) {
    opts.space_conversion = UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS;
} else {
    opts.space_conversion = UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY;
}
```

---

## Geometry Transforms（ジオメトリ変換）

<span style="white-space: pre-wrap;">FBX では </span>****ジオメトリ変換（geometry transform）****<span style="white-space: pre-wrap;"> と呼ばれる特殊な変換をサポートしています。</span>  
これはノード直下のメッシュなどにのみ適用され、子ノードには継承されません。  
多くのシーングラフではこの仕組みを直接サポートしていないため、ufbx は代替方法を提供します。

### ジオメトリ変換の利用

<span style="white-space: pre-wrap;">ジオメトリ変換は </span>`<span class="editor-theme-code">ufbx_node.geometry_transform</span>`<span style="white-space: pre-wrap;"> に格納されます。</span>  
また、補助的な行列：

- `<span class="editor-theme-code">ufbx_node.geometry_to_node</span>`
- `<span class="editor-theme-code">ufbx_node.geometry_to_world</span>`

もあり、特に静的メッシュをワールド座標で扱う際に便利です。

### ジオメトリ変換を除去する

非静的シーンでのジオメトリ変換は扱いが難しいため、  
`<span class="editor-theme-code">ufbx_load_opts.geometry_transform_handling</span>`<span style="white-space: pre-wrap;"> によりロード時に削除することも可能です。</span>

<table id="bkmrk-%E5%AE%9A%E6%95%B0%E5%90%8D%E5%86%85%E5%AE%B9ufbx_geometry_t"><colgroup><col></col><col></col></colgroup><tbody><tr><th>定数名

</th><th>内容

</th></tr><tr><td>`<span class="editor-theme-code">UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES</span>`

</td><td>補助ノードを挿入して対応（確実だがノード数が増える）

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY</span>`

</td><td>ジオメトリ変換を頂点データに焼き込み（きれいだが制約あり）

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY_NO_FALLBACK</span>`

</td><td>補助ノードを絶対に作らない（ただし変換誤差が発生する）

</td></tr></tbody></table>

---

## Inherit Modes（継承モード）

FBX では非標準的な変換継承も可能です。  
<span style="white-space: pre-wrap;">これは </span>`<span class="editor-theme-code">ufbx_node.inherit_mode</span>`<span style="white-space: pre-wrap;"> によって示されます。</span>

<table id="bkmrk-%E3%83%A2%E3%83%BC%E3%83%89%E5%86%85%E5%AE%B9ufbx_inherit_mo"><colgroup><col></col><col></col></colgroup><tbody><tr><th>モード

</th><th>内容

</th></tr><tr><td>`<span class="editor-theme-code">UFBX_INHERIT_MODE_IGNORE_PARENT_SCALE</span>`

</td><td>親のスケールを無視

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_INHERIT_MODE_COMPONENTWISE_SCALE</span>`

</td><td>スケールと回転を独立して合成

</td></tr></tbody></table>

ufbx では、ロード時にこれらを標準的なシーングラフへ変換するオプションを用意しています：

<table id="bkmrk-%E5%AE%9A%E6%95%B0%E5%86%85%E5%AE%B9ufbx_inherit_mod"><colgroup><col></col><col></col></colgroup><tbody><tr><th>定数

</th><th>内容

</th></tr><tr><td>`<span class="editor-theme-code">UFBX_INHERIT_MODE_HANDLING_PRESERVE</span>`

</td><td>継承モードをそのまま保持（正確だが複雑）

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_INHERIT_MODE_HANDLING_HELPER_NODES</span>`

</td><td>補助ノードを追加して対応

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_INHERIT_MODE_HANDLING_COMPENSATE</span>`

</td><td>子ノードのスケールを逆補正（できない場合は補助ノード）

</td></tr><tr><td>`<span class="editor-theme-code">UFBX_INHERIT_MODE_HANDLING_IGNORE</span>`

</td><td>非標準継承をすべて無視（単純だが不正確）

</td></tr></tbody></table>

---

## Pivots（ピボット）

FBX ノードでは、****回転ピボット****<span style="white-space: pre-wrap;"> と </span>****スケールピボット****<span style="white-space: pre-wrap;"> を個別に設定できます。</span>  
ufbx では、デフォルトでこれらの効果をノードの平行移動へ焼き込みます。

回転ピボットとスケールピボットが同一である場合、  
`<span class="editor-theme-code">ufbx_load_opts.pivot_handling = UFBX_PIVOT_HANDLING_ADJUST_TO_PIVOT</span>`  
を設定することで、ピボットをジオメトリ変換へ変換することも可能です。  
この場合は、`<span class="editor-theme-code">ufbx_load_opts.geometry_transform_handling</span>`<span style="white-space: pre-wrap;"> も併せて指定します（例：</span>`<span class="editor-theme-code">UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY</span>`）。

---

## その他のプロパティ

ノードには変換以外にも以下のプロパティがあります：

- ****可視性****：`<span class="editor-theme-code">ufbx_node.visible</span>`<span style="white-space: pre-wrap;"> でノードを非表示にできる</span>
- ****マテリアルの上書き****：`<span class="editor-theme-code">ufbx_node.materials[]</span>`<span style="white-space: pre-wrap;"> でインスタンスごとに別マテリアルを適用できる</span>

---

## 備考

<span style="white-space: pre-wrap;">FBX 仕様ではこれらを </span>****“Geometric” transforms（ジオメトリック変換）****<span style="white-space: pre-wrap;"> と呼びますが、</span>  
<span style="white-space: pre-wrap;">ufbx では明確化のため </span>****geometry transforms****<span style="white-space: pre-wrap;"> と呼んでいます。</span>

---