41

ゲームの「チャンク」システム用に 3D 配列を 1D 配列にフラット化しようとしています。これは 3D ブロック ゲームであり、基本的にはチャンク システムを Minecraft のシステムとほぼ同じにしたいと考えています (ただし、これは決して Minecraft のクローンではありません)。以前の 2D ゲームでは、次のアルゴリズムでフラット化された配列にアクセスしました。

Tiles[x + y * WIDTH]

ただし、Z 軸がないため、これは明らかに 3D では機能しません。この種のアルゴリズムを 3D 空間で実装する方法がわかりません。幅、高さ、奥行きはすべて定数です (幅は高さと同じ大きさです)。

それはただx + y*WIDTH + Z*DEPTHですか?私は数学がかなり苦手で、3D プログラミングを始めたばかりなので、かなり迷っています :|

PS。この理由は、私がループして、そこからインデックスごとにかなり多くのものを取得しているためです。1D配列は多次元配列よりも高速であることを知っています(理由を思い出せません:P)。これは必要ないかもしれませんが、できるだけ良いパフォーマンスが欲しいです:)

4

10 に答える 10

57

両方を提供するJavaのソリューションを次に示します。

  • 3Dから1Dへ
  • 一次元から三次元へ

以下は、3D マトリックスをトラバースするために選択したパスのグラフィカルな図です。セルには、トラバーサル順に番号が付けられています。

2 3D マトリックスの例

変換機能:

public int to1D( int x, int y, int z ) {
    return (z * xMax * yMax) + (y * xMax) + x;
}

public int[] to3D( int idx ) {
    final int z = idx / (xMax * yMax);
    idx -= (z * xMax * yMax);
    final int y = idx / xMax;
    final int x = idx % xMax;
    return new int[]{ x, y, z };
}
于 2015-12-18T20:08:43.617 に答える
49

アルゴリズムはほとんど同じです。3D配列がある場合は、次のようにOriginal[HEIGHT, WIDTH, DEPTH]変換できますFlat[HEIGHT * WIDTH * DEPTH]

Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]

余談ですが、.NET では多次元配列よりも配列の配列を優先する必要があります。パフォーマンスの違いは重要です

于 2011-09-09T21:46:49.290 に答える
38

上記は少し修正が必要だと思います。HEIGHT が 10、WIDTH が 90 の場合、1 次元配列は 900 になるとします。上記のロジックにより、配列の最後の要素 9 + 89*89 にいる場合、明らかにこれは 900 よりも大きくなります。正しいアルゴリズムは次のとおりです。

Flat[x + HEIGHT* (y + WIDTH* z)] = Original[x, y, z], assuming Original[HEIGHT,WIDTH,DEPTH] 

皮肉なことに、HEIGHT>WIDTH の場合、オーバーフローは発生せず、完全なボンカーの結果になります ;)

于 2013-05-17T13:16:50.960 に答える
11

x + y*WIDTH + Z*WIDTH*DEPTH. それを直方体として視覚化します。最初に に沿ってトラバースするとx、それぞれyが「線」widthステップの長さになり、それぞれzが領域内の「平面」WIDTH*DEPTHステップになります。

于 2011-09-09T21:46:30.280 に答える
7

あなたはほとんどそこにいます。WIDTH Z にと を掛ける必要がありますDEPTH

Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
于 2011-09-09T21:46:02.107 に答える
4

正しいアルゴリズムは次のとおりです。

Flat[ x * height * depth + y * depth + z ] = elements[x][y][z] 
where [WIDTH][HEIGHT][DEPTH]
于 2018-03-13T10:14:24.677 に答える