|
好調なんだか不調なんだかわかんないけど、とにかくダラダラと新しい3Dシステムのコード作成は進んでいます。
まぁしかしこのへんていうのは、単に数字が変わったり動いたりするだけなので、実に退屈。計算があっているのかどうかは自分の手で計算せにゃならないし、自分の手で計算するもんだから余計怪しいし、なにより今日のプログラムと昨日のプログラムの差が数字一桁なんてことはザラで、変化すらなかったり、もしくはプログラムを高度にしてしまったために、テストプログラムを組むことすらオックウになったりと、イロイロと危険なダラダラ期間なのであります。
まぁプログラムっていうのは、こうしたダラダラした期間がかなりの時間を占めるので、これを我慢できないひとには勤まらないんだよなぁと先生風をふかしつつ、しかしやっぱり面倒だしウザいしやだよやっぱRM使うことにしようかなぁと負け犬風味な感想すら抱きつつある今日このごろ。
今回の3Dシステムは以前僕がつくったものに比べて革新的なところがいくつかあります。ひとつは、フレームとパケットがそれぞれ独立していること。これは以前「ディジーチェーン」の話題のときに触れました。
真に効率の良い計算と、効率の良い描画順序とは、必ずしも一致しないのだということに気づき、パケットとフレームをまったくの非同期に操るという、見方としては少々複雑なものを構築しているわけです。
しかしながら、毎度のことなんだけれど、こういうものを作っているといつも途中で「果たしてこの方向性で正しいのだろうか」「なんか見落としているものはないか」「果たしてあと数ヶ月で完成するのだろうか」「このペースで来年本なんて出せるの?」という切実かつ切迫した疑念が、尾崎豊の「シェリー」のごとく押し寄せてくるのです。
まぁしかし、普通に考えれば、一ヶ月もあればこの程度のシステムなんてお茶の子サイサイで完成できなければプロを名乗れないのでしょうが、既に作りはじめてから一ヶ月が経過してなお、画面に動くものが出てないこの状況。
反省点としては、まぁ連日ゲームに次ぐゲームで、プログラムの合間にゲームしてたというよりもゲームの合間にプログラムをしてたといってもいいような状況だったし、スキー行ったし、新歓で忙しかった(?)しで、ちょっと猛省を促されなくてはならない事態であることはすでに弁明の余地はありませんな。
さて、この苦難の道を歩む新3Dシステムの扱おうとしている大切なテーマのひとつに、「メッシュ描画の最適化」があります。
これについては、以前、相対ベクトルを使って高速化が云々という話をしたきり、尻切れトンボになっていました。
まぁ相対ベクトルを使って計算量を減らすのも当然、大切なことなのですが、実はもっと大切なことがあるのです。
それは、頂点の数をできる限り減らすことです。なにを馬鹿なことをとおっしゃるな。実はこれは大変根の深い問題でもあるのです。
さて、おそらくあらゆる3Dシステムにおいて、絶対に出てくるメッシュの代表的なものといえばやはり立方体でしょう。では立方体を描画する方法は?
これ、ほとんどの3Dシステムでは大差ないのです。
あなたなら即座にどんな方法を思い付きますか?
たとえばDirect3Dの場合、描画できるのは三角形だけです。Direct3Dには3つの三角形描画モードがあります。ひとつは三角形のリストを与える「TRIANGLE_LIST」、そして連続した三角形を与える「TRIANGLE_STRIP」、さらに中央の点を指定して、それを囲うように点をあたえる「TRIANGLE_FAN」です。
もっとも愚劣な策は、箱を構成する6つの面につき、それぞれ二枚の三角形を与えることとし、TRIANGLE_LISTで実装することでしょう。
この場合、Direct3Dに対してDrawPrimitive命令を1回発行し、三角形としては6×2で12枚、頂点数にして12×3で36頂点を発行しなくてはなりません。
もっとも、これはIndexedを使えば頂点は8頂点だけで済みますが、結局、頂点インデクスは36頂点ぶんを発行しなくてはならなくなります。ですからここでは頂点の数といった場合はIndexedの場合は頂点インデクスの数をも指すことにします。
さて、もう少しマトモに考えれば、ひとつの面は単なる四角形ですから、これは4頂点のTRIANGLE_STRIPで描画できます。こうすると、ひとつの面につき頂点4個、かける6枚ぶんですから、全部で24頂点を発行することになります。
ごく一般的な普通の3Dシステムでは、このような方法をとっているのではないでしょうか。
さて、問題はここからです。
プログラマなら誰でもそうですが、少しあたまの働く人ならば、箱を構成する6枚の面のうち、4枚の面は連続していることに気づきます。そこで、側面4枚をつなげてTRIANGLE_STRIPで一気に描画してしまうことができます。この場合、本来、4枚描画するのに必要な4×4=16頂点の発行を、10頂点に減らすことができます。すると上蓋と下蓋でさらに4×2を足して、合計18頂点になります
しかしここで少し頭をひねれば、実は立方体は二つのコの字型を組み合わせたものだということに気づきます。すると二つのTRIANGLE_STRIPで済むことになり、この場合はひとつのコの字につき、8頂点必要ですから、これを二つあわせて合計16頂点となります。
ここまでくると、最初の最も愚劣な方法は36頂点必要でしたから、発行する頂点数が半分以下になりました。
さて、ここで満足してはいけません。
理屈のうえでは、さらに別の考え方をすることもできます。
それはふたつのTRIANGLE_FANを使う方法です。
図のように、ある頂点から周りの頂点を回転させるように指定していき、ひとつの大きなFANを作ります。これをもうひとつの対角線上の頂点に関してもおこない、ふたつのTRIANGLE_FANを作れば8×2で合計16頂点となります。
TRIANGLE_FANを使う方法と、TRIANGLE_STRIPで二つのコの字を作る方法では、表面的な差はありませんが、考え方に大きな差があります。
それは、TRIANGLE_FANを使う方法は自動的に見つけやすいということです。なぜなら、このようなやりかたが適用できるのは、必ず包囲された頂点群に対してのみだからです。
ふたつのコの字型というのは、人間くらいの思考力がないと、なかなか見つけられないものではないでしょうか。一般性のある幾何的な性質というのが、コの字型の組み合わせというアイディアにはなかなか見出せません。自動的にコの字型を二つみつけるような高度なパターン認識能力を有したプログラムを作るのは至難の技ではないでしょうか。
さて、このように箱の描画法ひとつとっても、さまざまなやり方があります。
思うのですが、Direct3DRMといい、その外の3Dシステムといい、メッシュそのものの性質についてあまりにも無頓着に過ぎたのではないでしょうか。知っている限りでは、殆どすべての3Dシステムはここで示した第二の方法、つまり単純な四角形または三角形の集合としてのみ、メッシュを扱ってきたように思います。
実は、このような方法は僕が以前、派遣会社に所属しているときに請け負い仕事をしていた時に思い付いたものなのですが、メッシュのもつ性質を自発的に見いだし、TRIANGLE_LISTだけではなく、より効率的・効果的なTRIANGLE_STRIPやTRIANGLE_FANの集積体を自動的に生成するような、新しいタイプのメッシュ・コンパイラが、これから実に有効に作用していくのではないでしょうか。
というのは、繰り返すまでもなく、TRIANGLE_LISTとTRIANGLE_STRIPではその効率に雲泥の差があるからです。
さらに、このようなメッシュの性質を見出すアルゴリズムとして、遺伝的アルゴリズムがもしかしたら有効かもしれないとも思っています。
というのも、今の議論を見てわかるとおり、メッシュの分割の仕方というのは、実にさまざまなパターンが考えられるからなのです。つまり通り一遍の数学的解決だけではうまくいかない可能性が高いということで、乱数的要素を含んだ遺伝的アルゴリズムのほうが、最終的にはより優れた結果を出すことができるかもしれない、とこれは単なる感想なのですが。
僕は例によって遺伝的アルゴリズムの専門家ではないので、詳しい記述は避けますが、とにかくそんなことを考えながら、ダラダラとプログラミングを続けています(あくまで考えているだけですからいま組んでいるのはもっと退屈な部分です。誤解なきよう)。
|
|
|
|