Skip to main content

Nodes(ノード)

Nodes(ノード) — ufbx ドキュメント日本語訳

本文・コード例は ufbx の公開ライセンス(MIT / Unlicense)に基づき翻訳・再構成しています。
© 2020 Samuli Raivio — Original docs under Unlicense/MIT. Japanese translation by <あなたの名前>.


概要

Nodes(ノード)ufbx_node)は、FBX ファイルの シーングラフ(Scene Graph) を構成する要素です。
ノード自体は、変換情報(ufbx_node.local_transform)と階層構造(ufbx_node.parent / ufbx_node.children[])を保持します。

ノードは 属性(attribute) によって機能が拡張されます。たとえば、ufbx_meshufbx_light などです。
1つの属性が複数のノードに参照されることもあり、同じメッシュを異なるトランスフォームでインスタンス化することができます。

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

  • ufbx_node.mesh
  • ufbx_node.light

などを通じてアクセスできます。
より珍しい属性は ufbx_node.attrib に格納されており、ufbx_as_bone() のようなヘルパ関数で具体的な型へキャスト(または NULL)できます。

逆に、「ノードがどの属性を持つか」を列挙する代わりに、「ある属性がどのノードで使用されているか」を調べることもできます。
各属性(例:ufbx_mesh)には ufbx_element.instances[] フィールドがあり、それを参照しているすべてのノードを取得できます。


Transforms(変換)

ノードのローカル変換は、平行移動(translation)・回転(rotation)・スケール(scale) の組み合わせで表されます。
これらは ufbx_node.local_transform に格納され、親ノードに対する相対的な変換 を表します。

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

  • ufbx_node.node_to_parent(親ノード座標系への行列)
  • ufbx_node.node_to_world(ワールド座標系への行列)

FBX の内部変換は非常に複雑ですが、ufbx ではこれを隠蔽するための機能を数多く備えています。
ufbx_node のフィールドや ufbx_evaluate_transform()ufbx_bake_anim() などを利用すれば、複雑さを意識せずに扱えます。

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


Coordinate Spaces(座標系)

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

これに対応するため、ufbx_scene.settings から 軸(axes)単位メートル値(unit_meters) を取得できます。

また、ufbx_load_opts.target_axes および ufbx_load_opts.target_unit_meters を設定することで、
読み込んだシーンを希望の座標系に変換することも可能です。

変換方法は ufbx_load_opts.space_conversion によって指定します:

定数名

内容

UFBX_SPACE_CONVERSION_TRANSFORM_ROOT

ルートノードで空間変換を行う

UFBX_SPACE_CONVERSION_ADJUST_TRANSFORMS

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

UFBX_SPACE_CONVERSION_MODIFY_GEOMETRY

ジオメトリにスケールを焼き込み、軸変換は ADJUST_TRANSFORMS と同様に行う

ufbx では、ufbx_load_opts.handedness_conversion_axis を使用して 左右座標系(右手/左手) の変換も可能です。
通常、FBX は右手座標系が主流なので、右手系を使用する場合は不要です。
左手座標系でシーンをロードする場合は、ミラー変換が必要になります。

また、カメラ(ローカル +X 向き)やライト(デフォルトではローカル -Y 向き)の軸を修正する機能もあります。
これには ufbx_load_opts.target_camera_axes および ufbx_load_opts.target_light_axes を使用します。


Coordinate Spaces in Files(ファイル内の座標系)

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

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

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

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

また、軽量ロード(ufbx_load_opts.ignore_all_content = true)を使ってシーンを一度読み込み、
ufbx_metadata.exporter を確認することで、エクスポータ(Blender / Maya 等)を特定し、
最適な変換方法を事前設定することも可能です。

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


サンプルコード

// シーンをメートル単位・右手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(ジオメトリ変換)

FBX では ジオメトリ変換(geometry transform) と呼ばれる特殊な変換をサポートしています。
これはノード直下のメッシュなどにのみ適用され、子ノードには継承されません。
多くのシーングラフではこの仕組みを直接サポートしていないため、ufbx は代替方法を提供します。

ジオメトリ変換の利用

ジオメトリ変換は ufbx_node.geometry_transform に格納されます。
また、補助的な行列:

  • ufbx_node.geometry_to_node
  • ufbx_node.geometry_to_world

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

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

非静的シーンでのジオメトリ変換は扱いが難しいため、
ufbx_load_opts.geometry_transform_handling によりロード時に削除することも可能です。

定数名

内容

UFBX_GEOMETRY_TRANSFORM_HANDLING_HELPER_NODES

補助ノードを挿入して対応(確実だがノード数が増える)

UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY

ジオメトリ変換を頂点データに焼き込み(きれいだが制約あり)

UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY_NO_FALLBACK

補助ノードを絶対に作らない(ただし変換誤差が発生する)


Inherit Modes(継承モード)

FBX では非標準的な変換継承も可能です。
これは ufbx_node.inherit_mode によって示されます。

モード

内容

UFBX_INHERIT_MODE_IGNORE_PARENT_SCALE

親のスケールを無視

UFBX_INHERIT_MODE_COMPONENTWISE_SCALE

スケールと回転を独立して合成

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

定数

内容

UFBX_INHERIT_MODE_HANDLING_PRESERVE

継承モードをそのまま保持(正確だが複雑)

UFBX_INHERIT_MODE_HANDLING_HELPER_NODES

補助ノードを追加して対応

UFBX_INHERIT_MODE_HANDLING_COMPENSATE

子ノードのスケールを逆補正(できない場合は補助ノード)

UFBX_INHERIT_MODE_HANDLING_IGNORE

非標準継承をすべて無視(単純だが不正確)


Pivots(ピボット)

FBX ノードでは、回転ピボットスケールピボット を個別に設定できます。
ufbx では、デフォルトでこれらの効果をノードの平行移動へ焼き込みます。

回転ピボットとスケールピボットが同一である場合、
ufbx_load_opts.pivot_handling = UFBX_PIVOT_HANDLING_ADJUST_TO_PIVOT
を設定することで、ピボットをジオメトリ変換へ変換することも可能です。
この場合は、ufbx_load_opts.geometry_transform_handling も併せて指定します(例:UFBX_GEOMETRY_TRANSFORM_HANDLING_MODIFY_GEOMETRY)。


その他のプロパティ

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

  • 可視性ufbx_node.visible でノードを非表示にできる
  • マテリアルの上書きufbx_node.materials[] でインスタンスごとに別マテリアルを適用できる

備考

FBX 仕様ではこれらを “Geometric” transforms(ジオメトリック変換) と呼びますが、
ufbx では明確化のため geometry transforms と呼んでいます。