PV3D2.1: DisplayObject3D.worldの値が更新されるタイミング

2009年9月 6日
前回のエントリー
「DisplayObject3D.world」でモデルのワールド空間での
移動・回転・スケールの変換行列が取得できる

と書いたんですが、どうやらworldプロパティは
シーンがレンダリングされるタイミングで初めて値が更新されるみたいです。

てことは、モデルを回転してからworldプロパティにアクセスしても
レンダリング直前では回転を適用する前の情報しか取れない事になる・・・
逆にレンダリングしてからアクセスしてしまうと、
例えば常に回転しているモデル上をキャラが歩く場合、
モデル回転→レンダリング→ワールド座標を取得して交差判定→キャラを動かす
という処理の流れになってしまって
キャラクターの描画が遅れる事になってしまう。。
かといって正確なworldプロパティを取得する為だけに
2回レンダリングするのも無駄すぎる・・・

色々調べて、どーしてもいい方法が見つからなかったので
worldプロパティを使わずにワールド空間での変形情報(Matrix3D)を調べる事にしました。
実は前回のエントリーで書いたDisplayObject3D.worldプロパティ、
最初このプロパティの存在に気づかずに
モデルのローカル空間?の変形情報が入っている
DisplayObject3D.transformプロパティ
を使ってworld相当の情報を無理矢理調べてました。

↓その時に作ったスクリプト
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.objects.DisplayObject3D;
/**
 * オブジェクトのワールド空間での変形情報を取得
 * @param	obj	
 * @return
 */
public static function getWorldTransform(obj:DisplayObject3D):Matrix3D {
	obj.updateTransform();
	var res:Matrix3D = new Matrix3D();
	res.copy(obj.transform);
	var parent3D:DisplayObject3D = obj.parent as DisplayObject3D;
	if (parent3D != null) res.calculateMultiply(getWorldTransform(parent3D), res);
	return res;
}
引数にモデルを渡すと変形情報がMatrix3Dクラスで返ってきます。
transformプロパティはあくまで自分の親からみた相対的な変形情報なので、
ワールド空間での最終的な変形情報を得るには
親のDisplayObject3Dを辿っていって、全ての親のtransformを混ぜる必要があります。
またtransformの値はDisplayObject3D.updateTransform()を実行しないと更新されません。
yaw()、pitch()、roll()、localRotation~()、translate()、move~()を使ったり、レンダリングしたりすると
自動でupdateTransform()が呼び出されるので必要ないみたいなんですが、
それ以外の方法で動かす可能性もあるので一応呼び出すようにしてます。
再帰処理があるのがちょっと嫌だけど、他に方法が思いつかない・・・
とりあえず頂点座標をワールド座標に変換する処理とかで
worldを使わずにこの関数で調べたMatrix3Dを使えば大丈夫かなあ。

トラックバック(0)

トラックバックURL: http://www.morocoshi.net/mt/mt-tb.cgi/6

コメントする