/** Calculates the grid connections for a single node */ public virtual void CalculateConnections (GridNode[] nodes, int x, int z, GridNode node) { //Reset all connections //node.flags = node.lags & -256; node.ResetConnectionsInternal (); //All connections are disabled if the node is not walkable if (!node.Walkable) { return; } int index = node.NodeInGridIndex; if (corners == null) { corners = new int[4]; } else { for (int i = 0;i<4;i++) { corners[i] = 0; } } for (int i=0, j = 3; i<4; j = i, i++) { int nx = x + neighbourXOffsets[i]; int nz = z + neighbourZOffsets[i]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } GridNode other = nodes[index+neighbourOffsets[i]] as GridNode; if (IsValidConnection (node, other)) { node.SetConnectionInternal (i, true); //SetNodeConnection (node, i, true); corners[i]++; corners[j]++; } else { node.SetConnectionInternal (i, false); //SetNodeConnection (node, i, false); } } if (neighbours == NumNeighbours.Eight) { if (cutCorners) { for (int i=0; i<4; i++) { if (corners[i] >= 1) { int nx = x + neighbourXOffsets[i+4]; int nz = z + neighbourZOffsets[i+4]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } GridNode other = nodes[index+neighbourOffsets[i+4]]; node.SetConnectionInternal (i+4, IsValidConnection (node,other)); //SetNodeConnection (node, i+4, IsValidConnection (node,other)); } } } else { for (int i=0; i<4; i++) { //We don't need to check if it is out of bounds because if both of the other neighbours are inside the bounds this one must be too if (corners[i] == 2) { GridNode other = nodes[index+neighbourOffsets[i+4]]; node.SetConnectionInternal (i+4, IsValidConnection (node,other)); //SetNodeConnection (node, i+4, IsValidConnection (node,other)); } } } } }
/** Calculates the grid connections for a single node */ public virtual void CalculateConnections (GridNode[] nodes, int x, int z, GridNode node) { //Reset all connections // This makes the node have NO connections to any neighbour nodes node.ResetConnectionsInternal (); //All connections are disabled if the node is not walkable if (!node.Walkable) { return; } // Internal index of where in the graph the node is int index = node.NodeInGridIndex; if (corners == null) { corners = new int[4]; } else { for (int i = 0;i<4;i++) { corners[i] = 0; } } // Loop through axis aligned neighbours (up, down, right, left) for (int i=0, j = 3; i<4; j = i, i++) { int nx = x + neighbourXOffsets[i]; int nz = z + neighbourZOffsets[i]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } GridNode other = nodes[index+neighbourOffsets[i]] as GridNode; if (IsValidConnection (node, other)) { node.SetConnectionInternal (i, true); corners[i]++; corners[j]++; } else { node.SetConnectionInternal (i, false); } } // Add in the diagonal connections if (neighbours == NumNeighbours.Eight) { if (cutCorners) { for (int i=0; i<4; i++) { if (corners[i] >= 1) { int nx = x + neighbourXOffsets[i+4]; int nz = z + neighbourZOffsets[i+4]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } GridNode other = nodes[index+neighbourOffsets[i+4]]; node.SetConnectionInternal (i+4, IsValidConnection (node,other)); } } } else { for (int i=0; i<4; i++) { //We don't need to check if it is out of bounds because if both of the other neighbours are inside the bounds this one must be too if (corners[i] == 2) { GridNode other = nodes[index+neighbourOffsets[i+4]]; node.SetConnectionInternal (i+4, IsValidConnection (node,other)); } } } } }
/** Calculates the grid connections for a single node. * The x and z parameters are assumed to be the grid coordinates of the node. * * \see CalculateConnections(GridNode) */ public virtual void CalculateConnections (int x, int z, GridNode node) { // All connections are disabled if the node is not walkable if (!node.Walkable) { // Reset all connections // This makes the node have NO connections to any neighbour nodes node.ResetConnectionsInternal(); return; } // Internal index of where in the graph the node is int index = node.NodeInGridIndex; if (neighbours == NumNeighbours.Four || neighbours == NumNeighbours.Eight) { // Bitpacked connections // bit 0 is set if connection 0 is enabled // bit 1 is set if connection 1 is enabled etc. int conns = 0; // Loop through axis aligned neighbours (down, right, up, left) or (-Z, +X, +Z, -X) for (int i = 0; i < 4; i++) { int nx = x + neighbourXOffsets[i]; int nz = z + neighbourZOffsets[i]; // Check if the new position is inside the grid // Bitwise AND (&) is measurably faster than && // (not much, but this code is hot) if (nx >= 0 & nz >= 0 & nx < width & nz < depth) { var other = nodes[index+neighbourOffsets[i]]; if (IsValidConnection(node, other)) { // Enable connection i conns |= 1 << i; } } } // Bitpacked diagonal connections int diagConns = 0; // Add in the diagonal connections if (neighbours == NumNeighbours.Eight) { if (cutCorners) { for (int i = 0; i < 4; i++) { // If at least one axis aligned connection // is adjacent to this diagonal, then we can add a connection. // Bitshifting is a lot faster than calling node.GetConnectionInternal. // We need to check if connection i and i+1 are enabled // but i+1 may overflow 4 and in that case need to be wrapped around // (so 3+1 = 4 goes to 0). We do that by checking both connection i+1 // and i+1-4 at the same time. Either i+1 or i+1-4 will be in the range // from 0 to 4 (exclusive) if (((conns >> i | conns >> (i+1) | conns >> (i+1-4)) & 1) != 0) { int directionIndex = i+4; int nx = x + neighbourXOffsets[directionIndex]; int nz = z + neighbourZOffsets[directionIndex]; if (nx >= 0 & nz >= 0 & nx < width & nz < depth) { GridNode other = nodes[index+neighbourOffsets[directionIndex]]; if (IsValidConnection(node, other)) { diagConns |= 1 << directionIndex; } } } } } else { for (int i = 0; i < 4; i++) { // If exactly 2 axis aligned connections is adjacent to this connection // then we can add the connection // We don't need to check if it is out of bounds because if both of // the other neighbours are inside the bounds this one must be too if ((conns >> i & 1) != 0 && ((conns >> (i+1) | conns >> (i+1-4)) & 1) != 0) { GridNode other = nodes[index+neighbourOffsets[i+4]]; if (IsValidConnection(node, other)) { diagConns |= 1 << (i+4); } } } } } // Set all connections at the same time node.SetAllConnectionInternal(conns | diagConns); } else { // Hexagon layout // Reset all connections // This makes the node have NO connections to any neighbour nodes node.ResetConnectionsInternal(); // Loop through all possible neighbours and try to connect to them for (int j = 0; j < hexagonNeighbourIndices.Length; j++) { var i = hexagonNeighbourIndices[j]; int nx = x + neighbourXOffsets[i]; int nz = z + neighbourZOffsets[i]; if (nx >= 0 & nz >= 0 & nx < width & nz < depth) { var other = nodes[index+neighbourOffsets[i]]; node.SetConnectionInternal(i, IsValidConnection(node, other)); } } } }
/** Calculates the grid connections for a single node */ public virtual void CalculateConnections (GridNode[] nodes, int x, int z, GridNode node) { //Reset all connections // This makes the node have NO connections to any neighbour nodes node.ResetConnectionsInternal (); //All connections are disabled if the node is not walkable if (!node.Walkable) { return; } // Internal index of where in the graph the node is int index = node.NodeInGridIndex; if (neighbours == NumNeighbours.Four || neighbours == NumNeighbours.Eight) { // Reset the buffer if (corners == null) { corners = new int[4]; } else { for (int i = 0;i<4;i++) { corners[i] = 0; } } // Loop through axis aligned neighbours (up, down, right, left) for (int i=0, j = 3; i<4; j = i, i++) { int nx = x + neighbourXOffsets[i]; int nz = z + neighbourZOffsets[i]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } var other = nodes[index+neighbourOffsets[i]]; if (IsValidConnection (node, other)) { node.SetConnectionInternal (i, true); // Mark the diagonal/corner adjacent to this connection as used corners[i]++; corners[j]++; } else { node.SetConnectionInternal (i, false); } } // Add in the diagonal connections if (neighbours == NumNeighbours.Eight) { if (cutCorners) { for (int i=0; i<4; i++) { // If at least one axis aligned connection // is adjacent to this diagonal, then we can add a connection if (corners[i] >= 1) { int nx = x + neighbourXOffsets[i+4]; int nz = z + neighbourZOffsets[i+4]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } GridNode other = nodes[index+neighbourOffsets[i+4]]; node.SetConnectionInternal (i+4, IsValidConnection (node,other)); } } } else { for (int i=0; i<4; i++) { // If exactly 2 axis aligned connections is adjacent to this connection // then we can add the connection //We don't need to check if it is out of bounds because if both of the other neighbours are inside the bounds this one must be too if (corners[i] == 2) { GridNode other = nodes[index+neighbourOffsets[i+4]]; node.SetConnectionInternal (i+4, IsValidConnection (node,other)); } } } } } else { // Hexagon layout // Loop through all possible neighbours and try to connect to them for (int j = 0; j < hexagonNeighbourIndices.Length; j++) { var i = hexagonNeighbourIndices[j]; int nx = x + neighbourXOffsets[i]; int nz = z + neighbourZOffsets[i]; if (nx < 0 || nz < 0 || nx >= width || nz >= depth) { continue; } var other = nodes[index+neighbourOffsets[i]]; node.SetConnectionInternal (i, IsValidConnection (node, other)); } } }