チュートリアル / プラグインを作ってみよう!ゲーム開発のためのツール製作講座
第4回:Softimage編 ノード情報の取得

  • ゲーム
  • コラム
  • スクリプト・API
  • チュートリアル
  • 上級者
  • 中級者
前回はPython版プラグインの説明で全部使ってしまいました。今回からようやくエクスポーター本編の説明に入れます。

まずこれからC++APIで作っていくdllプラグインの全体構成について説明します。dllプラグインはCOLLADAのファイルフォーマットを扱うライブラリと、エクスポーター本体の2つから構成されます。こちらの図はエクスポート時の処理の流れを説明したものです。最初にSoftimageSDKを使ってシーンの情報を取得します。その情報をCOLLADAライブラリに設定して、COLLADAフォーマットでファイルを出力します。



ここで大事なのはDCCツールから情報を取得する部分と、ファイルフォーマットを扱う部分を分離しておくことです。このようにモジュールを分割しておくとソースコードがシンプルになるので後々のメンテナンスが楽になります。また他のDCCツール用のエクスポーターを作る時に、ファイルフォーマットの部分を再利用することができます。実際に私はSoftimage版とMaya版の両方のエクスポーターをこの方法で作成しています。



こちらのコラムはSoftimageSDKの説明がメインなので、COLLADAフォーマット自体の説明は省略しています。COLLADAの仕様は公式サイトか書籍「Collada: Sailing the Gulf of 3d Digital Content Creation」を参考にしてください。今回作成するエクスポーターでは私のほうで独自に作成したCOLLADAのライブラリを使用しています。本来であればCOLLADAの公式サイトで公開されているCOLLADA DOMを使用したいところですが、こちらは非常に大きく扱いにくいのです。

さて実際にdllのエクスポーターコマンドを作成していきましょう。今回のコラムではノード情報の取得と出力を行います。前回作成したPythonのメニューから、今回作成するエクスポーターコマンドを呼び出し、設定したオプションに従って出力を行います。



最初にこちらのファイルをダウンロードしてください。今回のコラムで作成するプラグインのソースコードが一式入っています。今回はこちらのサンプルコードの動作を説明する形で進めていきたいと思います。サンプルコードのライセンスに関してはzipファイルに含まれている「使用許諾規約.txt」を参照してください。

[AJ_SISDK_201110.zip]

こちらをビルドするためにはSoftimageの環境変数の設定が必要です。第2回で説明した方法を使ってVisualStudioのソリューションファイルを開くようにすると便利です。SoftimageをインストールしているフォルダのApplication/binのsetenv.batを同じフォルダにコピーして、AJ09_setenv.batという名前にします。そして最後に以下の行を追加します。

"(VisualStudioをインストールしているフォルダ)\Common7\IDE\devenv.exe"
"(今回のサンプルを展開したフォルダ)\exporter\project\SIColladaExporter\SIColladaExporter.sln"

今回のサンプルをDドライブに置いて、VisualStudio2008をデフォルトのフォルダにインストールしている場合は以下のようになります。

"C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe"
"D:\AJ_SISDK_201109\exporter\project\SIColladaExporter\SIColladaExporter.sln"

設定が終わったらビルドできるかどうか確認してみてください。こちらのプロジェクトファイルは「ビルド後のイベント」でプラグインをSoftimageのプラグインフォルダにコピーするようになっています。

今回のサンプルはSoftimage2011とVisualStudio2008で動作確認していますが、おそらくSoftimage2012とVisualStudio2010でも動くと思います。

まずはdllプラグインの引数の設定方法から説明します。C++APIで作成するプラグインは自分自身のコマンドの引数を設定する必要があります。こちらの設定はプラグインの初期化関数で行います。今回作成するdllプラグインは"SIColladaExporter"という名前なので、初期化関数は"SIColladaExporter_Init()"になります(main.cppを参照)。

