How to "flatten" or "index" 3D-array in 1D array?

I am trying to flatten 3D array into 1D array for "chunk" system in my game. It's a 3D-block game and basically I want the chunk system to be almost identical to Minecraft's system (however, this isn't Minecraft clone by any measure). In my previous 2D-games I have accessed the flattened array with following algorithm:

Tiles[x + y * WIDTH]

However, this obviously doesn't work with 3D since it's missing the Z-axis. I have no idea how to implement this sort of algorithm in 3D-space. Width, height and depth are all constants (and width is just as large as height).

Is it just x + y*WIDTH + Z*DEPTH ? I am pretty bad with math and I am just beginning 3D-programming so I am pretty lost :|

PS. The reason for this is that I am looping and getting stuff by index from it quite a lot. I know that 1D arrays are faster than multi-dimensional arrays (for reasons I cant remember :P ). Even though this may not be necessary, I want as good performance as possible :)


Solution 1:

Here is a solution in Java that gives you both:

  • from 3D to 1D
  • from 1D to 3D

Below is a graphical illustration of the path I chose to traverse the 3D matrix, the cells are numbered in their traversal order:

2 Examples of 3D matrices

Conversion functions:

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 };
}

Solution 2:

The algorithm is mostly the same. If you have a 3D array Original[HEIGHT, WIDTH, DEPTH] then you could turn it into Flat[HEIGHT * WIDTH * DEPTH] by

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

As an aside, you should prefer arrays of arrays over multi-dimensional arrays in .NET. The performance differences are significant

Solution 3:

I think the above needs a little correction. Lets say you have a HEIGHT of 10, and a WIDTH of 90, single dimensional array will be 900. By the above logic, if you are at the last element on the array 9 + 89*89, obviously this is greater than 900. The correct algorithm is:

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

Ironically if you the HEIGHT>WIDTH you will not experience an overflow, just complete bonkers results ;)