/// <summary> /// Returns the intersection bounding box between the two bounds. /// The intersection bounds is the volume which is inside both bounds. /// If the rects do not have an intersection, an invalid rect is returned. /// See: IsValid /// </summary> public static IntBounds Intersection(IntBounds a, IntBounds b) { return(new IntBounds( math.max(a.min, b.min), math.min(a.max, b.max) )); }
public static void ForEachNode <T>(IntBounds bounds, ref T callback) where T : struct, INodeModifier { var size = bounds.size; int i = 0; for (int y = 0; y < size.y; y++) { for (int z = 0; z < size.z; z++) { for (int x = 0; x < size.x; x++, i++) { callback.ModifyNode(i, x, z); } } } }
/// <summary> /// Returns the data index for a node's neighbour in the given direction. /// /// The bounds, nodeConnections and layeredDataLayout fields can be retrieved from the \reflink{GridGraphRules.Context}.data object. /// /// Returns: Null if the node has no connection in that direction. Otherwise the data index for that node is returned. /// /// See: gridgraphrule-connection-filter (view in online documentation for working links) for example usage. /// </summary> /// <param name="bounds">Sub-rectangle of the grid graph that is being updated/scanned</param> /// <param name="nodeConnections">Data for all node connections</param> /// <param name="layeredDataLayout">True if this is a layered grid graph</param> /// <param name="dataX">X coordinate in the data arrays for the node for which you want to get a neighbour</param> /// <param name="dataLayer">Layer (Y) coordinate in the data arrays for the node for which you want to get a neighbour</param> /// <param name="dataZ">Z coordinate in the data arrays for the node for which you want to get a neighbour</param> /// <param name="direction">Direction to the neighbour. See \reflink{GridNode.HasConnectionInDirection}.</param> public static int?GetNeighbourDataIndex(IntBounds bounds, NativeArray <int> nodeConnections, bool layeredDataLayout, int dataX, int dataLayer, int dataZ, int direction) { // Find the coordinates of the adjacent node var dx = GridGraph.neighbourXOffsets[direction]; var dz = GridGraph.neighbourZOffsets[direction]; int nx = dataX + dx; int nz = dataZ + dz; // For valid nodeConnections arrays this is not necessary as out of bounds connections are not valid and it will thus be caught below in the 'has connection' check. // But let's be safe in case users do something weird if (nx < 0 || nz < 0 || nx >= bounds.size.x || nz >= bounds.size.z) { return(null); } // The data arrays are laid out row by row const int xstride = 1; var zstride = bounds.size.x; var ystride = bounds.size.x * bounds.size.z; var dataIndex = dataLayer * ystride + dataZ * zstride + dataX * xstride; var neighbourDataIndex = nz * zstride + nx * xstride; if (layeredDataLayout) { // In a layered grid graph we need to account for nodes in different layers var ny = nodeConnections[dataIndex] >> LevelGridNode.ConnectionStride * direction & LevelGridNode.ConnectionMask; if (ny == LevelGridNode.NoConnection) { return(null); } neighbourDataIndex += ny * ystride; } else if ((nodeConnections[dataIndex] & (1 << direction)) == 0) { return(null); } return(neighbourDataIndex); }
/// <summary>Returns the data index for a node's neighbour in the given direction</summary> public static int GetNeighbourDataIndex(IntBounds bounds, NativeArray <int> nodeConnections, bool layeredDataLayout, int dataIndex, int direction) { // Find the coordinates of the adjacent node var dx = GridGraph.neighbourXOffsets[direction]; var dz = GridGraph.neighbourZOffsets[direction]; // The data arrays are laid out row by row const int xstride = 1; var zstride = bounds.size.x; var neighbourDataIndex = dataIndex + dz * zstride + dx * xstride; if (layeredDataLayout) { // In a layered grid graph we need to account for nodes in different layers var y = dataIndex / (bounds.size.x * bounds.size.z); var neighbourY = nodeConnections[dataIndex] >> LevelGridNode.ConnectionStride * direction & LevelGridNode.ConnectionMask; neighbourDataIndex += (neighbourY - y) * bounds.size.x * bounds.size.z; } return(neighbourDataIndex); }
public static void FilterNodeConnections <T>(IntBounds bounds, NativeArray <int> nodeConnections, bool layeredDataLayout, ref T filter) where T : struct, IConnectionFilter { var size = bounds.size; int nodeIndex = 0; for (int y = 0; y < size.y; y++) { for (int z = 0; z < size.z; z++) { for (int x = 0; x < size.x; x++, nodeIndex++) { var conn = nodeConnections[nodeIndex]; if (layeredDataLayout) { // Layered grid graph for (int i = 0; i < 8; i++) { if (((conn >> LevelGridNode.ConnectionStride * i) & LevelGridNode.ConnectionMask) != LevelGridNode.NoConnection && !filter.IsValidConnection(nodeIndex, x, z, i)) { conn |= LevelGridNode.NoConnection << LevelGridNode.ConnectionStride * i; } } } else { // Normal grid graph // Iterate through all connections on the node for (int i = 0; i < 8; i++) { if ((conn & (1 << i)) != 0 && !filter.IsValidConnection(nodeIndex, x, z, i)) { conn &= ~(1 << i); } } } nodeConnections[nodeIndex] = conn; } } } }
/// <summary>Iterate through all nodes.</summary> /// <param name="bounds">Sub-rectangle of the grid graph that is being updated/scanned</param> /// <param name="nodeNormals">Data for all node normals. This is used to determine if a node exists (important for layered grid graphs).</param> /// <param name="callback">The ModifyNode method on the callback struct will be called for each node.</param> public static void ForEachNode <T>(IntBounds bounds, NativeArray <float4> nodeNormals, ref T callback) where T : struct, INodeModifier { var size = bounds.size; int i = 0; for (int y = 0; y < size.y; y++) { for (int z = 0; z < size.z; z++) { for (int x = 0; x < size.x; x++, i++) { // Check if the node exists at all // This is important for layered grid graphs // A normal is never zero otherwise if (math.any(nodeNormals[i])) { callback.ModifyNode(i, x, y, z); } } } } }
public bool Contains(IntBounds other) { return(math.all(other.min >= min & other.max <= max)); }