/** 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)); } } } }