3D Array as 1D array?

Jul 8, 2014 at 2:43am
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?
Jul 8, 2014 at 3:27am
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 
Jul 8, 2014 at 3:31am
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 Jul 8, 2014 at 3:32am
Jul 8, 2014 at 4:01am
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
Jul 8, 2014 at 4:04am
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.
Jul 8, 2014 at 4:20am
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 Jul 8, 2014 at 4:38am
Jul 8, 2014 at 8:21pm
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 Jul 8, 2014 at 8:23pm
Jul 8, 2014 at 9:52pm
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.
Jul 8, 2014 at 9:57pm
closed account (10X9216C)
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 Jul 8, 2014 at 10:00pm
Jul 8, 2014 at 10:06pm
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 Jul 8, 2014 at 10:07pm
Jul 8, 2014 at 10:59pm
closed account (10X9216C)
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 Jul 8, 2014 at 11:06pm
Jul 8, 2014 at 11:21pm
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 Jul 8, 2014 at 11:28pm
Jul 8, 2014 at 11:44pm
closed account (10X9216C)
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 Jul 8, 2014 at 11:55pm
Topic archived. No new replies allowed.