DAEクラスの動作
2008年 11 月 27日 木曜日
冬になるとどんどん冬眠モードになるヤマダです。
Papervision3D で Collada ファイルをロードする時には DAE クラスを使うんですが、これの挙動がイマイチよく分からないので調べてみた。
//インスタンス化。 //false は初期化が終わったあとにアニメを再生するかどうかのフラグ var dae:DAE = new DAE(false); //Colladaファイルを読み込み開始 dae.load(asset);
この時、asset に String で URL を渡した場合は Colladaファイルのロードを行い、既にロード済みのCollada を XML として渡した場合は、直接Colladaのパースを行うっぽい。
org.papervision3d.objects.parsers.DAE クラスの 314行目あたりで、
if(asset is XML)
{
this.COLLADA = asset as XML;
this.parser.loadDocument(asset);
}
else if(asset is ByteArray)
{
this.COLLADA = new XML(ByteArray(asset));
this.parser.loadDocument(asset);
}
else if(asset is String)
{
this.filename = String(asset);
this.parser.read(this.filename);
}
else
{
throw new Error("load : unknown asset type!");
}
みたいな感じで型の判別をやってる。
で、何らかのソフトを使ってColladaを書き出すと、だいたいはDAEファイルに対するテクスチャのパスがいい加減で、そのままロードできない事が多々あるんですね。
修正するのは簡単で、ColladaのXMLファイルを開くと、「library_images」 っていうノードがあるので、手書きで直す場合にはココを相対パスに書き換えてやればいい。
で、ですよ。
これをAIRとかのアプリでリクエスタを立ち上げて画像を選択し、一箇所のフォルダにコピーする的なプログラムを書こうと思ったら、このDAEクラスの変な癖に衝突。
脳内の妄想では、
Colladaを作業用フォルダにコピー
↓
XMLとしてロード
↓
ノードを解析して画像のリストを取得
↓
画像のノード毎にテクスチャのファイルを選択して作業フォルダにコピー
↓
XMLのノードを動く内容に上書き
↓
DAE.load(asset) で上書き済みのXMLを渡して表示
みたいな事を考えてた訳です。
しかーし…
DAEクラスさん、どうも直接XMLを渡した時にはパスの解決をやってくれないらしいんです。
しかも、
public var baseUrl:String; public var texturePath:String;
とか、解決用にあるっぽいパラメタを buildFileInfo() っていう関数が上書きしとるやん。filename = “./meshes/rawdata_dae” って何だよ。
再生するSWFから相対的に見た meshes フォルダに入れとけよっていう事なんだろうけどもだ。作業フォルダから読みたいちゅう話やで。
これが原因で、内部的に buildImagePath() 関数で baseURLに対して勝手なパスを生成してしまうので、画像のロード先がどうやっても制御できなくなってしまうと。
要するにこういうこと。
- URLを指定した場合(うまくいくケース)
DAE をロード → URLに対してテクスチャの絶対パスを生成してテクスチャをロード - XMLを指定した場合(なんだかコケるケース)
勝手に “./meshes/rawdata_dae” を基準にしたパスを生成
仕方が無いので、DAEクラス を extend して、”./meshes/rawdata_dae” の部分を変数として扱えるようにしてみました。
//ここをインスタンスの外からコントロールできるようにした
public var fileNameDefault:String = "./meshes/rawdata_dae";
/**
*
* @param asset
* @return
*/
override protected function buildFileInfo( asset:* ):void
{
this.filename = asset is String ? String(asset) : fileNameDefault;
// make sure we've got forward slashes!
this.filename = this.filename.split("\\").join("/");
if( this.filename.indexOf("/") != -1 )
{
// dae is located in a sub-directory of the swf.
var parts:Array = this.filename.split("/");
this.fileTitle = String( parts.pop() );
this.baseUrl = parts.join("/");
}
else
{
// dae is located in root directory of swf.
this.fileTitle = this.filename;
this.baseUrl = "";
}
}
PV3D以外のライブラリではどんな感じなんだろ?
時間ができたら試してみよう。