3D Array as 1D array?

How would I go about creating a 3D array using the "new" operator? I noticed that I could do:
 
int* array = new int[ width * height * depth ];

Which is the format I'd like to stick with since using [width,height,depth] does not work with or without the new operator.

However, I am not sure how to access array elements with this format. I found here http://gmc.yoyogames.com/index.php?showtopic=414085 that I could use:
 
array[ x * Height * Depth + y * Depth + z ] = value;

However, I am not sure how right/accurate this method is. Is this correct? Also, how do I go about grouping that indexing algorithm with parenthesis?
This is a very efficient way to store arrays, and it is right.
If you use a 3D array A[x][y][z] should be replaced by A[ x * height * depth + y * depth + z ]
If you have the 1D array A[index] and you want to see what that corresponds to in 3D,
1
2
3
width_index=index/(height*depth);  //Note the integer division . This is x
height_index=(index-width_index*height*depth)/depth; //This is y
depth_index=index-width_index*height*depth- height_index*depth;//This is z 
Thank you for the bonus info there. Now taking the aforementioned indexing algorithm into play:
 
x * Height * Depth + y * Depth + z;

How is that split up using parenthesis? I like to group everything in parenthesis to keep a good understanding of how it works.
Last edited on
BEDMAS.
In this case you only have multiplications and additions. Do the multiplications first moving left to right
((x * Height) * Depth) + (y * Depth) + z
then additions (left to right as well)
((((x * Height) * Depth) + (y * Depth)) + z)
frankly I think that makes it much harder to read :P
It looks like it's harder to read, because it is... however, it makes a better "at a glance" impression, making the overall readability far higher despite the overuse of parenthesis.
However, based on this little calculation I did: (3 x 3 x 3)

Depth: 0 (cells 0 to 8)
0,0,0
1,1,1
2,2,2

Depth: 1 (cells 9 to 17)
0,0,0
1,1,1
2,2,2

Depth: 2 (cells 18 to 26)
0,0,0
1,1,1
2,2,2

By plugging in cell: [ 1 , 2 , 0 ] I should get the 7th cell.
However based on:
 
((((x * Height) * Depth) + (y * Depth)) + z)

I get the 15th cell. So what is the issue here?

Instead wouldn't this make more sense?
 
( ( ( Width * Height ) * Zpos ) + ( Width * Ypos ) ) + Xpos;
Last edited on
I would wrap this in a class if I were to do this. Calculate the index in a getter. Allocate in the constructor and delete in the destructor.

1
2
3
int at( int x, int y, int z ) {
    return data[ z*width*height + y*width + x ];
}
Last edited on
Instead wouldn't this make more sense?

It makes the same amount of sense.

As long as you treat the dimensions consistently, it doesn't really matter which one is named x, y or z. Encapsulating access to the data structure as htirwin suggests is one way to ensure the dimensions are treated consistently.
If you use a 3D array A[x][y][z] should be replaced by A[ x * height * depth + y * depth + z ]

This is false, C++'s implementation of 3D array is exactly the same as taking a 1D array and handling the index yourself. Though you do have mroe control, such as which way to store it (row vs col major). C++'s implementation just uses row major if i recall correctly. You might be confused with std::vector<> and how people tend to use that to create a N dimension array std::vector<std::vector<std::vector<int>>>. In this case a lot of memory is wasted storing the data of the vectors, which usually just corresponds some data such as pointers and such.

You can just use boost's implementation, multi_array.
Last edited on
This is false, C++'s implementation of 3D array is exactly the same as taking a 1D array and handling the index yourself.


This isn't true if it's dynamically allocated.
Last edited on
This isn't true if it's dynamically allocated.

Yes it is... http://ideone.com/559Cyj
What difference do you think it makes having it on the stack or having it allocated else where in memory, it makes no difference how C++ handles arrays.
Last edited on
I meant this,
1
2
3
4
5
6
7
int ***a;
a = new int**[DEPTH];
for ( int i = 0; i < 10; ++i ) {
    a[i] = new int*[HEIGHT];
    for ( int j = 0; j < 10; ++j ) 
        a[i][j] = new int[WIDTH];	
}

Last edited on
http://ideone.com/f8Q7VN

What you've created isn't a 3D array.

Ah i get what you mean now. Still better to create a class to handle that, boost::multi_array should handle that. Your wording man, so much communication.
Last edited on
Topic archived. No new replies allowed.