/** Updates shortcuts to the first graph of different types. * Hard coding references to some graph types is not really a good thing imo. I want to keep it dynamic and flexible. * But these references ease the use of the system, so I decided to keep them. It is the only reference to specific graph types in the pathfinding core.\n */ public void UpdateShortcuts() { navmesh = (NavMeshGraph)FindGraphOfType(typeof(NavMeshGraph)); #if !ASTAR_NO_GRID_GRAPH gridGraph = (GridGraph)FindGraphOfType(typeof(GridGraph)); #endif #if !ASTAR_NO_POINT_GRAPH pointGraph = (PointGraph)FindGraphOfType(typeof(PointGraph)); #endif recastGraph = (RecastGraph)FindGraphOfType(typeof(RecastGraph)); }
public static NNInfoInternal GetNearest(NavMeshGraph graph, GraphNode[] nodes, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { if ((nodes == null) || (nodes.Length == 0)) { UnityEngine.Debug.LogError("NavGraph hasn't been generated yet or does not contain any nodes"); return(new NNInfoInternal()); } if (constraint == null) { constraint = NNConstraint.None; } Int3[] vertices = graph.vertices; if (graph.bbTree == null) { return(GetNearestForce(graph, graph, position, constraint, accurateNearestNode)); } float radius = ((graph.bbTree.Size.width + graph.bbTree.Size.height) * 0.5f) * 0.02f; NNInfoInternal internal2 = graph.bbTree.QueryCircle(position, radius, constraint); if (internal2.node == null) { for (int i = 1; i <= 8; i++) { internal2 = graph.bbTree.QueryCircle(position, (i * i) * radius, constraint); if ((internal2.node != null) || ((((i - 1) * (i - 1)) * radius) > (AstarPath.active.maxNearestNodeDistance * 2f))) { break; } } } if (internal2.node != null) { internal2.clampedPosition = ClosestPointOnNode(internal2.node as TriangleMeshNode, vertices, position); } if (internal2.constrainedNode != null) { if (constraint.constrainDistance) { Vector3 vector = ((Vector3)internal2.constrainedNode.position) - position; if (vector.sqrMagnitude > AstarPath.active.maxNearestNodeDistanceSqr) { internal2.constrainedNode = null; return(internal2); } } internal2.constClampedPosition = ClosestPointOnNode(internal2.constrainedNode as TriangleMeshNode, vertices, position); } return(internal2); }
public static void RebuildBBTree(NavMeshGraph graph) { BBTree bBTree = graph.bbTree; if (bBTree == null) { bBTree = new BBTree(graph); } bBTree.Clear(); TriangleMeshNode[] triNodes = graph.TriNodes; for (int i = triNodes.Length - 1; i >= 0; i--) { bBTree.Insert(triNodes[i]); } graph.bbTree = bBTree; }
void IUpdatableGraph.UpdateArea(GraphUpdateObject guo) { IntRect touchingTiles = base.GetTouchingTiles(guo.bounds); if (!guo.updatePhysics) { for (int i = touchingTiles.ymin; i <= touchingTiles.ymax; i++) { for (int j = touchingTiles.xmin; j <= touchingTiles.xmax; j++) { NavmeshTile graph = this.tiles[i * this.tileXCount + j]; NavMeshGraph.UpdateArea(guo, graph); } } return; } Voxelize voxelize = this.globalVox; if (voxelize == null) { throw new InvalidOperationException("No Voxelizer object. UpdateAreaInit should have been called before this function."); } for (int k = touchingTiles.xmin; k <= touchingTiles.xmax; k++) { for (int l = touchingTiles.ymin; l <= touchingTiles.ymax; l++) { this.stagingTiles.Add(this.BuildTileMesh(voxelize, k, l, 0)); } } uint graphIndex = (uint)AstarPath.active.data.GetGraphIndex(this); for (int m = 0; m < this.stagingTiles.Count; m++) { NavmeshTile navmeshTile = this.stagingTiles[m]; GraphNode[] nodes = navmeshTile.nodes; for (int n = 0; n < nodes.Length; n++) { nodes[n].GraphIndex = graphIndex; } } for (int num = 0; num < voxelize.inputMeshes.Count; num++) { voxelize.inputMeshes[num].Pool(); } ListPool <RasterizationMesh> .Release(voxelize.inputMeshes); voxelize.inputMeshes = null; }
public static NNInfo GetNearest(NavMeshGraph graph, GraphNode[] nodes, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { if (nodes == null || nodes.Length == 0) { Debug.LogError("NavGraph hasn't been generated yet or does not contain any nodes"); return(new NNInfo()); } if (constraint == null) { constraint = NNConstraint.None; } return(GetNearestForceBoth(graph, graph, position, NNConstraint.None, accurateNearestNode)); }
public static NNInfo GetNearest(NavMeshGraph graph, GraphNode[] nodes, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { if (nodes == null || nodes.Length == 0) { Debug.LogError("NavGraph hasn't been generated yet or does not contain any nodes"); return(default(NNInfo)); } if (constraint == null) { constraint = NNConstraint.None; } Int3[] vertices = graph.vertices; if (graph.bbTree == null) { return(NavMeshGraph.GetNearestForce(graph, graph, position, constraint, accurateNearestNode)); } float num = (graph.bbTree.Size.width + graph.bbTree.Size.height) * 0.5f * 0.02f; NNInfo result = graph.bbTree.QueryCircle(position, num, constraint); if (result.node == null) { for (int i = 1; i <= 8; i++) { result = graph.bbTree.QueryCircle(position, (float)(i * i) * num, constraint); if (result.node != null || (float)((i - 1) * (i - 1)) * num > AstarPath.active.maxNearestNodeDistance * 2f) { break; } } } if (result.node != null) { result.clampedPosition = NavMeshGraph.ClosestPointOnNode(result.node as TriangleMeshNode, vertices, position); } if (result.constrainedNode != null) { if (constraint.constrainDistance && ((Vector3)result.constrainedNode.position - position).sqrMagnitude > AstarPath.active.maxNearestNodeDistanceSqr) { result.constrainedNode = null; } else { result.constClampedPosition = NavMeshGraph.ClosestPointOnNode(result.constrainedNode as TriangleMeshNode, vertices, position); } } return(result); }
/** Rebuilds the BBTree on a NavGraph. * \astarpro * \see NavMeshGraph.bbTree */ public static void RebuildBBTree(NavMeshGraph graph) { //Build Axis Aligned Bounding Box Tree BBTree bbTree = graph.bbTree; bbTree = bbTree ?? new BBTree(graph); bbTree.Clear(); var nodes = graph.nodes; for (int i = nodes.Length - 1; i >= 0; i--) { bbTree.Insert(nodes[i]); } graph.bbTree = bbTree; }
public bool NodeIntersectsCircle(MeshNode node, Vector3 p, float radius) { if (NavMeshGraph.ContainsPoint(node, p, graph.vertices)) { return(true); } Int3[] vertices = graph.vertices; float r2 = radius * radius; Vector3 p1 = (Vector3)vertices[node[0]], p2 = (Vector3)vertices[node[1]], p3 = (Vector3)vertices[node[2]]; p1.y = p.y; p2.y = p.y; p3.y = p.y; return(Mathfx.DistancePointSegmentStrict(p1, p2, p) < r2 || Mathfx.DistancePointSegmentStrict(p2, p3, p) < r2 || Mathfx.DistancePointSegmentStrict(p3, p1, p) < r2); }
public void SearchBox(BBTreeBox box, Vector3 p, NNConstraint constraint, ref NNInfo nnInfo) //, int intendentLevel = 0) { { if (box.node != null) { //Leaf node if (NavMeshGraph.ContainsPoint(box.node, p, graph.vertices)) { //Update the NNInfo if (nnInfo.node == null) { nnInfo.node = box.node; } else if (Mathf.Abs(((Vector3)box.node.position).y - p.y) < Mathf.Abs(((Vector3)nnInfo.node.position).y - p.y)) { nnInfo.node = box.node; } if (constraint.Suitable(box.node)) { if (nnInfo.constrainedNode == null) { nnInfo.constrainedNode = box.node; } else if (Mathf.Abs(box.node.position.y - p.y) < Mathf.Abs(nnInfo.constrainedNode.position.y - p.y)) { nnInfo.constrainedNode = box.node; } } } return; } //Search children if (RectContains(box.c1.rect, p)) { SearchBox(box.c1, p, constraint, ref nnInfo); } if (RectContains(box.c2.rect, p)) { SearchBox(box.c2, p, constraint, ref nnInfo); } }
//These functions are for serialization, the static ones are there so other graphs using mesh nodes can serialize them more easily public static byte[] SerializeMeshNodes(NavMeshGraph graph, GraphNode[] nodes) { System.IO.MemoryStream mem = new System.IO.MemoryStream(); System.IO.BinaryWriter stream = new System.IO.BinaryWriter(mem); for (int i = 0; i < nodes.Length; i++) { TriangleMeshNode node = nodes[i] as TriangleMeshNode; if (node == null) { Debug.LogError("Serialization Error : Couldn't cast the node to the appropriate type - NavMeshGenerator. Omitting node data."); return(null); } stream.Write(node.v0); stream.Write(node.v1); stream.Write(node.v2); } Int3[] vertices = graph.vertices; if (vertices == null) { vertices = new Int3[0]; } stream.Write(vertices.Length); for (int i = 0; i < vertices.Length; i++) { stream.Write(vertices[i].x); stream.Write(vertices[i].y); stream.Write(vertices[i].z); } stream.Close(); return(mem.ToArray()); }
//public GameObject meshRenderer; public override void OnInspectorGUI(NavGraph target) { NavMeshGraph graph = target as NavMeshGraph; /* #if UNITY_3_3 * graph.sourceMesh = EditorGUILayout.ObjectField ("Source Mesh",graph.sourceMesh,typeof(Mesh)) as Mesh; #else * graph.sourceMesh = EditorGUILayout.ObjectField ("Source Mesh",graph.sourceMesh,typeof(Mesh), true) as Mesh; #endif */ graph.sourceMesh = ObjectField("Source Mesh", graph.sourceMesh, typeof(Mesh), false) as Mesh; #if UNITY_LE_4_3 EditorGUIUtility.LookLikeControls(); EditorGUILayoutx.BeginIndent(); #endif graph.offset = EditorGUILayout.Vector3Field("Offset", graph.offset); #if UNITY_LE_4_3 EditorGUILayoutx.EndIndent(); EditorGUILayoutx.BeginIndent(); #endif graph.rotation = EditorGUILayout.Vector3Field("Rotation", graph.rotation); #if UNITY_LE_4_3 EditorGUILayoutx.EndIndent(); EditorGUIUtility.LookLikeInspector(); #endif graph.scale = EditorGUILayout.FloatField(new GUIContent("Scale", "Scale of the mesh"), graph.scale); graph.scale = (graph.scale <0.01F && graph.scale> -0.01F) ? (graph.scale >= 0 ? 0.01F : -0.01F) : graph.scale; graph.accurateNearestNode = EditorGUILayout.Toggle(new GUIContent("Accurate Nearest Node Queries", "More accurate nearest node queries. See docs for more info"), graph.accurateNearestNode); }
public void UpdateShortcuts() { this.navmesh = (NavMeshGraph)this.FindGraphOfType(typeof(NavMeshGraph)); this.recastGraph = (RecastGraph)this.FindGraphOfType(typeof(RecastGraph)); }
/** Rebuilds the BBTree on a NavGraph. * \astarpro * \see NavMeshGraph.bbTree */ public static void RebuildBBTree(NavMeshGraph graph) { //BBTrees is a A* Pathfinding Project Pro only feature - The Pro version can be bought in the Unity Asset Store or on arongranberg.com }
// Token: 0x0600256F RID: 9583 RVA: 0x001A2E2C File Offset: 0x001A102C void IUpdatableGraph.UpdateArea(GraphUpdateObject o) { NavMeshGraph.UpdateArea(o, this); }
/** Updates shortcuts to the first graph of different types. * Hard coding references to some graph types is not really a good thing imo. I want to keep it dynamic and flexible. * But these references ease the use of the system, so I decided to keep them. It is the only reference to specific graph types in the pathfinding core.\n */ public void UpdateShortcuts() { navmesh = (NavMeshGraph)FindGraphOfType(typeof(NavMeshGraph)); gridGraph = (GridGraph)FindGraphOfType(typeof(GridGraph)); pointGraph = (PointGraph)FindGraphOfType(typeof(PointGraph)); }
public static NNInfo GetNearest (NavMeshGraph graph, GraphNode[] nodes, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { if (nodes == null || nodes.Length == 0) { Debug.LogError ("NavGraph hasn't been generated yet or does not contain any nodes"); return new NNInfo (); } if (constraint == null) constraint = NNConstraint.None; Int3[] vertices = graph.vertices; //Query BBTree if (graph.bbTree == null) { /** \todo Change method to require a navgraph */ return GetNearestForce (graph as NavGraph, graph as INavmeshHolder, position, constraint, accurateNearestNode); //Debug.LogError ("No Bounding Box Tree has been assigned"); //return new NNInfo (); } //Searches in radiuses of 0.05 - 0.2 - 0.45 ... 1.28 times the average of the width and depth of the bbTree float w = (graph.bbTree.root.rect.width + graph.bbTree.root.rect.height)*0.5F*0.02F; NNInfo query = graph.bbTree.QueryCircle (position,w,constraint);//graph.bbTree.Query (position,constraint); if (query.node == null) { for (int i=1;i<=8;i++) { query = graph.bbTree.QueryCircle (position, i*i*w, constraint); if (query.node != null || (i-1)*(i-1)*w > AstarPath.active.maxNearestNodeDistance*2) { // *2 for a margin break; } } } if (query.node != null) { query.clampedPosition = ClosestPointOnNode (query.node as TriangleMeshNode,vertices,position); } if (query.constrainedNode != null) { if (constraint.constrainDistance && ((Vector3)query.constrainedNode.position - position).sqrMagnitude > AstarPath.active.maxNearestNodeDistanceSqr) { query.constrainedNode = null; } else { query.constClampedPosition = ClosestPointOnNode (query.constrainedNode as TriangleMeshNode, vertices, position); } } return query; }
public static void DeserializeMeshNodes (NavMeshGraph graph, GraphNode[] nodes, byte[] bytes) { System.IO.MemoryStream mem = new System.IO.MemoryStream(bytes); System.IO.BinaryReader stream = new System.IO.BinaryReader(mem); for (int i=0;i<nodes.Length;i++) { TriangleMeshNode node = nodes[i] as TriangleMeshNode; if (node == null) { Debug.LogError ("Serialization Error : Couldn't cast the node to the appropriate type - NavMeshGenerator"); return; } node.v0 = stream.ReadInt32 (); node.v1 = stream.ReadInt32 (); node.v2 = stream.ReadInt32 (); } int numVertices = stream.ReadInt32 (); graph.vertices = new Int3[numVertices]; for (int i=0;i<numVertices;i++) { int x = stream.ReadInt32 (); int y = stream.ReadInt32 (); int z = stream.ReadInt32 (); graph.vertices[i] = new Int3 (x,y,z); } RebuildBBTree (graph); }
/** Rebuilds the BBTree on a NavGraph. * \astarpro * \see NavMeshGraph.bbTree */ public static void RebuildBBTree (NavMeshGraph graph) { //BBTrees is a A* Pathfinding Project Pro only feature - The Pro version can be bought in the Unity Asset Store or on arongranberg.com }
public static NNInfo GetNearest (NavMeshGraph graph, GraphNode[] nodes, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { if (nodes == null || nodes.Length == 0) { Debug.LogError ("NavGraph hasn't been generated yet or does not contain any nodes"); return new NNInfo (); } if (constraint == null) constraint = NNConstraint.None; return GetNearestForceBoth (graph,graph, position, NNConstraint.None, accurateNearestNode); }
public void SearchBoxCircle(BBTreeBox box, Vector3 p, float radius, NNConstraint constraint, ref NNInfo nnInfo) //, int intendentLevel = 0) { { if (box.node != null) { //Leaf node if (NodeIntersectsCircle(box.node, p, radius)) { //Update the NNInfo #if DEBUG Debug.DrawLine(graph.vertices[box.node[0]], graph.vertices[box.node[1]], Color.red); Debug.DrawLine(graph.vertices[box.node[1]], graph.vertices[box.node[2]], Color.red); Debug.DrawLine(graph.vertices[box.node[2]], graph.vertices[box.node[0]], Color.red); #endif Vector3 closest = NavMeshGraph.ClosestPointOnNode(box.node, graph.vertices, p); float dist = (closest - p).sqrMagnitude; if (nnInfo.node == null) { nnInfo.node = box.node; nnInfo.clampedPosition = closest; } else if (dist < (nnInfo.clampedPosition - p).sqrMagnitude) { nnInfo.node = box.node; nnInfo.clampedPosition = closest; } if (constraint.Suitable(box.node)) { if (nnInfo.constrainedNode == null) { nnInfo.constrainedNode = box.node; nnInfo.constClampedPosition = closest; } else if (dist < (nnInfo.constClampedPosition - p).sqrMagnitude) { nnInfo.constrainedNode = box.node; nnInfo.constClampedPosition = closest; } } } return; } #if DEBUG Debug.DrawLine(new Vector3(box.rect.xMin, 0, box.rect.yMin), new Vector3(box.rect.xMax, 0, box.rect.yMin), Color.white); Debug.DrawLine(new Vector3(box.rect.xMin, 0, box.rect.yMax), new Vector3(box.rect.xMax, 0, box.rect.yMax), Color.white); Debug.DrawLine(new Vector3(box.rect.xMin, 0, box.rect.yMin), new Vector3(box.rect.xMin, 0, box.rect.yMax), Color.white); Debug.DrawLine(new Vector3(box.rect.xMax, 0, box.rect.yMin), new Vector3(box.rect.xMax, 0, box.rect.yMax), Color.white); #endif //Search children if (RectIntersectsCircle(box.c1.rect, p, radius)) { SearchBoxCircle(box.c1, p, radius, constraint, ref nnInfo); } if (RectIntersectsCircle(box.c2.rect, p, radius)) { SearchBoxCircle(box.c2, p, radius, constraint, ref nnInfo); } }
/** Rebuilds the BBTree on a NavGraph. * \astarpro * \see NavMeshGraph.bbTree */ public static void RebuildBBTree (NavMeshGraph graph) { //Build Axis Aligned Bounding Box Tree BBTree bbTree = graph.bbTree; bbTree = bbTree ?? new BBTree (graph); bbTree.Clear (); var nodes = graph.nodes; for (int i=nodes.Length-1;i>=0;i--) { bbTree.Insert (nodes[i]); } graph.bbTree = bbTree; }
public NNInfo GetNearest(VInt3 position, NNConstraint constraint, GraphNode hint) { return(NavMeshGraph.GetNearest(this, this.nodes, (Vector3)position, constraint, this.accurateNearestNode)); }
public void UpdateShortcuts() { navmesh = (NavMeshGraph)FindGraphOfType (typeof(NavMeshGraph)); gridGraph = (GridGraph)FindGraphOfType (typeof(GridGraph)); listGraph = (ListGraph)FindGraphOfType (typeof(ListGraph)); }
public static NNInfo GetNearest(NavMeshGraph graph, GraphNode[] nodes, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { if (nodes == null || nodes.Length == 0) { Debug.LogError("NavGraph hasn't been generated yet or does not contain any nodes"); return(new NNInfo()); } if (constraint == null) { constraint = NNConstraint.None; } Int3[] vertices = graph.vertices; //Query BBTree if (graph.bbTree == null) { /** \todo Change method to require a navgraph */ return(GetNearestForce(graph, graph, position, constraint, accurateNearestNode)); } //Searches in radiuses of 0.05 - 0.2 - 0.45 ... 1.28 times the average of the width and depth of the bbTree float w = (graph.bbTree.Size.width + graph.bbTree.Size.height) * 0.5F * 0.02F; NNInfo query = graph.bbTree.QueryCircle(position, w, constraint); //graph.bbTree.Query (position,constraint); if (query.node == null) { for (int i = 1; i <= 8; i++) { query = graph.bbTree.QueryCircle(position, i * i * w, constraint); if (query.node != null || (i - 1) * (i - 1) * w > AstarPath.active.maxNearestNodeDistance * 2) // *2 for a margin { break; } } } if (query.node != null) { query.clampedPosition = ClosestPointOnNode(query.node as TriangleMeshNode, vertices, position); } if (query.constrainedNode != null) { if (constraint.constrainDistance && ((Vector3)query.constrainedNode.position - position).sqrMagnitude > AstarPath.active.maxNearestNodeDistanceSqr) { query.constrainedNode = null; } else { query.constClampedPosition = ClosestPointOnNode(query.constrainedNode as TriangleMeshNode, vertices, position); } } return(query); }
public override NNInfo GetNearestForce(Vector3 position, NNConstraint constraint) { return(NavMeshGraph.GetNearestForce(this, this, position, constraint, this.accurateNearestNode)); }
//These functions are for serialization, the static ones are there so other graphs using mesh nodes can serialize them more easily public static byte[] SerializeMeshNodes (NavMeshGraph graph, GraphNode[] nodes) { System.IO.MemoryStream mem = new System.IO.MemoryStream(); System.IO.BinaryWriter stream = new System.IO.BinaryWriter(mem); for (int i=0;i<nodes.Length;i++) { TriangleMeshNode node = nodes[i] as TriangleMeshNode; if (node == null) { Debug.LogError ("Serialization Error : Couldn't cast the node to the appropriate type - NavMeshGenerator. Omitting node data."); return null; } stream.Write (node.v0); stream.Write (node.v1); stream.Write (node.v2); } Int3[] vertices = graph.vertices; if (vertices == null) { vertices = new Int3[0]; } stream.Write (vertices.Length); for (int i=0;i<vertices.Length;i++) { stream.Write (vertices[i].x); stream.Write (vertices[i].y); stream.Write (vertices[i].z); } stream.Close (); return mem.ToArray(); }
public bool Linecast(Vector3 origin, Vector3 end, GraphNode hint) { GraphHitInfo graphHitInfo; return(NavMeshGraph.Linecast(this, origin, end, hint, out graphHitInfo, null)); }
/** Rebuilds the BBTree on a NavGraph. * \astarpro * \see NavMeshGraph.bbTree */ public static void RebuildBBTree (NavMeshGraph graph) { //Build Axis Aligned Bounding Box Tree NavMeshGraph meshGraph = graph as NavMeshGraph; BBTree bbTree = new BBTree (graph as INavmeshHolder); TriangleMeshNode[] nodes = meshGraph.TriNodes; for (int i=nodes.Length-1;i>=0;i--) { bbTree.Insert (nodes[i]); } meshGraph.bbTree = bbTree; }
public static bool Linecast(INavmesh graph, Vector3 tmp_origin, Vector3 tmp_end, GraphNode hint, out GraphHitInfo hit) { return(NavMeshGraph.Linecast(graph, tmp_origin, tmp_end, hint, out hit, null)); }
private void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices) { if (vectorVertices.Length == 0 || triangles.Length == 0) { originalVertices = vectorVertices; vertices = new Int3[0]; this.nodes = new TriangleMeshNode[0]; return; } vertices = new Int3[vectorVertices.Length]; int num = 0; for (int i = 0; i < vertices.Length; i++) { vertices[i] = (Int3)this.matrix.MultiplyPoint3x4(vectorVertices[i]); } Dictionary <Int3, int> dictionary = new Dictionary <Int3, int>(); int[] array = new int[vertices.Length]; for (int j = 0; j < vertices.Length; j++) { if (!dictionary.ContainsKey(vertices[j])) { array[num] = j; dictionary.Add(vertices[j], num); num++; } } for (int k = 0; k < triangles.Length; k++) { Int3 key = vertices[triangles[k]]; triangles[k] = dictionary[key]; } Int3[] array2 = vertices; vertices = new Int3[num]; originalVertices = new Vector3[num]; for (int l = 0; l < num; l++) { vertices[l] = array2[array[l]]; originalVertices[l] = vectorVertices[array[l]]; } this.nodes = new TriangleMeshNode[triangles.Length / 3]; int graphIndex = this.active.astarData.GetGraphIndex(this); for (int m = 0; m < this.nodes.Length; m++) { this.nodes[m] = new TriangleMeshNode(this.active); TriangleMeshNode triangleMeshNode = this.nodes[m]; triangleMeshNode.GraphIndex = (uint)graphIndex; triangleMeshNode.Penalty = this.initialPenalty; triangleMeshNode.Walkable = true; triangleMeshNode.v0 = triangles[m * 3]; triangleMeshNode.v1 = triangles[m * 3 + 1]; triangleMeshNode.v2 = triangles[m * 3 + 2]; if (!Polygon.IsClockwise(vertices[triangleMeshNode.v0], vertices[triangleMeshNode.v1], vertices[triangleMeshNode.v2])) { int v = triangleMeshNode.v0; triangleMeshNode.v0 = triangleMeshNode.v2; triangleMeshNode.v2 = v; } if (Polygon.IsColinear(vertices[triangleMeshNode.v0], vertices[triangleMeshNode.v1], vertices[triangleMeshNode.v2])) { Debug.DrawLine((Vector3)vertices[triangleMeshNode.v0], (Vector3)vertices[triangleMeshNode.v1], Color.red); Debug.DrawLine((Vector3)vertices[triangleMeshNode.v1], (Vector3)vertices[triangleMeshNode.v2], Color.red); Debug.DrawLine((Vector3)vertices[triangleMeshNode.v2], (Vector3)vertices[triangleMeshNode.v0], Color.red); } triangleMeshNode.UpdatePositionFromVertices(); } Dictionary <Int2, TriangleMeshNode> dictionary2 = new Dictionary <Int2, TriangleMeshNode>(); int n = 0; int num2 = 0; while (n < triangles.Length) { dictionary2[new Int2(triangles[n], triangles[n + 1])] = this.nodes[num2]; dictionary2[new Int2(triangles[n + 1], triangles[n + 2])] = this.nodes[num2]; dictionary2[new Int2(triangles[n + 2], triangles[n])] = this.nodes[num2]; num2++; n += 3; } List <MeshNode> list = new List <MeshNode>(); List <uint> list2 = new List <uint>(); int num3 = 0; int num4 = 0; while (num3 < triangles.Length) { list.Clear(); list2.Clear(); TriangleMeshNode triangleMeshNode2 = this.nodes[num4]; for (int num5 = 0; num5 < 3; num5++) { TriangleMeshNode triangleMeshNode3; if (dictionary2.TryGetValue(new Int2(triangles[num3 + (num5 + 1) % 3], triangles[num3 + num5]), out triangleMeshNode3)) { list.Add(triangleMeshNode3); list2.Add((uint)(triangleMeshNode2.position - triangleMeshNode3.position).costMagnitude); } } triangleMeshNode2.connections = list.ToArray(); triangleMeshNode2.connectionCosts = list2.ToArray(); num4++; num3 += 3; } NavMeshGraph.RebuildBBTree(this); }
/** Rebuilds the BBTree on a NavGraph. * \astarpro * \see NavMeshGraph.bbTree */ public static void RebuildBBTree (NavMeshGraph graph) { // Build Axis Aligned Bounding Box Tree BBTree bbTree = graph.bbTree; bbTree = bbTree ?? new BBTree (); bbTree.RebuildFrom(graph.nodes); graph.bbTree = bbTree; }
public void BuildFunnelCorridor(List <GraphNode> path, int startIndex, int endIndex, List <Vector3> left, List <Vector3> right) { NavMeshGraph.BuildFunnelCorridor(this, path, startIndex, endIndex, left, right); }
public override NNInfo GetNearest(Vector3 position, NNConstraint constraint, GraphNode hint) { return NavMeshGraph.GetNearest(this, this.nodes, position, constraint, this.accurateNearestNode); }
public bool Linecast(Vector3 origin, Vector3 end, GraphNode hint, out GraphHitInfo hit, List <GraphNode> trace) { return(NavMeshGraph.Linecast(this, origin, end, hint, out hit, trace)); }
public bool Linecast(VInt3 origin, VInt3 end, GraphNode hint, out GraphHitInfo hit) { return NavMeshGraph.Linecast(this, origin, end, hint, out hit, null); }
public void UpdateArea(GraphUpdateObject o) { NavMeshGraph.UpdateArea(o, this); }
private void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out VInt3[] vertices) { if (vectorVertices.Length == 0 || triangles.Length == 0) { originalVertices = vectorVertices; vertices = new VInt3[0]; this.nodes = new TriangleMeshNode[0]; return; } vertices = new VInt3[vectorVertices.Length]; int num = 0; for (int i = 0; i < vertices.Length; i++) { vertices[i] = (VInt3)this.matrix.MultiplyPoint3x4(vectorVertices[i]); } Dictionary<VInt3, int> dictionary = new Dictionary<VInt3, int>(); int[] array = new int[vertices.Length]; for (int j = 0; j < vertices.Length; j++) { if (!dictionary.ContainsKey(vertices[j])) { array[num] = j; dictionary.Add(vertices[j], num); num++; } } for (int k = 0; k < triangles.Length; k++) { VInt3 vInt = vertices[triangles[k]]; triangles[k] = dictionary.get_Item(vInt); } VInt3[] array2 = vertices; vertices = new VInt3[num]; originalVertices = new Vector3[num]; for (int l = 0; l < num; l++) { vertices[l] = array2[array[l]]; originalVertices[l] = vectorVertices[array[l]]; } this.nodes = new TriangleMeshNode[triangles.Length / 3]; int graphIndex = this.active.astarData.GetGraphIndex(this); for (int m = 0; m < this.nodes.Length; m++) { this.nodes[m] = new TriangleMeshNode(this.active); TriangleMeshNode triangleMeshNode = this.nodes[m]; triangleMeshNode.GraphIndex = (uint)graphIndex; triangleMeshNode.Penalty = this.initialPenalty; triangleMeshNode.Walkable = true; triangleMeshNode.v0 = triangles[m * 3]; triangleMeshNode.v1 = triangles[m * 3 + 1]; triangleMeshNode.v2 = triangles[m * 3 + 2]; if (!Polygon.IsClockwise(vertices[triangleMeshNode.v0], vertices[triangleMeshNode.v1], vertices[triangleMeshNode.v2])) { int v = triangleMeshNode.v0; triangleMeshNode.v0 = triangleMeshNode.v2; triangleMeshNode.v2 = v; } if (Polygon.IsColinear(vertices[triangleMeshNode.v0], vertices[triangleMeshNode.v1], vertices[triangleMeshNode.v2])) { Debug.DrawLine((Vector3)vertices[triangleMeshNode.v0], (Vector3)vertices[triangleMeshNode.v1], Color.red); Debug.DrawLine((Vector3)vertices[triangleMeshNode.v1], (Vector3)vertices[triangleMeshNode.v2], Color.red); Debug.DrawLine((Vector3)vertices[triangleMeshNode.v2], (Vector3)vertices[triangleMeshNode.v0], Color.red); } triangleMeshNode.UpdatePositionFromVertices(); } DictionaryView<VInt2, TriangleMeshNode> dictionaryView = new DictionaryView<VInt2, TriangleMeshNode>(); int n = 0; int num2 = 0; while (n < triangles.Length) { dictionaryView[new VInt2(triangles[n], triangles[n + 1])] = this.nodes[num2]; dictionaryView[new VInt2(triangles[n + 1], triangles[n + 2])] = this.nodes[num2]; dictionaryView[new VInt2(triangles[n + 2], triangles[n])] = this.nodes[num2]; num2++; n += 3; } ListLinqView<MeshNode> listLinqView = new ListLinqView<MeshNode>(); List<uint> list = new List<uint>(); int num3 = 0; int num4 = 0; int num5 = 0; while (num4 < triangles.Length) { listLinqView.Clear(); list.Clear(); TriangleMeshNode triangleMeshNode2 = this.nodes[num5]; for (int num6 = 0; num6 < 3; num6++) { TriangleMeshNode triangleMeshNode3; if (dictionaryView.TryGetValue(new VInt2(triangles[num4 + (num6 + 1) % 3], triangles[num4 + num6]), out triangleMeshNode3)) { listLinqView.Add(triangleMeshNode3); list.Add((uint)(triangleMeshNode2.position - triangleMeshNode3.position).costMagnitude); } } triangleMeshNode2.connections = listLinqView.ToArray(); triangleMeshNode2.connectionCosts = list.ToArray(); num5++; num4 += 3; } if (num3 > 0) { Debug.LogError("One or more triangles are identical to other triangles, this is not a good thing to have in a navmesh\nIncreasing the scale of the mesh might help\nNumber of triangles with error: " + num3 + "\n"); } NavMeshGraph.RebuildBBTree(this); }
public void DeSerializeNodes(Node[] nodes, AstarSerializer serializer) { NavMeshGraph.DeSerializeMeshNodes(this as INavmesh, nodes, serializer); }
/** Updates shortcuts to the first graph of different types. * Hard coding references to some graph types is not really a good thing imo. I want to keep it dynamic and flexible. * But these references ease the use of the system, so I decided to keep them. It is the only reference to specific graph types in the pathfinding core.\n */ public void UpdateShortcuts () { navmesh = (NavMeshGraph)FindGraphOfType (typeof(NavMeshGraph)); #if !ASTAR_NO_GRID_GRAPH gridGraph = (GridGraph)FindGraphOfType (typeof(GridGraph)); #endif #if !ASTAR_NO_POINT_GRAPH pointGraph = (PointGraph)FindGraphOfType (typeof(PointGraph)); #endif recastGraph = (RecastGraph)FindGraphOfType (typeof(RecastGraph)); }
/** Updates shortcuts to the first graph of different types. * Hard coding references to some graph types is not really a good thing imo. I want to keep it dynamic and flexible. * But these references ease the use of the system, so I decided to keep them. It is the only reference to specific graph types in the pathfinding core.\n */ public void UpdateShortcuts () { navmesh = (NavMeshGraph)FindGraphOfType (typeof(NavMeshGraph)); gridGraph = (GridGraph)FindGraphOfType (typeof(GridGraph)); pointGraph = (PointGraph)FindGraphOfType (typeof(PointGraph)); recastGraph = (RecastGraph)FindGraphOfType (typeof(RecastGraph)); }
void IUpdatableGraph.UpdateArea(GraphUpdateObject guo) { // Figure out which tiles are affected // Expand TileBorderSizeInWorldUnits voxels in all directions to make sure // all tiles that could be affected by the update are recalculated. var affectedTiles = GetTouchingTiles(guo.bounds, TileBorderSizeInWorldUnits); if (!guo.updatePhysics) { for (int z = affectedTiles.ymin; z <= affectedTiles.ymax; z++) { for (int x = affectedTiles.xmin; x <= affectedTiles.xmax; x++) { NavmeshTile tile = tiles[z * tileXCount + x]; NavMeshGraph.UpdateArea(guo, tile); } } return; } Voxelize vox = globalVox; if (vox == null) { throw new System.InvalidOperationException("No Voxelizer object. UpdateAreaInit should have been called before this function."); } AstarProfiler.StartProfile("Build Tiles"); var allMeshes = vox.inputMeshes; // Build the new tiles // If we are updating more than one tile it makes sense to do a more optimized pass for assigning each mesh to the buckets that it intersects. var buckets = PutMeshesIntoTileBuckets(vox.inputMeshes, affectedTiles); for (int x = affectedTiles.xmin; x <= affectedTiles.xmax; x++) { for (int z = affectedTiles.ymin; z <= affectedTiles.ymax; z++) { vox.inputMeshes = buckets[(z - affectedTiles.ymin) * affectedTiles.Width + (x - affectedTiles.xmin)]; stagingTiles.Add(BuildTileMesh(vox, x, z)); } } for (int i = 0; i < buckets.Length; i++) { ListPool <RasterizationMesh> .Release(buckets[i]); } for (int i = 0; i < allMeshes.Count; i++) { allMeshes[i].Pool(); } ListPool <RasterizationMesh> .Release(ref allMeshes); vox.inputMeshes = null; uint graphIndex = (uint)AstarPath.active.data.GetGraphIndex(this); // Set the correct graph index for (int i = 0; i < stagingTiles.Count; i++) { NavmeshTile tile = stagingTiles[i]; GraphNode[] nodes = tile.nodes; for (int j = 0; j < nodes.Length; j++) { nodes[j].GraphIndex = graphIndex; } } AstarProfiler.EndProfile("Build Tiles"); }