SIColladaExporter_Init( CRef& in_ctxt ) {
            Context ctxt( in_ctxt );
            Command cmd = ctxt.GetSource();
}

SIColladaExporter_Init()の引数はCRef型です。こちらは要素を参照するためのクラスなので、適切なクラスにキャストして使います。今回はContextクラスにキャストします。Contextクラスは引数の処理でしか使わないので詳しく知る必要はないでしょう。

Context::GetSource()関数からCommandクラスが取得できます。Commandクラスは名前の通りSoftimageのコマンドに相当するクラスで、コマンドの名前やカテゴリ、引数などの情報を持っています。次にCommand::GetArguments()関数を使って引数の配列を取得します。この配列は専用のArgumentArrayというクラスになっています。このクラスも使うのはここだけです。ArgumentArray::Add()関数を使って設定したい引数を追加します。

ArgumentArray args = cmd.GetArguments();
args.Add( L"OutputFilename" );
args.Add( L"ExportAll" );

ここまでで、このdllプラグイン側の引数の設定ができました。次にPythonスクリプトからdllプラグインが呼び出されたときの引数の値を取得する方法を説明します。先ほどの説明は「プラグインの引数の設定」で、これから行うのは「呼び出し時の引数取得」なので混乱しないように注意してください。

dllプラグインが呼び出された時の引数はContextクラスから取得します。Context::GetAttribute()関数に文字列"Arguments"を渡して呼び出し時の引数を取得します。このときの戻り値はCValueArrayクラスです。CValueクラスはSoftimageSDKにおけるVariant型で、引数やパラメータの値を扱うときに使います。引数には文字列やブール、整数などいろいろな型が使われるのでCValueクラスが使われているのでしょう。

// Contextから引数を取得
CValueArray args = ctxt.GetAttribute( L"Arguments" );

まずCValueArray::GetCount()を使って引数の個数をチェックします。プラグインの仕様によりますが、ここでは個数が違う場合にエラーになるようにしています。

// 引数の個数チェック
if( args.GetCount() != 7 ) {
            app.LogMessage( "err: arguments number is wrong.\n" );
            return CStatus::Fail;
}

個数が合っていれば、引数の値をキャストしながら取得します。

int index = 0;
// ファイル名(文字列)
CString filename( args[ index++ ] );
// ExportAllフラグ(Bool値)
const bool exportAll = ((bool)args[index++]) ? true : false;

ここまでで引数の処理が終わりました。このあたりはどのdllプラグインでも同じ処理になると思います。

ここからようやくSoftimageのシーン情報の取得に入っていきます。最初に説明したように今回はノードの情報を取得します。ここでノードと呼んでいるのはSoftimageのシーン上の各種オブジェクト(ポリゴンメッシュ、ヌル、ライト、カメラ)のことです。

ノード情報を取得していく上で便利なのが「SDK Explorer」です。SDK Explorerはメニューの表示>スクリプト>SDK Explorerから開きます。このツールを使うと現在選択しているノードやプロパティなどの属性、パラメータの値などを簡単に調べることができます。

最初に取得するのはノードの「選択状態」です。なぜ選択状態を取得する必要があるのでしょうか? 一般的なエクスポーターは「シーンの中身を全部出力する」と「現在選択されているものを出力する」という二つの出力方法が選べます。今回作成するエクスポーターではオプションの”ExportAll”のオン/オフでこの出力方法を指定します。このオプションがオフのとき、つまり選択されているノードだけを出力する場合に、現在の選択状態を取得する必要があるのです。

Softimageのシーン上で選択されているものを取得するときはApplicationクラスを使います。Applicationクラスは現在実行中のSoftimageのアプリケーション本体に相当します。このクラスは必要な時にインスタンスを作成して使用します。メンバ変数として格納しておく必要はありません。

Application app;

