ボクセル地形を表すためにどのデータ構造を使用する必要がありますか?


18

ボクセルに関するウィキペディアのページによると、「[...]ボクセルの位置は、他のボクセルとの相対的な位置(つまり、単一のボリュメトリックイメージを構成するデータ構造内の位置)に基づいて推測されます。」

そのようなデータ構造をどのように実装する必要がありますか?私は八分木について考えていましたが、聞いたことがない何か他のものがあるかどうか疑問に思っています。


1
これは、ボクセルデータに必要なデータに大きく依存するため、質問するのはやや難しい質問です。ボクセルがどれだけいっぱいか、どのように見えるかなどは、あなたが何をしているのかにかなり依存します。第二に、データ構造は、データのリアルタイム操作とその後の更新のために高速アクセスに適している必要があります。ボクセルごとにメモリ構造を低くし、データの高速アクセス/操作を高速に保つ方法は、主な技術的課題ですボクセルエンジンを使用する場合、かなり意図的に特定されます。答えではないので、コメント。
ジェームズ

回答:


14

最初。各ボクセルについて何を知っているかを書きましょう:

voxel = (x, y, z, color) // or some other information

一般的な保管

一般的な方法はこれだけです:

set of voxels = set of (x,y,z, color)

ボクセルは空間内のポイントであり、2つのポイントが1つの場所を占めることはないため(静的ボクセルデータについて話していると思います)、トリプレット(x、y、z)は各ボクセルを一意に識別します。

単純なデータには問題ないはずです。しかし、それは決して高速なデータ構造ではありません。

レンダリングは、スキャンラインアルゴリズムによって行われます。ボクセルに関するTomのハードウェア記事には、スキャンラインアルゴリズムのイメージがあります

高速ルックアップ

高速ルックアップが必要な場合、ルックアップの最速のデータ構造はハッシュ(配列、マップなど)です。だから、あなたはそれからハッシュを作成する必要があります。したがって、単純に、任意の要素を取得するための最速の方法が必要です。

array [x][y][z] of (color)
  • これには、x、y、z座標でボクセルを検索するためのO(1)があります。

  • 問題は、スペース要件がO(D ^ 3)であるということです。ここで、Dはx、y、zの各数値の範囲です(256の値の範囲を持つCharの場合、256になるため、実数は忘れてください) 3 = 2 ^ 24 == 16 777 216配列の要素)。

しかし、それはあなたがボクセルで何をしたいかに依存します。レンダリングがあなたの望むものであるなら、おそらくあなたが望むのはこの配列でしょう。しかし、ストレージの問題はまだ残っています...

ストレージに問題がある場合

1つの方法は、配列でRLE圧縮を使用することです。ボクセルのスライス(ボクセルのセット。ボクセルには1つの座標定数値があります。たとえば、z = 13の平面のように)を想像してください。このようなボクセルのスライスは、MSPaintの単純な描画のように見えます。ボクセルモデルは、通常、考えられるすべての場所の一部を占めます(考えられるすべてのボクセルのD ^ 3スペース)。「座標のトリプレットからペアを取り、残りの軸を圧縮する」ことがトリックだと思います(たとえば、[x] [y]を取り、各要素について、指定されたx、yでz軸のすべてのボクセルを圧縮します。 。0から数個の要素があり、RLEはここで問題ありません):

array [x][y] of RLE compressed z "lines" of voxel; each uncompressed voxel has color 
  • Ken SilvermanのVoxlapで使用されています。彼のRLE圧縮は、鉱山のバリエーションとは異なる場合があります。
  • カーマックは、ボクセルのどこかでRLE圧縮を行うことにも言及しました。ところで、John CarmackはRLEで圧縮することでQuakeでPVSを最適化しました
  • このように、任意のボクセルデータを保存する最良の方法ではない場合があります。

ストレージの問題を解決する他の方法は、ツリーデータ構造を使用した配列の代わりです。

tree data structure  = recursively classified voxels
for octrees: recursively classified by which octant does voxel at (x,y,z) belong to
  • オクトリー、ニックが言及したように。ボクセルを圧縮する必要があります。Octreeのルックアップ速度はまあまあです。O(log N)で、Nはボクセルの数です。
  • Octreeは、適切に任意のボクセルデータを保存できる必要があります。

ボクセルが単純なハイトマップである場合は、それだけを保存できます。または、高さマップを生成する関数のパラメーターを保存することもできます。

そしてもちろん、すべての可能なアプローチを組み合わせることができます。ただし、コードが機能することをテストし、それが本当に高速であることを測定しない限り、無理をしないでください(最適化の価値があります)。

TL; DR

Octrees以外には、ボクセル、Google「voxlap」、「ken silverman」を使用したRLE圧縮があります...

資源

リソースのリストと高速ボクセルレンダラーの作成方法に関する議論があり、論文とソースコードが含まれています


1
「ストレージが問題である場合は、」:また、あなたは、VTC(使用することができますoss.sgi.com/projects/ogl-sample/registry/NV/...)またはDXT圧縮を
KindDragon

@KindDragonこの情報をありがとう。:)それは非常に良い考えです。
user712092

