2012年3月11日日曜日

COLLADA (7)プリミティブ

再びジオメトリ周辺。

<p>(インデクス配列)には直前の<input>要素の数だけインデクスが入っている。

<input semantic="VERTEX" source="#vertices" offset="0"/>
<input semantic="NORMAL" source="#normals" offset="1"/>
<input semantic="TEXCOORD" source="#texcoords" offset="2" set="0"/>
<p>0 0 1 1 2 2</p>

位置、法線、座標、位置、法線、座標

なんて具合にインデクスが混在している。
上記は非常に単純な例だが、仕様書には様々なイカレタ例が示されている。
また実際に利用される実数は<p>に依存する。

とあるサンプルファイルの実数配列部は
位置:4122  / 3 = 1374
法線:4122  / 3 = 1374
座標:12904 / 2 = 6452

<p>に基づき展開すると
位置:6318 / 3 = 2106
法線:6318 / 3 = 2106
座標:4212 / 2 = 2106

しかしこれではインデクス化の旨みが0。
OpenGLなら要素毎にプッシュできるので百歩譲って問題ないが・・・。
頂点配列を利用するなら再インデクス化が必要。
この部分だけ見ると強烈にダルいフォーマットだなぁ。
[追記]
再インデクス化と頂点入力の圧縮が終わったので採用した作戦の概要。
手抜きだから時間が掛かる。

(1) <p>に基づき各種頂点入力を展開
この時点で独立三角形となる
つまりインデクスは不要
(2) インデスクを初期化
インデクス数はCOLLADAの<p>の数のままで問題ない
独立三角形となっているのでインデクスは0, 1, 2, 3....
と連番の単純なものとなる
(3) 重複を調べるための領域を確保
量はインデクス数と同様
(4) 重複を調べながら再インデクス化を行う
重複自体は各種頂点入力配列の先頭からチェック対象の1つ前まで検査。
重複していれば重複した部分のインデクスで上書き
重複していなければ0から始まるカウンタの値でインデクスを上書き
その後、カウンタは加算
繰り返し
(5) 各種頂点入力の圧縮
重複マップを参照して重複部分を削除

std::vectorを利用すると操作中の不要なメモリ確保や削除などが発生しなくて楽。

とあるサンプル(<mesh>内の各プリミティブ分を圧縮格納している点に注意)
位置:4122  / 3 = 1374
法線:4122  / 3 = 1374
座標:12904 / 2 = 6452

<p>に基づき展開
位置:6318 / 3 = 2106
法線:6318 / 3 = 2106
座標:4212 / 2 = 2106

今回の作戦を適用
位置:1632 / 3 = 544
法線:1632 / 3 = 544
座標:1088 / 2 = 544

すべてがそうなるわけではないが、今回の例では74%の削減ができた。
DirectXなりOpenGL(一部描画機能を除く)でそのまま描画はできないので
遅かれ早かれやらねばならなかった。

これまで間接的に描画していたものを直接描画してみることにした。
上手くいっているご様子。

余談
バージョン管理ソフトはこれまでにVSSやCVS、SVNを利用していたんだけど
GCでrubyあたりを見ているときにGitHubが気になったので試験的に利用することにしてみた。
当方の場所は関連リンクから。
ColladaLoaderという名称のリポジトリが今弄ってるものだけど、何にも意識しないで書いている
ので内容はお粗末です。

0 件のコメント :

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。