Astro ビルトインによる 3D 表現の模索(2)~Zソート<1>~
2008/05/30 22:08 - Astro
Zソートのアルゴリズムの話。
まずはダメ押しの再確認からですが、Zソートというくらいだから、表示オブジェクトのZ座標がソーティングのキーになっているということは申すまでもないこと。
AS2時代は実に牧歌的な時代で、ある意味、幸福な時代でもありました。Z座標をそのまま使ってZソートをおこなっていたんですから(まぁ私はあんな仕様の言語に戻りたいとは金輪際思いませんが、それはそれとして)。
表示オブジェクトのZ座標が正の整数になるように補正をかけ、swapDepths() の引数にぶち込んで深度を変えることで、表示オブジェクトの重なり順を変えていました。
正の整数にするために、ソーティングの段階で、全ての表示オブジェクトのZ座標値を1000倍したりとか、マイナスが発生していた場合は想定可能なZ座標の最小値を求め、その絶対値を加えるとかしてました。
ActionScript 3.0 になり、深度という概念は破棄され、代わってディスプレイリストという概念が導入されると、このアルゴリズムは使えなくなりました。
上記 AS2 によるアルゴリズムでは深度が連続している必要はありませんでしたが、ディスプレイリストに登録される表示オブジェクトのインデックスは連続である必要があるからです。
その結果導入したアルゴリズムは、表示オブジェクトとZ座標をペアにして配列で管理するというものでした(参照エントリー:新 3D クラス開発日記(10))。
コードとしては以下のようになります。
(1) var zsort_array:Array = new Array(); (2) for ( idx in objectArray ) { zsort_array.push( { face:objectArray[idx].face , depth:objectArray[idx].transCoordinate.z } ); } (3) zsort_array.sortOn( "depth", Array.NUMERIC | Array.DESCENDING ); (4) for ( idx in zsort_array ) { objectContainer.setChildIndex( zsort_array[idx].face , idx ); }
(1) まずZソート用の配列を生成。
(2) 次にその配列に表示オブジェクトとZ座標をペアにした Object を push していきます。 上記例では for in の対象となっている objectArray は 3Dオブジェクト を格納した配列で、その要素に一つづつアクセスし、 3D オブジェクトの表示オブジェクトを face、表示オブジェクトの現在のZ座標値を depth としました。
(3) は実際のソートの部分です。 Array のメソッド sortOn を使って、配列の要素にソーティングをかけています。 第1引数はソート対象、第2引数はソートの仕方を指定しています。depth を数値として降順でソートしろ、という命令になります。
(4) で表示オブジェクトの重なり順の変更がおこなわれています。 for in で配列を舐めて、配列の先頭から小さいインデックスで setChildIndex しています。(3)で降順にしているので、Z座標が大きいものほど、ディスプレイリストのインデックスが小さくなる、つまり重なりとしては下になるわけです。
これを踏まえて Astro ではどのようなZソートにするか、というのが次の課題。
続く。