リソースリンクがダウンしています。
エゼキエル14年

4

彼らが話しているかもしれない2つの異なるデータ構造の側面があります。

配列構造

任意の数の次元の配列の要素を参照する場合、インデックス(たとえば、myArray[4][6][15])を渡すと、配列自体がその場所にあるものを知っていると考えてください。その場所にあるものがボクセルである場合、そのボクセルは独自のx、y、およびz座標を追加で記録する必要はありません-ボクセルを保持する配列は、配列インデックス付きの位置に基づいて暗黙的に世界の位置を指定します。

これが良い理由は、この種の配列アクセスに使用されるポインター演算が本質的に高速であり、一般的に言えば、言語間で見られるほとんどの高速(「ネイティブ」と呼ばれる)配列の基盤を提供するからです。これらの配列の欠点は、前述のポインター演算を適用できるように、バイト単位で同じサイズの要素を持たなければならないことです。

オクトリーズ

(これはウィキペディアが参照している可能性が低いため、この2番目に注意します。また、ボクセルの実装ではoctreeを使用する必要はありませんが、現代のもののほとんどはoctreeを使用しています。)

octreeのルートノードは、分割されていない単一のキューブです。例を設定しましょう。octreeのルート(立方体の中心)が{0, 0, 0}3D空間にあるとします。その空間内にオブジェクトを配置し始めたら(読み取り:複数のオブジェクト)、octreeをさらに細分化します。これは、xy、xz、yz平面である3つの平面を使用してスライスすることにより、8(oct-)に分割する場所です。元のキューブには、8個の小さなキューブが正確に含まれるようになりました。これらのサブノードはそれぞれ、中央の親キューブからのオフセットとして配置されます。つまり、たとえば、正のxyzオクタントにあるキューブは、親からのオフセットを持ち、キューブの中心を正確に含む{root.width / 4, root.height / 4, root.depth / 4}。各サブノードの絶対位置を指定するのではなく、親ノードをその子空間の原点と見なす方が論理的に理にかなっています。これは、シーングラフの機能と同じです。

これを2D図面で見るのは簡単です。正方形を描き、それを4つの等しい領域に分割します。オクトツリールートノードのように、親の正方形の中心がと見なされる場合{0, 0}、子の正方形の4つの中心は次のようになります。

{root.width / 4, root.height / 4}{-root.width / 4, root.height / 4}{root.width / 4, -root.height / 4}{-root.width / 4, -root.height / 4}

...親を基準として-3Dと同じ原理。


ご回答ありがとうございます。私の場合、地形の大部分は同じタイプのボクセルで作られているため、八分木について考えていました(大きなチャンクを細分化する必要はありません)。ただし、実装がより簡単に見えるので、3D配列を試してみましょう。必要に応じて実装を切り替えるのがそれほど難しくないように、テレインクラスの実装の詳細を十分に抽象化できると確信しています。
-pwny

どういたしまして。私は間違いなく八分木を調べることをお勧めします、実際にはそれらを理解するのは難しくありません。しかし、はい、あなたのアプローチは今のところ理にかなっています、確かに3Dアレイを使用して最初のプロトタイピングを行う価値があります。
エンジニア

さらに読むと、いくつかの役立つリファレンスを含むoctreesの実装に関する適切な議論が、Intelのゲーム向けSTL拡張の記事にあります。
マーティンフット

1

RLEを使用できます。ただし、SVO(Sparse Voxel Octree)を使用できます。idTech 6はSVOを使用します。SVOは、八分木データ表現へのレイキャスティングまたはレイトレーシングアプローチを使用した3Dコンピュータグラフィックスレンダリング手法です。

テクニックは多少異なりますが、一般的には、画面の解像度とサイズを考慮して、可視または可視の可能性のあるポイントのハル(スパースボクセル)の生成と処理に依存します。

より高速であるため、レイキャスティングを使用します。


0

通常、地形の3Dデータ構造を回避できます。代わりに、高さマップを使用できます。これは、実行時に非常に安価で効率的にボクセル化できます。私の経験では、通常、各列でレンダリングするのに必要な最小の高さを追跡するだけでなく、場合によっては、背面の列もカリングできるように、開始-停止-上部の角度がかかります。

ここに私が長い間作ったものがあります:http : //sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash

地形に少数のオーバーハングや洞窟、またはハイトマップで表現できないその他のフィーチャがある場合、ハイトマップに穴を空けて、代替表現を作成できます。保証されています。

ボクセルの大規模な真の世界がある場合、スパースボクセル表現は価値があります。 ジョン・カーマックはここ数年、彼らと話をしています...


高さマップについても考えましたが、いくつかのことが私をそれらから遠ざけました。問題は、私の場合、地形は決して大きくないか、非常に複雑ではないことです(迷路型の地形、非常にデカルト的だと考えてください)。また、地形の一部を破壊可能にするか、ユーザーが建設を通じて地形に影響を与えることを許可します。これにより、プレイヤーが地形に「トンネル」を作成し、ハイトマップで表現するのがより複雑に見える場合があります。
pwny
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.