現在選択されているオブジェクトの一覧はApplication::GetSelection()関数で取得します。戻り値はCRefArrayというクラスです。CRefArrayクラスはCRefという参照用のクラスの配列です。

CRefArray selectionArray = app.GetSelection();

CRefクラスは今後もよく出てくるのでここで説明します。SoftimageSDKの多くの関数は結果をCRefクラスの形で返します。ユーザーは受け取ったCRefクラスのオブジェクトを適切な型へキャストして使用します。キャストできるかどうかはCRef::IsA()関数か、CBase::IsValid()関数を使います。

IsA()関数を使うと、CRefクラスから他のクラスへキャストできるかどうか調べることができます。

if( selection[ i ].IsA( siX3DObjectID ) ) {
            X3DObject x3DObject( selection[ i ] );
}

CBase::IsValid()関数はキャストした後でそのキャストが有効かどうか調べるときに使います。

X3DObject x3DObject( selection[ i ] );
            if( x3DObject.IsValid() ) {
                        /* x3DObjectへの処理 */
}

Softimageのプラグイン開発では、このように特定のクラスにキャストできるかどうかを調べながら情報を取得していきます。逆に言うと、キャストできるクラスを常に把握しておく必要があります。ここがSoftimageSDKの一番やっかいなところで、初心者が混乱してしまう最大のポイントではないでしょうか。どのクラスにキャストできるかわからないと、そこから先の情報がたどれなくなってしまうからです。

キャストできるクラスはSDK Explorerで確認することができます。ここではポリゴンメッシュのCylinderを選択しています。ClassNameがX3DObjectクラスになっているので、このCylinderを参照しているCRefクラスはX3DObjectクラスにキャストできることがわかります。



少し脇にそれたので、選択状態を取得するところに戻りましょう。Application::GetSelection()関数の結果を調べてみます。このコードはサンプルとは違いますが、CRefクラスからSIObjectクラスへ変換して、変換が有効ならば名前を取得して表示しています。

Application app;
CRefArray selection = app.GetSelection();
for( unsigned i=0; i<selection.GetCount(); i++ ) {
            SIObject siObject( selection[ i ] );
            if( siObject.IsValid() ) {
                        app.LogMessage( siObject.GetName() );
            }
}

SIObjectクラスはSoftimageSDKのオブジェクトモデルのクラスの一種で、ノードの名前を持っています。SIObject::GetName()関数から名前を取得できます。キャスト後のIsValid()関数によるチェックが不必要な場合は省いても構いません。以後の説明では簡略化のために必要がない限り省きます。

ここまでで選択されているノードとその名前が取得できるようになりました。今回使用するCOLLADAの仕様ではノードにユニーク(一意)な名前を付ける必要があるのですが、SIObject::GetName()関数で取得した名前はそのまま使えるでしょうか?

通常Softimageのノードの名前は重複しません。階層構造が違っていても同じ名前を付けることができません。つまりノードの名前はすべてユニークになります。これならばGetName()で取得した名前がそのまま使えそうですね。



ところがSoftimageにはモデルと呼ばれる特殊なノードがあり、この下のノードは名前の重複が許されます。



この画像の場合"cube"という名前はシーン上でユニークではありません。以上のことからSoftimageのノードの名前は「重複する」可能性があります。GetName()で取得した名前は、そのままではCOLLADAのノードの名前に使えないということです。

Softimageのこの仕様は不便な気もしますが、ちょっと考えてみると妥当なことがわかります。たとえば人間のキャラクターモデルを2体出した場合、ノード名に重複が許されない場合、2体目のノード名がすべて変わってしまいます。これは明らかに不便ですよね。

