その3 ノードを巡って巡って・・・
FBXの内部は「ノード」という樹状の塊になっています。ノードから必要な情報を読み取りプログラムに取り込んでいく。それがFBX
SDKの使い方(読み込み方)の基本となります。この章ではノードを辿る方法を見ていくことにしましょう。
@ KFbxNodeクラス
ノード情報はすべてKfbxNodeクラスに格納されています。ノードはエクスプローラのように階層上に連なっていて、すべてのサブノードは「ルートノード」の下に置かれます。ルートノードは前章で取得したKFbxSceneオブジェクトから取得できます:
ルートノードを取得 KFbxNode *pRootNode = pScene->GetRootNode();
あるノードにぶら下がっているサブノード(子ノード)の数はKFbxNode::GetChildCountメソッドで取得できます:
子ノードの数を取得 int childNodeNum = pRootNode->GetChildCount();
取得した子ノードの数から順にノードを辿る事ができます。あるノードにぶら下がっている子ノードを取得するにはKFbxNode::GetChildメソッドを用います:
子ノードを取得 for ( int i = 0; i < childNodeNum; i++ )
{
KFbxNode *pChild = pRootNode->GetChild(i); // 子ノードを取得
}
もちろん、子ノードの下には孫ノードもひ孫ノードも存在します。これをすべて辿るには必然的に再帰関数が必要になります。典型的なのは次のような関数です:
ノードを辿る再帰関数 void RecursiveNode( KFdxNode *pNode )
{
for ( int i = 0; i < childNodeNum; i++ )
{
KFbxNode *pChild = pRootNode->GetChild(i); // 子ノードを取得
RecursiveNode( pChild );
}
}
上の関数はただノードを巡って終わるわけで楽しくも何ともありません。ここから情報を取得する仕組みを整える必要があります。
A ノードタイプ
ノードに含まれる情報は実に様々です。それを判別するにはKFbxNode::GetNodeAttributeメソッドでノード属性クラス(KFbxNodeAttribute)のオブジェクトを取得し、そこからノードタイプを得ます:
ノードタイプを取得 KFbxNodeAttribute *pAttrib = pNode->GetNodeAttribute();
if ( pAttrib ) {
KFbxNodeAttribute::EAttributeType type = pAttrib->GetAttributeType();
}
KFbxNodeAttribute::EAttributeType列挙型にはノードタイプが列挙されています。取得可能なフラグは次の通りです:
分かる範囲です、すいません
ノードタイプ typedef enum
{
eUNIDENTIFIED, // 不定
eNULL, // NULL
eMARKER, // マーカー
eSKELETON, // スケルトン(ボーン)
eMESH, // メッシュ
eNURB, // NURBS
ePATCH, // パッチ
eCAMERA, // カメラ
eCAMERA_SWITCHER, // カメラスイッチャ
eLIGHT, // ライト
eOPTICAL_REFERENCE, // ?
eOPTICAL_MARKER, // ?
eCONSTRAINT, // 制約条件
eNURBS_CURVE, // NURBS曲線
eTRIM_NURBS_SURFACE, // NURBSトリム
eBOUNDARY, // 境界ボリューム配列
eNURBS_SURFACE // NURBS曲面
} EAttributeType;
非常に沢山の種類がありますが、すべて使う必要はありません。以後の章ではこのノードタイプの情報について詳細を追います。
再帰関数内ではこのノードタイプを判別して独自の取得部分を実装します:
ノードタイプで取得関数を区別(再帰関数内) KFbxNodeAttribute::EAttributeType type = pAttrib->GetAttributeType();
switch ( type )
{
case KFbxNodeAttribute::eUNIDENTIFIED:
case KFbxNodeAttribute::eNULL:
return;
case KFbxNodeAttribute::eMESH:
GetMesh( pAttrib ); // メッシュを作成
return;
case KFbxNodeAttribute::eCamera:
GetCamera( pAttrib ); // カメラを作成
}
実は、後の章で出てきますが、各取得関数にノードから派生したKFbxNodeAttributeへのポインタを渡すのがコツです。と言うのもこれが無いと各種情報を得る事ができないんです。
どういう事かというと、ノードの各属性を表す具体的なクラスのほとんどはKFbxNodeAttributeクラスから派生されているんです。その様子を表した下のクラス図をご覧下さい:
FKbxNodeAttributeクラスが大親分になっていて、その下に沢山の子クラスが並んでいます。先に取得したノードのノードタイプは上の子クラスに対応しています。つまりKFbxNodeAttribute::GetAttributeTypeメソッドでノードタイプを確定させたら、KFbxNodeAttributeをダウンキャストして各具象クラスにしてしまいます。これで、各子クラスが持つ具体的なメソッドを呼び出すことができ、上のクラス図で分類された情報を取得することができます。
次の章では、上のクラスの右上から2番目にあるKFbxMeshが持つ、3Dモデルにおいて最重要情報である「メッシュ情報」を取得してみましょう。