ゲームの「チャンク」システム用に3Dアレイを1Dアレイにフラット化しようとしています。それは3Dブロックゲームであり、基本的にチャンクシステムをMinecraftのシステムとほぼ同一にしたい(ただし、これはMinecraftのクローンではありません)。以前の2Dゲームでは、次のアルゴリズムを使用してフラット化された配列にアクセスしました。
Tiles[x + y * WIDTH]
ただし、Z軸が欠落しているため、これは明らかに3Dでは機能しません。この種のアルゴリズムを3D空間に実装する方法がわかりません。幅、高さ、深さはすべて一定です(幅は高さと同じくらいです)。
ただx + y*WIDTH + Z*DEPTH
?私は数学が苦手で、3Dプログラミングを始めたばかりなので、かなり迷っています:|
PS。その理由は、私はループを作成し、そこからかなり多くのインデックスを取得しているからです。 1D配列は多次元配列よりも高速であることを知っています(理由は覚えていません:P)。これは必要ではないかもしれませんが、可能な限り良好なパフォーマンスが必要です:)
アルゴリズムはほとんど同じです。 3D配列がある場合Original[HEIGHT, WIDTH, DEPTH]
その後、それをFlat[HEIGHT * WIDTH * DEPTH]
沿って
Flat[x + WIDTH * (y + DEPTH * z)] = Original[x, y, z]
余談ですが、.NETの多次元配列よりも配列の配列を優先する必要があります。パフォーマンスの違いは大きい
Javaの解決策は、両方を提供します:
以下は、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 };
}
上記には少し修正が必要だと思います。 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の場合、オーバーフローは発生せず、単なる完全な結果が得られます;)
x + y*WIDTH + Z*WIDTH*DEPTH
。それを直方体として視覚化します。最初にx
に沿ってトラバースし、次に各y
が「ライン」width
ステップ長で、各z
が"飛行機" WIDTH*DEPTH
エリア内のステップ。
あなたはほとんどそこにいます。 ZにWIDTH
andDEPTH
を掛ける必要があります。
Tiles[x + y*WIDTH + Z*WIDTH*DEPTH] = elements[x][y][z]; // or elements[x,y,z]
正しいアルゴリズムは次のとおりです。
Flat[ x * height * depth + y * depth + z ] = elements[x][y][z]
where [WIDTH][HEIGHT][DEPTH]
TL; DR
正解はさまざまな方法で書くことができますが、理解して視覚化するのが非常に簡単な方法で書くことができるのが一番好きです。正確な答えは次のとおりです。
(width * height * z) + (width * y) + x
TS; DR
それを視覚化する:
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
someNumberToRepresentZ
は、どの行列にあるかを示します(depth
)。どの行列にいるかを知るには、各行列の大きさを知る必要があります。マトリックスのサイズは2次元でwidth * height
、シンプル。尋ねる質問は、「いくつのマトリックスは、私がいるマトリックスの前ですか?」です。答えはz
:
someNumberToRepresentZ = width * height * z
someNumberToRepresentY
は、どの行にあるかを示します(height
)。どの行にいるかを知るには、各行の大きさを知る必要があります。各行は1dで、サイズはwidth
です。尋ねる質問は、「いくつの行は行の前にありますか?」です。答えはy
:
someNumberToRepresentY = width * y
someNumberToRepresentX
は、どの列にいるかを示します(width
)。どの列にいるかを知るには、単にx
を使用します。
someNumberToRepresentX = x
その後の可視化
someNumberToRepresentZ + someNumberToRepresentY + someNumberToRepresentX
になる
(width * height * z) + (width * y) + x
1D配列での3D配列の説明をよりよく理解するには(最良の答えの深さはYサイズを意味すると思います)
IndexArray = x + y * InSizeX + z * InSizeX * InSizeY;
IndexArray = x + InSizeX * (y + z * InSizeY);