このような状況でノードにユニークな名前を付ける場合、2つの方法が考えられます。連番を付ける方法と、親から子供までの名前を連結して使う方法です。前者は番号が付くだけなので名前が短く、ランタイムに持って行くときにメモリが節約できます。しかし番号で管理するので、デバッグするときにやや不便です。後者は階層が深いと名前が非常に長くなってしまうのですが、名前に階層の情報が入っているので、デバッグをするときに助かります。どちらもメリット・デメリットがあるのですが、今回は後者の方法を使っています。これでノードのユニークな名前が手に入りました。COLLADAのノードの名前にはこちらを使うことにしましょう。

次はノードの種類を調べてみます。Softimage上のシーンにはライト、カメラ、ポリゴンメッシュなどの様々な種類のノードがあります。ノードの種類はSIObject::GetType()かGetClassID()で調べます。今回の実装ではデバッグしやすさを優先してGetType()を使っています。

// カメラ?
CString type = siObject.GetType();
if( type == L"camera" || type == L"CameraRoot" || type == L"CameraInterest" ) {
            /* カメラを出力 */
}

ここで取得する「ノードの種類」は「SoftimageSDKのオブジェクトモデル(クラス)」とはまったく別の概念です。少しややこしいので混同しないようにしてください。たとえばカメラもライトもSIObjectの派生クラスですが、SIObject::GetType()の値は異なります。GetType()で取得できる値はSDK Explorerから調べることができます。


ノードの種類の次は「表示/非表示」の状態を取得してみましょう。こちらの情報はなぜ取得する必要があるのでしょうか? ゲーム開発においてアーティストがデータを作る場合、エクスポートするデータ以外にも作業用のデータを沢山作成します。作業用のデータをシーンに残したままエクスポートするためには、何らかの方法で「エクスポートするデータ」と「エクスポートしないデータ」を区別する必要があります。

方法はいくつか考えられますが、今回は画面に表示されているものはエクスポートして、非表示のものはエクスポートしない、という仕様にしました。この仕様にしておけば出力結果が見た目通りになるのでわかりやすくミスも減ります。

Softimage上で表示/非表示の切り替えを行うには「ハイド」か「レイヤー」を使います。まずハイドについて説明します。Softimage上でノードを選んでHキーを押すと、そのノードが非表示(ハイド状態)になります。Explorer上でHマークが付いているノードは非表示になっています。Hキーをもう一度押すと表示状態に戻ります。



このハイドの状態をプログラム上で取得してみましょう。ハイドの状態は"visibility"プロパティの"viewvis"パラメータに格納されています。Explorer上で探してみると、下の図の部分に入っていることがわかります。



ここで出てきた「パラメータ」というのは名前を持った一つの変数です。値はVariant型なのでパラメータによっていろいろな型の値が入っています。

「プロパティ」は「パラメータ」を複数格納するための入れ物と思っておけばよいでしょう。SoftimageのGUI上では"View Visibility"となっていますが、SDKからアクセスする場合は"viewvis"という名前になります。このように表示されている名前とSDKで使用する名前が違うことがあるので注意してください。これらの名前の対応関係はSDK ExplorerのParameterの項目で調べることができます。SDKで使用するのは"ScriptName"のほうです。

オブジェクトのプロパティ一覧はSceneItem::GetProperties()関数から取得できます。プロパティ一覧から"Visibility"プロパティを取得する場合はCRefArray::GetItem()を使います。引数に取得したいプロパティ名を渡すと、該当するプロパティを返します。

CRefArray props = sceneItem.GetProperties();
Property prop = props.GetItem( L"visibility" );

プロパティが取得できたらParameter::GetParameterValue()関数で"viewvis"パラメータの値を取得します。

bool v = prop.GetParameterValue( L"viewvis" );

上のコードではプロパティの中のパラメータの値を直接取得しましたが、一度パラメータを取り出してからその値を取得することもできます。

Parameter param = prop.GetParameter( L"viewvis" );
bool v = param.GetValue();

これでハイドによる表示・非表示の状態を取得することができました。次にレイヤーの表示状態を取得しますが、その前にSoftimageのレイヤーについて説明します。


