DAEクラスの動作


冬になるとどんどん冬眠モードになるヤマダです。

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以外のライブラリではどんな感じなんだろ?
時間ができたら試してみよう。

コメントを残す