2013/01/28

ブロック地形進捗 #2

最大頂点数をとるチャンクを空間全体に敷き詰める前提を立てていましたが、「それは流石にハードルが高すぎる」と考えるに至り、頂点数がそこまで膨大とならないようにノイズを調整し、その他実装を修正していました。

16^3 チャンクで可視範囲を 20 チャンク (20 * 16 = 320 ブロック) としたキャプチャが下図です。

他のオブジェクトの配置を考えると、16 チャンク程度で済ませる気がしないでもありません。

なお、地形の背面に存在する洞窟の状態をキャプチャしたものは下図となります。

視点から見えるチャンクの状態に依存しますが、概ね、描画の負荷が多大な状態です。原因の一つは、描画対象とするチャンクの探索にかかる負荷です。チャンクを含め、シーンに描画するオブジェクトは八分木を用いて管理していますが、満足できる結果ではないと感じています。

これから、地形だけではなく、木を表現するブロックをチャンクへ配置しようと思います。木の配置まで終えたら、節目として動画を上げてみようと思います・・・たぶん。まぁそろそろ、積んだまま放置している Borderlands 2 をやりたいな、と。

2013/01/17

ブロック地形実装進捗

「心が折れそうだ」

煮詰まってきたため、ブログを書いて気持ちを誤魔化すことにしました。納得できるパフォーマンスを出せていないので、まだ動画公開はしませんが、下図が現時点のスクリーン ショットです。

 

僕の GitHub ページでコードは公開されていますが、動画公開まではタグを貼りません。そもそも、自分の環境でもメモリ不足によりアプリケーションが落ちる状態です。

今は、チャンク サイズ 16x16x16 で作成しています。チャンクは、上下左右に int とディスク スペースが許す限り無限に配置できる設計です。
チャンク
立方体ブロックを一塊としてメッシュとする単位。Minecraft では 16x256x16 や 16x128x16 なども用いる模様。
追記
今はチャンク サイズ 32x32x32 としています(チャンクのメッシュは 16x16x16 へ分割した状態)。チャンクの粒度を細かくするとチャンク総数が増えることから、チャンク探索処理に大きな負荷がかかるため、大きなサイズとしました。メッシュはインデックス バッファの制約から 16x16x16 (ushort で収まる範囲) が妥当かと思います。Minecraft 形式の場合ならば、高さ固定から二次元でのチャンク探索となり、比較すると遥かに高速かと思います。
地形は、ノイズを用いて自動生成しています。過去の一般的な地形生成ではノイズをハイトマップ生成に利用しましたが、今回はハイトマップを更に密度へ変換して利用しています。
密度を用いる利点は、密度生成を工夫することで、内部に洞窟を自動生成させたり、ハングしている崖などの、ハイトマップのみでは表現できない地形データを表現できる事。Minecraft でも密度を利用しているとの話。スクリーン ショット上で見える地形の内部には洞窟が存在。
で、満足できていない点ですが、チャンクをあまり多くロードするとメモリ不足に陥る所です (頂点バッファを確保できなくなる)。特に、洞窟を含むチャンクでは頂点数が一気に跳ね上がり、それに応じてロードできるチャンク数が減ります。

今は、可視範囲で 10 チャンク距離 (10 * 16 = 160 ブロック距離)、予備範囲で 12 チャンク距離 (12 * 16 = 192 ブロック距離) をロードしています。やはり、より遠方まで地形を表示したいわけで、せめて可視範囲で 12 チャンク距離程度はロードしたい所です。
Minecraft では 200 ブロック距離までも描画可能との話 (これを知ると、まだまだやれる事があると考えざるを得ません)。
理屈としては、恐らく、チャンク内で交互にブロックが配置 (立方体の角のみ隣接する配置) される構成が、チャンク頂点数を最大とする構成であろうと思います。そこで、この最大頂点数のチャンクのみをロードする前提で考えている所です。
最大頂点数のチャンクは、サイズ 16x16x16 において、頂点数 36864、インデックス数 36864。
チャンクの外部から不可視となる閉塞空間を検出し、閉塞空間に隣接する面を刈り取るなどしてみましたが、最大頂点構成では閉塞空間がなく、あえなく敗れ去った所です。とは言え、閉塞空間を含むチャンクでは大幅に頂点を削減できています。

そこで、今は、カメラとチャンクの位置関係から背面を除去しようとしている所です。チャンクのメッシュは実行中に非同期に更新しているため、カメラとチャンクの位置関係が変化した場合にメッシュ再構築を要求し、背面を刈り取るだけですが、現実装では即座にメッシュ再構築が完了するわけではないため、どうアプローチしようかと悩んでいる所です。

libgdx いじり

Google が提供している Java 版の Tango Examples は Rajawali をベースにしているため、自分が仕事で開発する Tango アプリも Rajawali ベースとしていましたが、最近は libGDX への移行を進めています。一応、要点については移行が...