SoftimageのレイヤーはPhotoshopなどのレイヤーと同じようなもので、レイヤー単位で表示/非表示を切り替えることができます。各ノードは任意のレイヤーに登録することができ、レイヤーの表示/非表示の切り替えによって、登録しているノードの表示状態を一括で変更できます。



一般的なワークフローでは、アーティストがエクスポート用のレイヤーを作っておき、出力するノードをそのレイヤーに登録しておきます。エクスポートするときはエクスポート用のレイヤーだけ表示してから出力します。このようにエクスポート用のレイヤーを作っておくと、どのノードを出力するのかはっきりするので、アーティストの間でデータの引き継ぎを行うときに非常に楽です。エクスポートするたびにノードを毎回選んでいると必ず間違えるので、レイヤーを使って管理したほうがよいでしょう。

それではレイヤーの表示状態を取得してみましょう。レイヤーの表示状態はレイヤーの"View Visibility"パラメータから取得できます。レイヤーはアプリケーションの下に入っています。Explorer上では以下の場所に入っていることがわかります。



ここでは「ノードの属しているレイヤー」の「表示・非表示の状態」を取得したいので、まずノードが属しているレイヤーを取得します。ノードが属しているレイヤーはProjectItem::GetOwners()関数から取得します。GetOwners()関数からは複数のオブジェクトが返ってくるので、ClassIDがsiLayerIDのものを選びます。レイヤーはLayerクラスなのでキャストして、それから"viewvis"パラメータの値を取得します。この辺はハイドのところと同じです。

CRefArray owners = projectItem.GetOwners();
for( int i=0; i<owners.GetCount(); i++ ) {
            if( owners[ i ].IsA( siLayerID ) ) {
                        Layer layer( owners[ i ] );
                        bool v = layer.GetParameterValue( "viewvis" );
                        …
            }
}

以上でハイドとレイヤーによる「ノード単位」の表示・非表示の状態が取得できました。実は今回のサンプルコードでは「親が非表示なら子供も非表示として扱う」という実装になっています。これは親子関係の真ん中のノードだけ非表示になっている場合に対応するためです。真ん中のノードだけ非表示にして出力する場合、そのノードの子供の座標に「非表示の親の座標」も含める必要があります(こうしないと子供のグローバル座標が変わってしまいます)。これは大変面倒なので、親が非表示ならそれ以降の子供もすべて非表示として扱っています。


今度はノードの親ノードを取得してみましょう。SIObject::GetParent()という関数でノードの親のCRefクラスを取得することができます。オブジェクトが親を持たない場合、GetParent()関数は自分自身を返します。シーンの一番上のノードは親がいないので自分自身が返ってきます。

SIObject siObjectParent( siObject.GetParent() );
// 自分自身が返ってきた場合は親がいない
if( siObjectParent == siObject ) {
            app.LogMessage( L"No Parent." );
}
// それ以外のケースでは親が返ってくる
else {
            app.LogMessage( siObjectParent.GetName() );
}

親の次はノードの座標情報を取得します。SIObjectクラスは名前しか持っていないので、SIObjectの派生先のX3DObjectクラスを使います。X3DObjectクラスはシーン中の3Dオブジェクトを表現するクラスで、3D座標の情報を持っています。このX3DObjectクラスから座標情報の格納されたCTransformationクラスを取得します。



X3DObject::GetKinematics()関数からKinematicsクラスが取得できます。このKinematicsクラスから位置情報へアクセスできるのですが、KinematicsクラスはGetGlobal()、GetLocal()という二つの関数を持っています。これらの関数は名前の通り、グローバル(ワールド)座標、ローカル座標の位置情報を返します。今回はローカルの座標情報を取得したいのでKinematics::GetLocal()関数を使います。


Kinematics::GetLocal()関数はKinematicStateクラスを返します。KinematicStateクラスはX3DObjectクラスの現在のポーズ情報を格納しています。KinematicState::GetTransform()関数からMATH::CTransformationクラスが取得できます。これでようやく座標情報の格納されたCTransformationクラスが取得できました。

