Simplifying my neighbouring index algorithm

Started by
1 comment, last by symbiote 13 years, 3 months ago
I'm currently checking for neighbouring indices in a cube like formation:



// [Neighbour Index]
// z [TOP]
// / 0, 1, 2, 3, 4, 5, 6, 7, 8
// /
// [0]_____[1]_____[2] [MIDDLE]
// / | /| 9, 10, 11, 12, 13, 14, 15, 16
// / | / |
// [3] | [4] [5] | [BOTTOM]
// y / | / | 17, 18, 19, 20, 21, 22, 23, 24, 25
// | / | / |
// | [6]_____[7]_____[8]___ | [Array Indices]
// | [17] [18]| [19]
// | / | / +Y -Z
// | [20] [21] | [22] | /
// | / | / | /
// | / | / |/
// [23]____[24]____[25] --- x .-------> +X


The current algorithm is as follows:



// Check all neighbours
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;
int neighbourIndex;

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

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

// [Left, Top, Far]
// • XNA: -X, +Y, -Z
// • Array: -X, +Y, -Z

// Check array bounds
if (left && top && far)
{
neighbourIndex = leftIndex * width * height + topIndex * width + farIndex;

// Check if the node exists
if (nodes[neighbourIndex] != null)
{
// Add the neighbour
nodes[index].Neighbours[0] = nodes[neighbourIndex];
}
}

// [Centre, Top, Far]
if (top && far)
{
neighbourIndex = x * width * height + topIndex * width + farIndex;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[1] = nodes[neighbourIndex];
}
}

// [Right, Top, Far]
if (right && top && far)
{
neighbourIndex = rightIndex * width * height + topIndex * width + farIndex;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[2] = nodes[neighbourIndex];
}
}

// [Left, Top, Centre]
if (left && top)
{
neighbourIndex = leftIndex * width * height + topIndex * width + z;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[3] = nodes[neighbourIndex];
}
}

// [Centre, Top, Centre]
if (top)
{
neighbourIndex = x * width * height + topIndex * width + z;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[4] = nodes[neighbourIndex];
}
}

// [Right, Top, Centre]
if (right && top)
{
neighbourIndex = rightIndex * width * height + topIndex * width + z;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[5] = nodes[neighbourIndex];
}
}

// [Left, Top, Near]
if (left && top && near)
{
neighbourIndex = leftIndex * width * height + topIndex * width + nearIndex;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[6] = nodes[neighbourIndex];
}
}

// [Centre, Top, Near]
if (top && near)
{
neighbourIndex = x * width * height + topIndex * width + nearIndex;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[7] = nodes[neighbourIndex];
}
}

// [Right, Top, Near]
if (right && top && near)
{
neighbourIndex = rightIndex * width * height + topIndex * width + nearIndex;

if (nodes[neighbourIndex] != null)
{
nodes[index].Neighbours[8] = nodes[neighbourIndex];
}
}

// etc. etc.
}
}
}
}


but it is unnecessary to keep checking the boolean value for 'top' each time in the above case.

How could I check each surrounding node without as many if conditions?
Advertisement
- why are you checking if the node exists before adding it as a Neighbour?
- i mean... isn't "Neighbours" array null by default? (it certainly looks like it since you don't write anything there when you don't find a Neighbour)

you could try to nest some of those if statements but since it's a cube you will probably still have duplicate checks

you could perhaps loop over node array more in a more direct way to makes things more compact.

i made the following assumptions:
- the "Neighbours" array contains null values by default
- your "Neighbours" array contains a total number of 3*3*3 (27) elements
- everything is ordered in the same way in your "Neighbours" array as in your "nodes" array
i was thinking of something like this:


// loops over nodes
for( int i = 0; i < width*height*depth; i++ )
{
// get x, y, z of current node
int z = i % (width*height);
int y = (i-z) % width;
int x = (i-z) - y*height;

// check for potential neighbours (1 in each direction)
for( int x2 = x-1; x2 <= x+1; x2++ )
{
for( int y2 = y-1; y2 <= y+1; y2++ )
{
for( int z2 = z-1; z2 <= z+1; z2++ )
{
// get potential neighbour's index
int j;
j = x2*width*height + y2*width + z2;

// check if potential neighbour is within array bounds and node is not it's own neighbour
if( (0 <= j&&j < width*height*depth) && j!=i )
{
// get x, y, z of the found neighbour, relative to the cube around the current node (for the Neighbours array)
int neighbour_x = x2 - (x-1);
int neighbour_y = y2 - (y-1);
int neighbour_z = z2 - (z-1);

// store the neighbour, assuming that Neighbours has 3*3*3 (27) elements that are null by default
nodes.Neighbours[neighbour_x*3*3 + neighbour_y*3 + neighbour_z] = nodes[j];
}
}
}
}
}


edit: i just noticed that i didn't check the lower bounds... fixed it
edit2: i made it more readable
sorry for the double post

This topic is closed to new replies.

Advertisement