public override void UpdateRecursiveG(Path path, PathNode pathNode, PathHandler handler) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; base.UpdateG(path, pathNode); handler.heap.Add(pathNode); ushort pathID = handler.PathID; int nodeInGridIndex = base.NodeInGridIndex; for (int i = 0; i < 8; i++) { if (this.HasConnectionInDirection(i)) { GridNode gridNode = nodes[nodeInGridIndex + neighbourOffsets[i]]; PathNode pathNode2 = handler.GetPathNode(gridNode); if (pathNode2.parent == pathNode && pathNode2.pathID == pathID) { gridNode.UpdateRecursiveG(path, pathNode2, handler); } } } base.UpdateRecursiveG(path, pathNode, handler); }
// Token: 0x060025D1 RID: 9681 RVA: 0x001A6030 File Offset: 0x001A4230 public override Vector3 RandomPointOnSurface() { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); Vector3 a = gridGraph.transform.InverseTransform((Vector3)this.position); return(gridGraph.transform.Transform(a + new Vector3(UnityEngine.Random.value - 0.5f, 0f, UnityEngine.Random.value - 0.5f))); }
/** Helper method to set PathNode.flag1 to a specific value for all nodes adjacent to a grid node */ void SetFlag1OnSurroundingGridNodes(GridNode gridNode, bool flag1State) { // Loop through all adjacent grid nodes var gridGraph = GridNode.GetGridGraph(gridNode.GraphIndex); // Number of neighbours as an int int mxnum = gridGraph.neighbours == NumNeighbours.Four ? 4 : (gridGraph.neighbours == NumNeighbours.Eight ? 8 : 6); // Calculate the coordinates of the node var x = gridNode.NodeInGridIndex % gridGraph.width; var z = gridNode.NodeInGridIndex / gridGraph.width; for (int i = 0; i < mxnum; i++) { int nx, nz; if (gridGraph.neighbours == NumNeighbours.Six) { // Hexagon graph nx = x + gridGraph.neighbourXOffsets[GridGraph.hexagonNeighbourIndices[i]]; nz = z + gridGraph.neighbourZOffsets[GridGraph.hexagonNeighbourIndices[i]]; } else { nx = x + gridGraph.neighbourXOffsets[i]; nz = z + gridGraph.neighbourZOffsets[i]; } // Check if the position is still inside the grid if (nx >= 0 && nz >= 0 && nx < gridGraph.width && nz < gridGraph.depth) { var adjacentNode = gridGraph.nodes[nz * gridGraph.width + nx]; pathHandler.GetPathNode(adjacentNode).flag1 = flag1State; } } }
public override void UpdateRecursiveG(Path path, PathNode pathNode, PathHandler handler) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; base.UpdateG(path, pathNode); handler.PushNode(pathNode); ushort pathID = handler.PathID; for (int i = 0; i < 8; i++) { if (this.GetConnectionInternal(i)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]]; PathNode pathNode2 = handler.GetPathNode(gridNode); if (pathNode2.parent == pathNode && pathNode2.pathID == pathID) { gridNode.UpdateRecursiveG(path, pathNode2, handler); } } } if (this.connections != null) { for (int j = 0; j < this.connections.Length; j++) { GraphNode graphNode = this.connections[j]; PathNode pathNode3 = handler.GetPathNode(graphNode); if (pathNode3.parent == pathNode && pathNode3.pathID == pathID) { graphNode.UpdateRecursiveG(path, pathNode3, handler); } } } }
public override void ClearConnections(bool alsoReverse) { if (alsoReverse) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); for (int i = 0; i < 8; i++) { GridNode nodeConnection = gridGraph.GetNodeConnection(this, i); if (nodeConnection != null) { nodeConnection.SetConnectionInternal((i >= 4) ? 7 : ((i + 2) % 4), false); } } } this.ResetConnectionsInternal(); if (alsoReverse && this.connections != null) { for (int j = 0; j < this.connections.Length; j++) { this.connections[j].RemoveConnection(this); } } this.connections = null; this.connectionCosts = null; }
public override void GetConnections(GraphNodeDelegate del) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 8; i++) { if (this.GetConnectionInternal(i)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]]; if (gridNode != null) { del(gridNode); } } } if (this.connections != null) { for (int j = 0; j < this.connections.Length; j++) { del(this.connections[j]); } } }
public override void FloodFill(Stack <GraphNode> stack, uint region) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 8; i++) { if (this.GetConnectionInternal(i)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]]; if (gridNode != null && gridNode.Area != region) { gridNode.Area = region; stack.Push(gridNode); } } } if (this.connections != null) { for (int j = 0; j < this.connections.Length; j++) { GraphNode graphNode = this.connections[j]; if (graphNode.Area != region) { graphNode.Area = region; stack.Push(graphNode); } } } }
public Vector3 Point2GraphSpace(float height) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int num = this.nodeInGridIndex % gridGraph.width; int num2 = this.nodeInGridIndex / gridGraph.width; return(new Vector3((float)num, height, (float)num2)); }
public override Vector3 RandomPointOnSurface() { GridGraph gg = GridNode.GetGridGraph(GraphIndex); var graphSpacePosition = gg.transform.InverseTransform((Vector3)position); return(gg.transform.Transform(graphSpacePosition + new Vector3(Random.value - 0.5f, 0, Random.value - 0.5f))); }
public override GridNodeBase GetNeighbourAlongDirection(int direction) { if (this.HasConnectionInDirection(direction)) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); return(gridGraph.nodes[base.NodeInGridIndex + gridGraph.neighbourOffsets[direction]]); } return(null); }
public override bool GetPortal(GraphNode other, List <Vector3> left, List <Vector3> right, bool backwards) { if (backwards) { return(true); } GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 4; i++) { if (this.GetConnectionInternal(i) && other == nodes[this.nodeInGridIndex + neighbourOffsets[i]]) { Vector3 a = (Vector3)(this.position + other.position) * 0.5f; Vector3 vector = Vector3.Cross(gridGraph.collision.up, (Vector3)(other.position - this.position)); vector.Normalize(); vector *= gridGraph.nodeSize * 0.5f; left.Add(a - vector); right.Add(a + vector); return(true); } } for (int j = 4; j < 8; j++) { if (this.GetConnectionInternal(j) && other == nodes[this.nodeInGridIndex + neighbourOffsets[j]]) { bool flag = false; bool flag2 = false; if (this.GetConnectionInternal(j - 4)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[j - 4]]; if (gridNode.Walkable && gridNode.GetConnectionInternal((j - 4 + 1) % 4)) { flag = true; } } if (this.GetConnectionInternal((j - 4 + 1) % 4)) { GridNode gridNode2 = nodes[this.nodeInGridIndex + neighbourOffsets[(j - 4 + 1) % 4]]; if (gridNode2.Walkable && gridNode2.GetConnectionInternal(j - 4)) { flag2 = true; } } Vector3 a2 = (Vector3)(this.position + other.position) * 0.5f; Vector3 vector2 = Vector3.Cross(gridGraph.collision.up, (Vector3)(other.position - this.position)); vector2.Normalize(); vector2 *= gridGraph.nodeSize * 1.4142f; left.Add(a2 - ((!flag2) ? Vector3.zero : vector2)); right.Add(a2 + ((!flag) ? Vector3.zero : vector2)); return(true); } } return(false); }
//GG //public override Vector3 RandomPointOnSurface () { public override VInt3 RandomPointOnSurface() { GridGraph gg = GridNode.GetGridGraph(GraphIndex); //GG //var graphSpacePosition = gg.transform.InverseTransform((Vector3)position); var graphSpacePosition = gg.transform.InverseTransform(position); //GG //return gg.transform.Transform(graphSpacePosition + new Vector3(Random.value - 0.5f, 0, Random.value - 0.5f)); return(gg.transform.Transform(graphSpacePosition + new VInt3(VRandom.Random(1, 1000) - 500, 0, VRandom.Random(1, 1000) - 500))); }
// Token: 0x06002568 RID: 9576 RVA: 0x0019FE30 File Offset: 0x0019E030 public Vector3 ClosestPointOnNode(Vector3 p) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); p = gridGraph.transform.InverseTransform(p); int num = base.NodeInGridIndex % gridGraph.width; int num2 = base.NodeInGridIndex / gridGraph.width; float y = gridGraph.transform.InverseTransform((Vector3)this.position).y; Vector3 point = new Vector3(Mathf.Clamp(p.x, (float)num, (float)num + 1f), y, Mathf.Clamp(p.z, (float)num2, (float)num2 + 1f)); return(gridGraph.transform.Transform(point)); }
public Vector3 ClosestPointOnNode(Vector3 p) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); p = gridGraph.inverseMatrix.MultiplyPoint3x4(p); float value = (float)this.position.x - 0.5f; float value2 = (float)this.position.z - 0.5f; int num = this.nodeInGridIndex % gridGraph.width; int num2 = this.nodeInGridIndex / gridGraph.width; float y = gridGraph.inverseMatrix.MultiplyPoint3x4(p).y; Vector3 v = new Vector3(Mathf.Clamp(value, (float)num - 0.5f, (float)num + 0.5f) + 0.5f, y, Mathf.Clamp(value2, (float)num2 - 0.5f, (float)num2 + 0.5f) + 0.5f); return(gridGraph.matrix.MultiplyPoint3x4(v)); }
public Vector3 ClosestPointOnNode(Vector3 p) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); p = gridGraph.transform.InverseTransform(p); float value = (float)this.position.x - 0.5f; float value2 = (float)this.position.z - 0.5f; int num = base.NodeInGridIndex % gridGraph.width; int num2 = base.NodeInGridIndex / gridGraph.width; float y = gridGraph.transform.InverseTransform((Vector3)this.position).y; Vector3 p2 = new Vector3(Mathf.Clamp(value, (float)num - 0.5f, (float)num + 0.5f) + 0.5f, y, Mathf.Clamp(value2, (float)num2 - 0.5f, (float)num2 + 0.5f) + 0.5f); return(gridGraph.transform.Transform(p2)); }
/// <summary>Helper method to set PathNode.flag1 to a specific value for all nodes adjacent to a grid node</summary> private void SetFlagOnSurroundingGridNodes(GridNode gridNode, int flag, bool flagState) { // Loop through all adjacent grid nodes var gridGraph = GridNode.GetGridGraph(gridNode.GraphIndex); // Number of neighbours as an int var mxnum = gridGraph.neighbours == NumNeighbours.Four ? 4 : gridGraph.neighbours == NumNeighbours.Eight ? 8 : 6; // Calculate the coordinates of the node var x = gridNode.NodeInGridIndex % gridGraph.width; var z = gridNode.NodeInGridIndex / gridGraph.width; if (flag != 1 && flag != 2) { throw new System.ArgumentOutOfRangeException("flag"); } for (var i = 0; i < mxnum; i++) { int nx, nz; if (gridGraph.neighbours == NumNeighbours.Six) { // Hexagon graph nx = x + gridGraph.neighbourXOffsets[GridGraph.hexagonNeighbourIndices[i]]; nz = z + gridGraph.neighbourZOffsets[GridGraph.hexagonNeighbourIndices[i]]; } else { nx = x + gridGraph.neighbourXOffsets[i]; nz = z + gridGraph.neighbourZOffsets[i]; } // Check if the position is still inside the grid if (nx >= 0 && nz >= 0 && nx < gridGraph.width && nz < gridGraph.depth) { var adjacentNode = gridGraph.nodes[nz * gridGraph.width + nx]; var pathNode = pathHandler.GetPathNode(adjacentNode); if (flag == 1) { pathNode.flag1 = flagState; } else { pathNode.flag2 = flagState; } } } }
// Token: 0x060004E2 RID: 1250 RVA: 0x0002AB84 File Offset: 0x00028F84 public override void ClearConnections(bool alsoReverse) { if (alsoReverse) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); for (int i = 0; i < 8; i++) { GridNode nodeConnection = gridGraph.GetNodeConnection(this, i); if (nodeConnection != null) { nodeConnection.SetConnectionInternal((i >= 4) ? 7 : ((i + 2) % 4), false); } } } this.ResetConnectionsInternal(); }
public override void Open(Path path, PathNode pathNode, PathHandler handler) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); ushort pathID = handler.PathID; int[] neighbourOffsets = gridGraph.neighbourOffsets; uint[] neighbourCosts = gridGraph.neighbourCosts; GridNode[] nodes = gridGraph.nodes; int nodeInGridIndex = base.NodeInGridIndex; for (int i = 0; i < 8; i++) { if (this.HasConnectionInDirection(i)) { GridNode gridNode = nodes[nodeInGridIndex + neighbourOffsets[i]]; if (path.CanTraverse(gridNode)) { PathNode pathNode2 = handler.GetPathNode(gridNode); uint num = neighbourCosts[i]; if (pathNode2.pathID != pathID) { pathNode2.parent = pathNode; pathNode2.pathID = pathID; pathNode2.cost = num; pathNode2.H = path.CalculateHScore(gridNode); gridNode.UpdateG(path, pathNode2); handler.heap.Add(pathNode2); } else if (pathNode.G + num + path.GetTraversalCost(gridNode) < pathNode2.G) { pathNode2.cost = num; pathNode2.parent = pathNode; gridNode.UpdateRecursiveG(path, pathNode2, handler); } else if (pathNode2.G + num + path.GetTraversalCost(this) < pathNode.G) { pathNode.parent = pathNode2; pathNode.cost = num; this.UpdateRecursiveG(path, pathNode, handler); } } } } base.Open(path, pathNode, handler); }
// Token: 0x06002567 RID: 9575 RVA: 0x0019FDDC File Offset: 0x0019DFDC public override void GetConnections(Action <GraphNode> action) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 8; i++) { if (this.HasConnectionInDirection(i)) { GridNode gridNode = nodes[base.NodeInGridIndex + neighbourOffsets[i]]; if (gridNode != null) { action(gridNode); } } } }
public override bool ContainsConnection(GraphNode node) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 8; i++) { if (this.GetConnectionInternal(i)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]]; if (gridNode == node) { return(true); } } } return(false); }
// Token: 0x0600256A RID: 9578 RVA: 0x001A0104 File Offset: 0x0019E304 public override void FloodFill(Stack <GraphNode> stack, uint region) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); int[] neighbourOffsets = gridGraph.neighbourOffsets; GridNode[] nodes = gridGraph.nodes; int nodeInGridIndex = base.NodeInGridIndex; for (int i = 0; i < 8; i++) { if (this.HasConnectionInDirection(i)) { GridNode gridNode = nodes[nodeInGridIndex + neighbourOffsets[i]]; if (gridNode != null && gridNode.Area != region) { gridNode.Area = region; stack.Push(gridNode); } } } }
private void SetFlagOnSurroundingGridNodes(GridNode gridNode, int flag, bool flagState) { GridGraph gridGraph = GridNode.GetGridGraph(gridNode.GraphIndex); int num = (gridGraph.neighbours != NumNeighbours.Four) ? ((gridGraph.neighbours != NumNeighbours.Eight) ? 6 : 8) : 4; int num2 = gridNode.NodeInGridIndex % gridGraph.width; int num3 = gridNode.NodeInGridIndex / gridGraph.width; if ((flag != 1) && (flag != 2)) { throw new ArgumentOutOfRangeException("flag"); } for (int i = 0; i < num; i++) { int num5; int num6; if (gridGraph.neighbours == NumNeighbours.Six) { num5 = num2 + gridGraph.neighbourXOffsets[GridGraph.hexagonNeighbourIndices[i]]; num6 = num3 + gridGraph.neighbourZOffsets[GridGraph.hexagonNeighbourIndices[i]]; } else { num5 = num2 + gridGraph.neighbourXOffsets[i]; num6 = num3 + gridGraph.neighbourZOffsets[i]; } if (((num5 >= 0) && (num6 >= 0)) && ((num5 < gridGraph.width) && (num6 < gridGraph.depth))) { GridNode node = gridGraph.nodes[(num6 * gridGraph.width) + num5]; PathNode pathNode = base.pathHandler.GetPathNode(node); if (flag == 1) { pathNode.flag1 = flagState; } else { pathNode.flag2 = flagState; } } } }
// Token: 0x06002719 RID: 10009 RVA: 0x001AF3CC File Offset: 0x001AD5CC private void SetFlagOnSurroundingGridNodes(GridNode gridNode, int flag, bool flagState) { GridGraph gridGraph = GridNode.GetGridGraph(gridNode.GraphIndex); int num = (gridGraph.neighbours == NumNeighbours.Four) ? 4 : ((gridGraph.neighbours == NumNeighbours.Eight) ? 8 : 6); int num2 = gridNode.NodeInGridIndex % gridGraph.width; int num3 = gridNode.NodeInGridIndex / gridGraph.width; if (flag != 1 && flag != 2) { throw new ArgumentOutOfRangeException("flag"); } for (int i = 0; i < num; i++) { int num4; int num5; if (gridGraph.neighbours == NumNeighbours.Six) { num4 = num2 + gridGraph.neighbourXOffsets[GridGraph.hexagonNeighbourIndices[i]]; num5 = num3 + gridGraph.neighbourZOffsets[GridGraph.hexagonNeighbourIndices[i]]; } else { num4 = num2 + gridGraph.neighbourXOffsets[i]; num5 = num3 + gridGraph.neighbourZOffsets[i]; } if (num4 >= 0 && num5 >= 0 && num4 < gridGraph.width && num5 < gridGraph.depth) { GridNode node = gridGraph.nodes[num5 * gridGraph.width + num4]; PathNode pathNode = this.pathHandler.GetPathNode(node); if (flag == 1) { pathNode.flag1 = flagState; } else { pathNode.flag2 = flagState; } } } }
/** Applies a special case for grid nodes. * * Assume the closest walkable node is a grid node. * We will now apply a special case only for grid graphs. * In tile based games, an obstacle often occupies a whole * node. When a path is requested to the position of an obstacle * (single unwalkable node) the closest walkable node will be * one of the 8 nodes surrounding that unwalkable node * but that node is not neccessarily the one that is most * optimal to walk to so in this special case * we mark all nodes around the unwalkable node as targets * and when we search and find any one of them we simply exit * and set that first node we found to be the 'real' end node * because that will be the optimal node (this does not apply * in general unless the heuristic is set to None, but * for a single unwalkable node it does). * This also applies if the nearest node cannot be traversed for * some other reason like restricted tags. * * \returns True if the workaround was applied. If this happens the * endPoint, endNode, hTarget and hTargetNode fields will be modified. * * Image below shows paths when this special case is applied. The path goes from the white sphere to the blue orange box. * \shadowimage{abpath_grid_special.gif} * * Image below shows paths when this special case has been disabled * \shadowimage{abpath_grid_not_special.gif} */ protected virtual bool EndPointGridGraphSpecialCase(GraphNode closestWalkableEndNode) { var gridNode = closestWalkableEndNode as GridNode; if (gridNode != null) { var gridGraph = GridNode.GetGridGraph(gridNode.GraphIndex); // Find the closest node, not neccessarily walkable var endNNInfo2 = AstarPath.active.GetNearest(originalEndPoint, NNConstraint.None, endHint); var gridNode2 = endNNInfo2.node as GridNode; if (gridNode != gridNode2 && gridNode2 != null && gridNode.GraphIndex == gridNode2.GraphIndex) { // Calculate the coordinates of the nodes var x1 = gridNode.NodeInGridIndex % gridGraph.width; var z1 = gridNode.NodeInGridIndex / gridGraph.width; var x2 = gridNode2.NodeInGridIndex % gridGraph.width; var z2 = gridNode2.NodeInGridIndex / gridGraph.width; bool wasClose = false; switch (gridGraph.neighbours) { case NumNeighbours.Four: if ((x1 == x2 && System.Math.Abs(z1 - z2) == 1) || (z1 == z2 && System.Math.Abs(x1 - x2) == 1)) { // If 'O' is gridNode2, then gridNode is one of the nodes marked with an 'x' // x // x O x // x wasClose = true; } break; case NumNeighbours.Eight: if (System.Math.Abs(x1 - x2) <= 1 && System.Math.Abs(z1 - z2) <= 1) { // If 'O' is gridNode2, then gridNode is one of the nodes marked with an 'x' // x x x // x O x // x x x wasClose = true; } break; case NumNeighbours.Six: // Hexagon graph for (int i = 0; i < 6; i++) { var nx = x2 + gridGraph.neighbourXOffsets[GridGraph.hexagonNeighbourIndices[i]]; var nz = z2 + gridGraph.neighbourZOffsets[GridGraph.hexagonNeighbourIndices[i]]; if (x1 == nx && z1 == nz) { // If 'O' is gridNode2, then gridNode is one of the nodes marked with an 'x' // x x // x O x // x x wasClose = true; break; } } break; default: // Should not happen unless NumNeighbours is modified in the future throw new System.Exception("Unhandled NumNeighbours"); } if (wasClose) { // We now need to find all nodes marked with an x to be able to mark them as targets SetFlagOnSurroundingGridNodes(gridNode2, 1, true); // Note, other methods assume hTarget is (Int3)endPoint endPoint = (Vector3)gridNode2.position; hTarget = gridNode2.position; endNode = gridNode2; // hTargetNode is used for heuristic optimizations // (also known as euclidean embedding). // Even though the endNode is not walkable // we can use it for better heuristics since // there is a workaround added (EuclideanEmbedding.ApplyGridGraphEndpointSpecialCase) // which is there to support this case. hTargetNode = endNode; // We need to save this node // so that we can reset flag1 on all nodes later gridSpecialCaseNode = gridNode2; return(true); } } } return(false); }
/** Returns randomly selected points on the specified nodes with each point being separated by \a clearanceRadius from each other. * Selecting points ON the nodes only works for TriangleMeshNode (used by Recast Graph and Navmesh Graph) and GridNode (used by GridGraph). * For other node types, only the positions of the nodes will be used. * * clearanceRadius will be reduced if no valid points can be found. */ public static List<Vector3> GetPointsOnNodes (List<GraphNode> nodes, int count, float clearanceRadius = 0) { if (nodes == null) throw new ArgumentNullException ("nodes"); if (nodes.Count == 0) throw new ArgumentException ("no nodes passed"); var rnd = new System.Random(); var pts = ListPool<Vector3>.Claim(count); // Square clearanceRadius *= clearanceRadius; if (nodes[0] is TriangleMeshNode || nodes[0] is GridNode) { //Assume all nodes are triangle nodes or grid nodes var accs = ListPool<float>.Claim(nodes.Count); float tot = 0; for (var i=0;i<nodes.Count;i++) { var tnode = nodes[i] as TriangleMeshNode; if (tnode != null) { float a = Math.Abs(Polygon.TriangleArea(tnode.GetVertex(0), tnode.GetVertex(1), tnode.GetVertex(2))); tot += a; accs.Add (tot); } else { var gnode = nodes[i] as GridNode; if (gnode != null) { var gg = GridNode.GetGridGraph (gnode.GraphIndex); var a = gg.nodeSize*gg.nodeSize; tot += a; accs.Add (tot); } else { accs.Add(tot); } } } for (var i=0;i<count;i++) { //Pick point var testCount = 0; var testLimit = 10; var worked = false; while (!worked) { worked = true; //If no valid points can be found, progressively lower the clearance radius until such a point is found if (testCount >= testLimit) { clearanceRadius *= 0.8f; testLimit += 10; if (testLimit > 100) clearanceRadius = 0; } var tg = (float)rnd.NextDouble()*tot; var v = accs.BinarySearch(tg); if (v < 0) v = ~v; if (v >= nodes.Count) { // This shouldn't happen, due to NextDouble being smaller than 1... but I don't trust floating point arithmetic. worked = false; continue; } var node = nodes[v] as TriangleMeshNode; Vector3 p; if (node != null) { // Find a random point inside the triangle float v1; float v2; do { v1 = (float)rnd.NextDouble(); v2 = (float)rnd.NextDouble(); } while (v1+v2 > 1); p = ((Vector3)(node.GetVertex(1)-node.GetVertex(0)))*v1 + ((Vector3)(node.GetVertex(2)-node.GetVertex(0)))*v2 + (Vector3)node.GetVertex(0); } else { var gnode = nodes[v] as GridNode; if (gnode != null) { var gg = GridNode.GetGridGraph (gnode.GraphIndex); var v1 = (float)rnd.NextDouble(); var v2 = (float)rnd.NextDouble(); p = (Vector3)gnode.position + new Vector3(v1 - 0.5f, 0, v2 - 0.5f) * gg.nodeSize; } else { //Point nodes have no area, so we break directly instead pts.Add ((Vector3)nodes[v].position); break; } } // Test if it is some distance away from the other points if (clearanceRadius > 0) { for (var j=0;j<pts.Count;j++) { if ((pts[j]-p).sqrMagnitude < clearanceRadius) { worked = false; break; } } } if (worked) { pts.Add (p); break; } else { testCount++; } } } ListPool<float>.Release(accs); } else { for (var i=0;i<count;i++) { pts.Add ((Vector3)nodes[rnd.Next (nodes.Count)].position); } } return pts; }
public override Vector3 RandomPointOnSurface() { GridGraph gg = GridNode.GetGridGraph(GraphIndex); return((Vector3)position + new Vector3(Random.value - 0.5f, 0, Random.value - 0.5f) * gg.nodeSize); }
public override float SurfaceArea() { GridGraph gg = GridNode.GetGridGraph(GraphIndex); return(gg.nodeSize * gg.nodeSize); }
// Token: 0x060025D0 RID: 9680 RVA: 0x001A6008 File Offset: 0x001A4208 public override float SurfaceArea() { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); return(gridGraph.nodeSize * gridGraph.nodeSize); }
public override void Open(Path path, PathNode pathNode, PathHandler handler) { GridGraph gridGraph = GridNode.GetGridGraph(base.GraphIndex); ushort pathID = handler.PathID; int[] neighbourOffsets = gridGraph.neighbourOffsets; uint[] neighbourCosts = gridGraph.neighbourCosts; GridNode[] nodes = gridGraph.nodes; for (int i = 0; i < 8; i++) { if (this.GetConnectionInternal(i)) { GridNode gridNode = nodes[this.nodeInGridIndex + neighbourOffsets[i]]; if (path.CanTraverse(gridNode)) { PathNode pathNode2 = handler.GetPathNode(gridNode); uint num = neighbourCosts[i]; if (pathNode2.pathID != pathID) { pathNode2.parent = pathNode; pathNode2.pathID = pathID; pathNode2.cost = num; pathNode2.H = path.CalculateHScore(gridNode); gridNode.UpdateG(path, pathNode2); handler.PushNode(pathNode2); } else if (pathNode.G + num + path.GetTraversalCost(gridNode) < pathNode2.G) { pathNode2.cost = num; pathNode2.parent = pathNode; gridNode.UpdateRecursiveG(path, pathNode2, handler); } else if (pathNode2.G + num + path.GetTraversalCost(this) < pathNode.G) { pathNode.parent = pathNode2; pathNode.cost = num; this.UpdateRecursiveG(path, pathNode, handler); } } } } if (this.connections != null) { for (int j = 0; j < this.connections.Length; j++) { GraphNode graphNode = this.connections[j]; if (path.CanTraverse(graphNode)) { PathNode pathNode3 = handler.GetPathNode(graphNode); uint num2 = this.connectionCosts[j]; if (pathNode3.pathID != pathID) { pathNode3.parent = pathNode; pathNode3.pathID = pathID; pathNode3.cost = num2; pathNode3.H = path.CalculateHScore(graphNode); graphNode.UpdateG(path, pathNode3); handler.PushNode(pathNode3); } else if (pathNode.G + num2 + path.GetTraversalCost(graphNode) < pathNode3.G) { pathNode3.cost = num2; pathNode3.parent = pathNode; graphNode.UpdateRecursiveG(path, pathNode3, handler); } else if (pathNode3.G + num2 + path.GetTraversalCost(this) < pathNode.G && graphNode.ContainsConnection(this)) { pathNode.parent = pathNode3; pathNode.cost = num2; this.UpdateRecursiveG(path, pathNode, handler); } } } } }
/** Returns randomly selected points on the specified nodes with each point being separated by \a clearanceRadius from each other. * Selecting points ON the nodes only works for TriangleMeshNode (used by Recast Graph and Navmesh Graph) and GridNode (used by GridGraph). * For other node types, only the positions of the nodes will be used. * * clearanceRadius will be reduced if no valid points can be found. */ public static List <Vector3> GetPointsOnNodes(List <GraphNode> nodes, int count, float clearanceRadius = 0) { if (nodes == null) { throw new System.ArgumentNullException("nodes"); } if (nodes.Count == 0) { throw new System.ArgumentException("no nodes passed"); } var rnd = new System.Random(); List <Vector3> pts = ListPool <Vector3> .Claim(count); // Square clearanceRadius *= clearanceRadius; if (nodes[0] is TriangleMeshNode #if !ASTAR_NO_GRID_GRAPH || nodes[0] is GridNode #endif ) { // Accumulated area of all nodes List <float> accs = ListPool <float> .Claim(nodes.Count); // Total area of all nodes so far float tot = 0; for (int i = 0; i < nodes.Count; i++) { var tnode = nodes[i] as TriangleMeshNode; if (tnode != null) { /** \bug Doesn't this need to be divided by 2? */ float a = System.Math.Abs(VectorMath.SignedTriangleAreaTimes2XZ(tnode.GetVertex(0), tnode.GetVertex(1), tnode.GetVertex(2))); tot += a; accs.Add(tot); } #if !ASTAR_NO_GRID_GRAPH else { var gnode = nodes[i] as GridNode; if (gnode != null) { GridGraph gg = GridNode.GetGridGraph(gnode.GraphIndex); float a = gg.nodeSize * gg.nodeSize; tot += a; accs.Add(tot); } else { accs.Add(tot); } } #endif } for (int i = 0; i < count; i++) { //Pick point int testCount = 0; int testLimit = 10; bool worked = false; while (!worked) { worked = true; //If no valid points can be found, progressively lower the clearance radius until such a point is found if (testCount >= testLimit) { clearanceRadius *= 0.8f; testLimit += 10; if (testLimit > 100) { clearanceRadius = 0; } } // Pick a random node among the ones in the list weighted by their area float tg = (float)rnd.NextDouble() * tot; int v = accs.BinarySearch(tg); if (v < 0) { v = ~v; } if (v >= nodes.Count) { // This shouldn't happen, due to NextDouble being smaller than 1... but I don't trust floating point arithmetic. worked = false; continue; } var node = nodes[v] as TriangleMeshNode; Vector3 p; if (node != null) { // Find a random point inside the triangle // This generates uniformly distributed trilinear coordinates // See http://mathworld.wolfram.com/TrianglePointPicking.html float v1; float v2; do { v1 = (float)rnd.NextDouble(); v2 = (float)rnd.NextDouble(); } while (v1 + v2 > 1); // Pick the point corresponding to the trilinear coordinate p = ((Vector3)(node.GetVertex(1) - node.GetVertex(0))) * v1 + ((Vector3)(node.GetVertex(2) - node.GetVertex(0))) * v2 + (Vector3)node.GetVertex(0); } else { #if !ASTAR_NO_GRID_GRAPH var gnode = nodes[v] as GridNode; if (gnode != null) { GridGraph gg = GridNode.GetGridGraph(gnode.GraphIndex); float v1 = (float)rnd.NextDouble(); float v2 = (float)rnd.NextDouble(); p = (Vector3)gnode.position + new Vector3(v1 - 0.5f, 0, v2 - 0.5f) * gg.nodeSize; } else #endif { //Point nodes have no area, so we break directly instead pts.Add((Vector3)nodes[v].position); break; } } // Test if it is some distance away from the other points if (clearanceRadius > 0) { for (int j = 0; j < pts.Count; j++) { if ((pts[j] - p).sqrMagnitude < clearanceRadius) { worked = false; break; } } } if (worked) { pts.Add(p); break; } testCount++; } } ListPool <float> .Release(accs); } else { for (int i = 0; i < count; i++) { pts.Add((Vector3)nodes[rnd.Next(nodes.Count)].position); } } return(pts); }