X3DObject x3DObject( selection[ i ] );
MATH::CTransformation transform;
Kinematics kinematics = x3DObject.GetKinematics();
KinematicState kinematicState = kinematics.GetLocal();
transform = kinematicState.GetTransform();

上のコードでは一つずつ取得していますが、X3DObjectから一気にCTransformationクラスを取得することもできます。

X3DObject x3DObject( selection[ i ] );
MATH::CTransformation transform;
transform = x3DObject.GetKinematics().GetLocal().GetTransform();

CTransformationクラスが取得できたので、その中の座標情報を取得します。CTransformationクラスには取得用の関数が沢山あるので、詳細はCTransformationクラスのマニュアルを参照してください。こちらのコードではスケール、回転、移動、クォータニオンの値を取得しています。

MATH::CVector3 scale = transform.GetScaling();
MATH::CVector3 rotation = transformation.GetRotationXYZAngles();
MATH::CVector3 translation = transformation.GetTranslation();
MATH::CQuaternion quaternion = transformation.GetRotationQuaternion();

rotationの値はラジアンです。度に変換したい場合はMATH::RadiansToDegrees()関数を使います。

const float rx = static_cast< float >( MATH::RadiansToDegrees( rotation.GetX() ) );
const float ry = static_cast< float >( MATH::RadiansToDegrees( rotation.GetY() ) );
const float rz = static_cast< float >( MATH::RadiansToDegrees( rotation.GetZ() ) );

これで座標の情報をすべて取得できたのですが、回転に関しては少し注意が必要です。SoftimageなどのDCCツールではXYZ回転の適用順をノード単位で変更できるからです。



Softimage上では上の図のように回転を適用する順番を自由に選ぶことができます。これを描画エンジン側で対応することも可能ですが、どのように扱うかは事前にアーティストと相談して決めておきましょう。今回はデフォルト設定のXYZ順で固定しています。ちなみにSoftimage上での回転の適応順はCTransformation::GetRotationOrder()関数で取得できます。



座標情報に関してはもう一点注意したい点があります。Softimageには階層(Softimage)スケーリングという特殊なモードがあります。このモードを使うとマトリックスの計算が通常とは変わってしまいます。通常、マトリックスの変換は親から子へと演算の結果が伝わっていきますが、この階層(Softimage)スケーリングが有効な場合はスケール成分だけ別扱いで計算します。この違いを説明したのが以下の図です。



こちらの図ではコーンをキューブの子供にして、キューブにScaleY=2, コーンにRotateZ=45を適用しています。通常のマトリックス演算では、子供を回転してから親のスケールを適用するので、子供のコーンはゆがんでいます(右側の図形)。階層(Softimage)スケーリングが有効な場合はスケールだけ別に計算するので、子供のコーンがゆがんでいません。これはこれで便利そうな機能ですが、この機能を実現する場合は描画エンジン側の対応も必要になります。対応するかどうかはアーティストと相談して決めてください。MayaやMAXなど他のDCCツールには無い機能なので、プロジェクトで複数のツールが混在する場合は使わないほうがよいでしょう。



ポリゴンメッシュの次はカメラの情報を取得してみましょう。Softimageのカメラは「カメラルート」「カメラの注視点」「カメラ本体」から構成されます。Explorerで見るとこのような構造になっています。



SDK Explorerで調べると、「カメラルート」はCameraRigクラス、「カメラの注視点」はNullクラス、「カメラ本体」はCameraクラスになっていることがわかります。一方、タイプは"CameraRoot"、"CameraInterest"、"Camera"になっています。カメラルートとカメラの注視点はNullの一種と考えればよいので、通常のノードと同じ扱いにします。カメラの各種パラメータはカメラ自体から取得できます。CameraクラスはProjectItemの派生クラスなので、ProjectItem::GetParameterValue()関数を使ってパラメータの値を取得します。実際にカメラのパラメータを取得するところはサンプルコードを参照してください。



