その2 FBXファイルの読み込みと終了処理
前章でFBX SDKのインストールと面倒くさいプロジェクトの設定が終わりました。この章からはいよいよFBX
SDKの使い方に入ります。
FBX SDKはその名の通り「FBXファイル」を扱うSDKです。FBXファイルの中にはXファイルよりもはるかに豊富な3Dモデルの情報が格納されています(はるか過ぎて逆に困ります(^-^;)。またMayaやMax、LightWaveなどの3Dモデリングツールからエクスポート(出力)する事ができます。そして、このSDKを使うとFBXファイルからそれらの情報をプログラムに読み込む事ができるようになります。
しかし、Xファイルよりも豊富なデータということは、その取り扱いも大変であることは否めません。焦らず細切れに行こうと思います。
@ FBXファイルの読み込み
FBX SDKの中核をなすヘッダーファイルはfbxsdx.hです。メイン関数にこのヘッダーファイルをインクルードすると、SDKのコアクラスである「KFbxSdkManagerクラス」を使う事ができるようになります。このクラスはその名の通りこのSDK全体を管理して各種オブジェクトの生成も行います。これが無いと何も進めません。
KFbxSdkManagerオブジェクトを生成するにはKFbxSdkManager::Createメソッドを用います:
KFbxSdkManagerオブジェクトの生成 KFbxSdkManager *pSdkManager = KFbxSdkManager::Create();
前のバージョンとオブジェクトの作り方が変わりましたのでご注意ください。メソッドの戻り値はKFbxSdkManagerオブジェクトへのポインタです。
マネージャが作成できたら、続いて「インポータ(KFbxImporter)」を作成します。インポータというのはFBXファイルを読み込んでその情報をプログラムから読み込める形に管理してくれるクラスです。面倒なトークン解析をインポータがやってくれるので大助かりです。
インポータを生成するにはKFbxImporter::Createメソッドを使います:
インポータの作成 KFbxImporter *pImporter = KFbxImporter::Create( pSdkManager, "");
第1引数にはマネージャを指定します。第2引数はこのオブジェクトにつける適当な名前です。空でも大丈夫です。
続いてインポータにFBXのファイルフォーマットを伝えます。これはFBX自体にバージョンがあるためです。これにはお決まりの方法が用意されています:
FBXフォーマットのチェック const char *pFileName = "Sample.fbx";
int iFileFormat = -1;
if ( !KFbxIOPluginRegistryAccessor::Get()->DetectFileFormat( pFileName, iFileFormat ) )
{
// 失敗処理
}
pImporter->SetFileFormat(iFileFormat);
KFbxIOPluginRegistryAccessorというクラスが持つDetectFileFormatメソッドはFBXファイルをチェックしてそのフォーマットIDを第2引数に返してくれます。失敗するとfalseが返ります。成功した場合はiFileFormatにフォーマットIDが返りますのでそれをKFbxImporter::SetFileFormatメソッドに渡して登録します。
ファイルが正しいFBXファイルで、そのフォーマットもセットしたら、そのファイル名でインポータを初期化します:
FBXファイルの読み込み if ( pImporter->Initialize( pFileName ) )
{
// 失敗処理
}
これでインポータとファイルが関連付けられます。
さて、インポータ自体はファイルから情報を読み取る人です。その情報を受け取る別の人が用意されています。それがKFbxSceneクラスです。このオブジェクトの生成と情報の受け渡しは次のように行います:
シーンオブジェクトの生成 KFbxScene *pScene = KFbxScene::Create(pSdkManager,""); // 作成
pImporter->Import(*pScene); // シーン作成
pImporter->Destroy(); // インポータの削除
KFbxScene::Createメソッドでシーンオブジェクトを作成し、KFbxImporter::Importメソッドでインポータが持つ情報とシーンとを関連付けます。関連付けた段階でインポータの役目が終わりますので、Destroyメソッドを呼び出して削除してしまいます。
これで、FBXファイルから情報を読み込む事ができました。すべての情報をKFbxSceneが持つメソッドを通して取得できます。次章からはこのシーンクラスに登録された情報をプログラム側に還元する方法についてじっくり検討していきますが、この章は大まかな筋道を示したいので確保したオブジェクトの解放について説明して終りにしたいと思います。
A オブジェクトの解放
確保したオブジェクトは使い終わったら解放する必要があります。この章で確保したのはKFbxScene、KFbxImporterそしてKFbxSdkManagerです。
KFbxSdkManager::Destroyメソッドを呼ぶとシーンを始めとする各種関連オブジェクトも自動的に削除されます。2006.11.1バージョンではメモリリークが残る事が既知の問題として残っていましたが(Autodesk FBX Forum)、本バージョンで綺麗に無くなりました。ようやく使えるSDKになりました〜(^-^)。
今回確保したオブジェクトを次のように解放します:
オブジェクトの解放 gSdkManager->Destroy();
B 日本語パスについて
FBXは日本語パスの扱いを苦手にしているようです。当初私も「日本語パスは扱えなさそう」と紹介していたのですが、koi様より「UTF8に変換すると認識してくれる」との情報を頂きました。実際試してみますと、なるほどうまくいきます!
具体的な方法です。FBX SDKにはANSI_to_UTF8マクロが用意されています。これはその名の通りANSIをUTF8に変換してくれるマクロです。これを用いると日本語パスでも認識してくれます。ただ、FBXファイルを相対パスで指定した場合、暗黙の日本語フォルダが絶対パス内に含まれているとうまくいきません。よって、ファイル名はすべて絶対パスに変換して扱うようにします。変換関数を作ってみました:
日本語パスに対応するUTF8フォーマットの絶対ファイルパスを取得する関数 void getUTF8AbsFilePath( const char* filePath, char outAbsFilePath[ 512 ] ) {
char fullPath[ 512 ];
_fullpath( fullPath, filePath, 512 );
ANSI_to_UTF8( fullPath, outAbsFilePath );
}
第1引数に相対パス(絶対パスもOK)を入れると、第2引数にUTF8に変換された絶対パスが返ります。このファイルパスを読み込みに使うとうまくいきます。
(2009. 11. 19追記)
ANSIをUTF8に変換するマクロが変更されていました。対応版は以下の通りです:
日本語パスに対応するUTF8フォーマットの絶対ファイルパスを取得する関数 void getUTF8AbsFilePath( const char* filePath, char outAbsFilePath[ 512 ] ) {
char fullPath[ 512 ];
_fullpath( fullPath, filePath, 512 );
KFBX_ANSI_to_UTF8( fullPath, outAbsFilePath );
}
この章で出てきたKFbxSceneオブジェクトを通すと、読み込んだFBXファイルからプログラムで参照できる3Dモデルの情報を取得する事ができます。後はそこから色々な情報を抽出する作業となります。これがまたボリュームたっっぷりなので、少しずつ掘っていきましょう。
C 謝辞
日本語パスの扱いについてご教授下さいましたkoi様にお礼申し上げます。