I have a 1D array. Each element in the array is arranged to emulate a 3D index:

for (int x = 0; x < depth; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    for (int z = 0; z < width; ++z)
                    {
                        int index = x * width * height + y * width + z;

For each element I need to check all neighbouring elements to see if they exist. This means that a 3D array would produce a maximum of 26 possible neighbours per element.

I first have to check to see if the neighbouring element is in range using a set of booleans:

// Array indices
                            int leftIndex = x - 1;
                            int rightIndex = x + 1;
                            int bottomIndex = y - 1;
                            int topIndex = y + 1;
                            int farIndex = z - 1;
                            int nearIndex = z + 1;

                            bool left = leftIndex >= 0;
                            bool right = rightIndex < width;
                            bool bottom = bottomIndex >= 0;
                            bool top = topIndex < height;
                            bool far = farIndex >= 0;
                            bool near = nearIndex < depth;

With these boolean values I can determine if each one of the 26 neighbours exist.

How can I set up the boolean values so that I don't need to keep checking them for each neighbour?

In other words I can determine each neighbour as follows:

if (left && top && far)

if (top && far)

if (right && top && far)

if (left && top)

if (top)

// etc

but this will mean checking a boolean condition more than once.

Is there a way to use a |= operator with these boolean values and simplify them so they add up to a number? This can can be used with a switch case statement that knows which neighbours can be created?

Or can someone think of an alternative method to prevent repeating boolean checks for each neighbour?

Recommended Answers

All 4 Replies

Instead of using array indexes of 0..n-1, use indexes of 0..n+1. Place your values in 1 .. n so you have an 'empty' boarder around the entire array. Make sure those values are always 'empty' and then you don't have to do any kind of boolean check. Every valid element will have 26 neighbors.

Since you are using a 1d array as a 3d array, you'll have to adjust the size (my example was for a true 1d array).

Thank you. The array could be arranged like you suggested but it will mean a fair amount of recoding as my level structure is based on it.

If I am using a 1D array like a 3D array I will still need to check the indices like so:

// [Left, Top, Far]
neighbourIndex = leftIndex * width * height + topIndex * width + farIndex;

// [Centre, Top, Far]
neighbourIndex = x * width * height + topIndex * width + farIndex;

// [Right, Top, Far]
neighbourIndex = rightIndex * width * height + topIndex * width + farIndex;

// [Left, Top, Centre]
neighbourIndex = leftIndex * width * height + topIndex * width + z;

 // [Centre, Top, Centre]
neighbourIndex = x * width * height + topIndex * width + z;

Or is there a way to avoid that also?

Which of these two methods would be preferable and why? Or does it make no difference considering int is a struct?

for (int x = 1; x < depth - 1; ++x)
            {
                for (int y = 1; y < height - 1; ++y)
                {
                    for (int z = 1; z < width - 1; ++z)
                    {
                        int index = x * width * height + y * width + z;
                                           
                        // Current node = nodes[index]

                        // Check for neighbouring nodes
                        if (nodes[index] != null)
                        {
                            // Array indices
                            int leftIndex = x - 1;
                            int rightIndex = x + 1;
                            int bottomIndex = y - 1;
                            int topIndex = y + 1;
                            int farIndex = z - 1;
                            int nearIndex = z + 1;

                            int neighbourIndex;

OR

int index;

            int leftIndex;
            int rightIndex;
            int bottomIndex;
            int topIndex;
            int farIndex;
            int nearIndex;

            int neighbourIndex;


            for (int x = 1; x < depth - 1; ++x)
            {
                for (int y = 1; y < height - 1; ++y)
                {
                    for (int z = 1; z < width - 1; ++z)
                    {
                        index = x * width * height + y * width + z;
                                           
                        // Current node = nodes[index]

                        // Check for neighbouring nodes
                        if (nodes[index] != null)
                        {
                            // Array indices
                            leftIndex = x - 1;
                            rightIndex = x + 1;
                            bottomIndex = y - 1;
                            topIndex = y + 1;
                            farIndex = z - 1;
                            nearIndex = z + 1;

                            neighbourIndex;

Stack allocation is very fast and you probably won't notice a difference in the runtimes between the two. Over the long haul, the 2nd method will probably prove to be slightly faster (after thousands or tens of thousands of iterations). What I'd look at removing is the costly multiplications that you are doing every time. Possibly doing something like this (it's early here and I've not checked to make sure this is 100% accurate :)):

int xstep = width * height;
int xmax = xstep * depth;
int ymax = xstep;

for (int x = xstep; x < xmax; x += xstep) {
    for (int y = width; y < ymax; y += width) {
        for (int z = 1; z < width - 1; z++) {
            index = x + y + z;
            // blah blah ...
        }
    }
}

I need to point out again that I've not verified the limits yet (xstep, xmax, ymax). I'll look at it again in a few hours when I'm really awake :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.