カメラの次はライトの情報を取得しましょう。ライトの構造はライトの種類によって多少変わってきます。並行光源の場合はライト本体のみですが、スポットライトの場合はカメラのように「ライトのルート」と「ライト本体」、「ライトの注視点」から構成されます。



SDK Explorerで調べてみると、「ライトのルート」はLightRigクラス、「ライト本体」はLightクラス、「ライトの注視点」はNullクラスとなっています。タイプはそれぞれ"SpotRoot"、"light"、"SpotInterest"です。ここはカメラと同じですね。ルートと注視点はNullと同じ扱いにして、ライト本体からライトのパラメータを取得します。


ライトの種類はLightクラスの"Type"パラメータから取得できます。ここで取得するのは"Type"という名前のパラメータで、SIObject::GetType()関数で取得するタイプとは別物です。紛らわしいので間違えないようにしてください。代表的なライトの"Type"パラメータの値を以下にまとめました。他のライトの値はSDK Explorerで確認してください。

ポイントライト:0
並行光源:1
スポットライト:2

Softimageのライトには多数のパラメータがありますが、今回作成するエクスポーターではその中の"soft_light"のカラーを取得しています。他のパラメータを取得したい場合はSDK Explorerで詳細を確認してから取得してください。

今回の説明ではCRefクラス,CBaseクラス,SIObjectクラス,X3DObjectクラスと沢山のクラスが出てきました。SoftimageSDKのクラス階層は結構深いので、よく使うクラスとその構造を下の図にまとめてみました。



Softimageのオブジェクトモデルの一番基本となるのがCBaseクラスからX3DObjectクラスまでの一連のクラスです。この階層では各クラスがそれぞれの役割を持っています。一方、CRefクラスは各オブジェクトへの参照で実体はありません。SoftimageSDKには沢山のクラスがありますが、まずはこれらのクラスを覚えておきましょう。



長くなりましたが、これでノードの情報が一通り取得できました。サンプルコードをビルドしてエクスポートできることを確認してください。Softimage上でポリゴンメッシュやカメラ、ライトを適当に置いて親子構造を作り、メニューからSIColladaExporterを使ってエクスポートすると、Colladaのファイル(*.dae)が出力されます。daeファイルはテキストのXMLなので、テキストエディタで中身を確認することができます。

以下のColladaファイルはnullの下にcubeを作ってエクスポートした例です。

<library_visual_scenes>
            <visual_scene id="Scene_Root" name="Scene_Root">
                        <node id="null" name="null">
                                    <translate sid="translate">1 0 0</translate>
                                    <rotate sid="rotateX">1 0 0 0</rotate>
                                    <rotate sid="rotateY">0 1 0 0</rotate>
                                    <rotate sid="rotateZ">0 0 1 0</rotate>
                                    <scale sid="scale">1 1 1</scale>
                                    <node id="null/cube" name="cube">
                                                <translate sid="translate">2 0 0</translate>
                                                <rotate sid="rotateX">1 0 0 0</rotate>
                                                <rotate sid="rotateY">0 1 0 0</rotate>
                                                <rotate sid="rotateZ">0 0 1 0</rotate>
                                    <scale sid="scale">1 1 1</scale>
                                    </node>
                        </node>
            </visual_scene>
</library_visual_scenes>

今回でノード情報は一通り取得できました。スキニングやアニメーションに関係する部分は今後改めて説明する予定なので、今回のサンプルコードから除いてあります。次回はポリゴンメッシュのジオメトリ情報について説明する予定です。

製品購入に関するお問い合わせ
オートデスク メディア&エンターテインメント 製品のご購入に関してご連絡を希望される場合は、こちらからお問い合わせください。