public static void UpdateArea (GraphUpdateObject o, INavmesh graph) { //System.DateTime startTime = System.DateTime.UtcNow; Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect (bounds.min.x,bounds.min.z,bounds.max.x,bounds.max.z); IntRect r2 = new IntRect( Mathf.FloorToInt(bounds.min.x*Int3.Precision), Mathf.FloorToInt(bounds.min.z*Int3.Precision), Mathf.FloorToInt(bounds.max.x*Int3.Precision), Mathf.FloorToInt(bounds.max.z*Int3.Precision) ); /*Vector3 a = new Vector3 (r.xMin,0,r.yMin);// -1 -1 Vector3 b = new Vector3 (r.xMin,0,r.yMax);// -1 1 Vector3 c = new Vector3 (r.xMax,0,r.yMin);// 1 -1 Vector3 d = new Vector3 (r.xMax,0,r.yMax);// 1 1 */ Int3 a = new Int3(r2.xmin,0,r2.ymin); Int3 b = new Int3(r2.xmin,0,r2.ymax); Int3 c = new Int3(r2.xmax,0,r2.ymin); Int3 d = new Int3(r2.xmax,0,r2.ymax); Int3 ia = (Int3)a; Int3 ib = (Int3)b; Int3 ic = (Int3)c; Int3 id = (Int3)d; #if ASTARDEBUG Debug.DrawLine (a,b,Color.white); Debug.DrawLine (a,c,Color.white); Debug.DrawLine (c,d,Color.white); Debug.DrawLine (d,b,Color.white); #endif //for (int i=0;i<nodes.Length;i++) { graph.GetNodes (delegate (GraphNode _node) { TriangleMeshNode node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v=0;v<3;v++) { Int3 p = node.GetVertex(v); Vector3 vert = (Vector3)p; //Vector2 vert2D = new Vector2 (vert.x,vert.z); if (r2.Contains (p.x,p.z)) { //Debug.DrawRay (vert,Vector3.up*10,Color.yellow); inside = true; break; } if (vert.x < r.xMin) allLeft++; if (vert.x > r.xMax) allRight++; if (vert.z < r.yMin) allTop++; if (vert.z > r.yMax) allBottom++; //if (!bounds.Contains (node[v]) { // inside = false; // break; //} } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return true; } } //Debug.DrawLine ((Vector3)node.GetVertex(0),(Vector3)node.GetVertex(1),Color.yellow); //Debug.DrawLine ((Vector3)node.GetVertex(1),(Vector3)node.GetVertex(2),Color.yellow); //Debug.DrawLine ((Vector3)node.GetVertex(2),(Vector3)node.GetVertex(0),Color.yellow); for (int v=0;v<3;v++) { int v2 = v > 1 ? 0 : v+1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (Polygon.Intersects (a,b,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (a,c,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (c,d,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (d,b,vert1,vert2)) { inside = true; break; } } if (node.ContainsPoint (ia) || node.ContainsPoint (ib) || node.ContainsPoint (ic) || node.ContainsPoint (id)) { inside = true; } if (!inside) { return true; } o.WillUpdateNode(node); o.Apply (node); /*Debug.DrawLine ((Vector3)node.GetVertex(0),(Vector3)node.GetVertex(1),Color.blue); Debug.DrawLine ((Vector3)node.GetVertex(1),(Vector3)node.GetVertex(2),Color.blue); Debug.DrawLine ((Vector3)node.GetVertex(2),(Vector3)node.GetVertex(0),Color.blue); Debug.Break ();*/ return true; }); //System.DateTime endTime = System.DateTime.UtcNow; //float theTime = (endTime-startTime).Ticks*0.0001F; //Debug.Log ("Intersecting bounds with navmesh took "+theTime.ToString ("0.000")+" ms"); }
public static void UpdateArea (GraphUpdateObject o, INavmesh graph) { Bounds bounds = o.bounds; // Bounding rectangle with floating point coordinates Rect r = Rect.MinMaxRect (bounds.min.x,bounds.min.z,bounds.max.x,bounds.max.z); // Bounding rectangle with int coordinates var r2 = new IntRect( Mathf.FloorToInt(bounds.min.x*Int3.Precision), Mathf.FloorToInt(bounds.min.z*Int3.Precision), Mathf.FloorToInt(bounds.max.x*Int3.Precision), Mathf.FloorToInt(bounds.max.z*Int3.Precision) ); // Corners of the bounding rectangle var a = new Int3(r2.xmin,0,r2.ymin); var b = new Int3(r2.xmin,0,r2.ymax); var c = new Int3(r2.xmax,0,r2.ymin); var d = new Int3(r2.xmax,0,r2.ymax); var ymin = ((Int3)bounds.min).y; var ymax = ((Int3)bounds.max).y; // Loop through all nodes graph.GetNodes (_node => { var node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; // Check bounding box rect in XZ plane for (int v=0;v<3;v++) { Int3 p = node.GetVertex(v); var vert = (Vector3)p; if (r2.Contains (p.x,p.z)) { inside = true; break; } if (vert.x < r.xMin) allLeft++; if (vert.x > r.xMax) allRight++; if (vert.z < r.yMin) allTop++; if (vert.z > r.yMax) allBottom++; } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return true; } } // Check if the polygon edges intersect the bounding rect for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v+1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (Polygon.Intersects (a,b,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (a,c,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (c,d,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (d,b,vert1,vert2)) { inside = true; break; } } // Check if the node contains any corner of the bounding rect if (inside || node.ContainsPoint (a) || node.ContainsPoint (b) || node.ContainsPoint (c) || node.ContainsPoint (d)) { inside = true; } if (!inside) { return true; } int allAbove = 0; int allBelow = 0; // Check y coordinate for (int v = 0; v < 3; v++) { Int3 p = node.GetVertex(v); var vert = (Vector3)p; if (vert.y < ymin) allBelow++; if (vert.y > ymax) allAbove++; } // Polygon is either completely above the bounding box or completely below it if (allBelow == 3 || allAbove == 3) return true; // Triangle is inside the bounding box! // Update it! o.WillUpdateNode(node); o.Apply (node); return true; }); }
public static void UpdateArea (GraphUpdateObject o, INavmesh graph) { //System.DateTime startTime = System.DateTime.UtcNow; Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect (bounds.min.x,bounds.min.z,bounds.max.x,bounds.max.z); var r2 = new IntRect( Mathf.FloorToInt(bounds.min.x*Int3.Precision), Mathf.FloorToInt(bounds.min.z*Int3.Precision), Mathf.FloorToInt(bounds.max.x*Int3.Precision), Mathf.FloorToInt(bounds.max.z*Int3.Precision) ); var a = new Int3(r2.xmin,0,r2.ymin); var b = new Int3(r2.xmin,0,r2.ymax); var c = new Int3(r2.xmax,0,r2.ymin); var d = new Int3(r2.xmax,0,r2.ymax); graph.GetNodes (_node => { var node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v=0;v<3;v++) { Int3 p = node.GetVertex(v); var vert = (Vector3)p; if (r2.Contains (p.x,p.z)) { inside = true; break; } if (vert.x < r.xMin) allLeft++; if (vert.x > r.xMax) allRight++; if (vert.z < r.yMin) allTop++; if (vert.z > r.yMax) allBottom++; } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return true; } } for (int v=0;v<3;v++) { int v2 = v > 1 ? 0 : v+1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (Polygon.Intersects (a,b,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (a,c,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (c,d,vert1,vert2)) { inside = true; break; } if (Polygon.Intersects (d,b,vert1,vert2)) { inside = true; break; } } if (node.ContainsPoint (a) || node.ContainsPoint (b) || node.ContainsPoint (c) || node.ContainsPoint (d)) { inside = true; } if (!inside) { return true; } o.WillUpdateNode(node); o.Apply (node); return true; }); }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { //System.DateTime startTime = System.DateTime.UtcNow; Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); IntRect r2 = new IntRect( Mathf.FloorToInt(bounds.min.x * Int3.Precision), Mathf.FloorToInt(bounds.min.z * Int3.Precision), Mathf.FloorToInt(bounds.max.x * Int3.Precision), Mathf.FloorToInt(bounds.max.z * Int3.Precision) ); /*Vector3 a = new Vector3 (r.xMin,0,r.yMin);// -1 -1 * Vector3 b = new Vector3 (r.xMin,0,r.yMax);// -1 1 * Vector3 c = new Vector3 (r.xMax,0,r.yMin);// 1 -1 * Vector3 d = new Vector3 (r.xMax,0,r.yMax);// 1 1 */ Int3 a = new Int3(r2.xmin, 0, r2.ymin); Int3 b = new Int3(r2.xmin, 0, r2.ymax); Int3 c = new Int3(r2.xmax, 0, r2.ymin); Int3 d = new Int3(r2.xmax, 0, r2.ymax); Int3 ia = (Int3)a; Int3 ib = (Int3)b; Int3 ic = (Int3)c; Int3 id = (Int3)d; //for (int i=0;i<nodes.Length;i++) { graph.GetNodes(delegate(GraphNode _node) { TriangleMeshNode node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v = 0; v < 3; v++) { Int3 p = node.GetVertex(v); Vector3 vert = (Vector3)p; //Vector2 vert2D = new Vector2 (vert.x,vert.z); if (r2.Contains(p.x, p.z)) { //Debug.DrawRay (vert,Vector3.up*10,Color.yellow); inside = true; break; } if (vert.x < r.xMin) { allLeft++; } if (vert.x > r.xMax) { allRight++; } if (vert.z < r.yMin) { allTop++; } if (vert.z > r.yMax) { allBottom++; } //if (!bounds.Contains (node[v]) { // inside = false; // break; //} } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return(true); } } //Debug.DrawLine ((Vector3)node.GetVertex(0),(Vector3)node.GetVertex(1),Color.yellow); //Debug.DrawLine ((Vector3)node.GetVertex(1),(Vector3)node.GetVertex(2),Color.yellow); //Debug.DrawLine ((Vector3)node.GetVertex(2),(Vector3)node.GetVertex(0),Color.yellow); for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v + 1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (Polygon.Intersects(a, b, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(a, c, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(c, d, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(d, b, vert1, vert2)) { inside = true; break; } } if (node.ContainsPoint(ia) || node.ContainsPoint(ib) || node.ContainsPoint(ic) || node.ContainsPoint(id)) { inside = true; } if (!inside) { return(true); } o.WillUpdateNode(node); o.Apply(node); /*Debug.DrawLine ((Vector3)node.GetVertex(0),(Vector3)node.GetVertex(1),Color.blue); * Debug.DrawLine ((Vector3)node.GetVertex(1),(Vector3)node.GetVertex(2),Color.blue); * Debug.DrawLine ((Vector3)node.GetVertex(2),(Vector3)node.GetVertex(0),Color.blue); * Debug.Break ();*/ return(true); }); //System.DateTime endTime = System.DateTime.UtcNow; //float theTime = (endTime-startTime).Ticks*0.0001F; //Debug.Log ("Intersecting bounds with navmesh took "+theTime.ToString ("0.000")+" ms"); }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { Bounds bounds = o.bounds; // Bounding rectangle with floating point coordinates Rect r = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); // Bounding rectangle with int coordinates var r2 = new IntRect( Mathf.FloorToInt(bounds.min.x * Int3.Precision), Mathf.FloorToInt(bounds.min.z * Int3.Precision), Mathf.FloorToInt(bounds.max.x * Int3.Precision), Mathf.FloorToInt(bounds.max.z * Int3.Precision) ); // Corners of the bounding rectangle var a = new Int3(r2.xmin, 0, r2.ymin); var b = new Int3(r2.xmin, 0, r2.ymax); var c = new Int3(r2.xmax, 0, r2.ymin); var d = new Int3(r2.xmax, 0, r2.ymax); var ymin = ((Int3)bounds.min).y; var ymax = ((Int3)bounds.max).y; // Loop through all nodes graph.GetNodes(_node => { var node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; // Check bounding box rect in XZ plane for (int v = 0; v < 3; v++) { Int3 p = node.GetVertex(v); var vert = (Vector3)p; if (r2.Contains(p.x, p.z)) { inside = true; break; } if (vert.x < r.xMin) { allLeft++; } if (vert.x > r.xMax) { allRight++; } if (vert.z < r.yMin) { allTop++; } if (vert.z > r.yMax) { allBottom++; } } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return(true); } } // Check if the polygon edges intersect the bounding rect for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v + 1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (VectorMath.SegmentsIntersectXZ(a, b, vert1, vert2)) { inside = true; break; } if (VectorMath.SegmentsIntersectXZ(a, c, vert1, vert2)) { inside = true; break; } if (VectorMath.SegmentsIntersectXZ(c, d, vert1, vert2)) { inside = true; break; } if (VectorMath.SegmentsIntersectXZ(d, b, vert1, vert2)) { inside = true; break; } } // Check if the node contains any corner of the bounding rect if (inside || node.ContainsPoint(a) || node.ContainsPoint(b) || node.ContainsPoint(c) || node.ContainsPoint(d)) { inside = true; } if (!inside) { return(true); } int allAbove = 0; int allBelow = 0; // Check y coordinate for (int v = 0; v < 3; v++) { Int3 p = node.GetVertex(v); if (p.y < ymin) { allBelow++; } if (p.y > ymax) { allAbove++; } } // Polygon is either completely above the bounding box or completely below it if (allBelow == 3 || allAbove == 3) { return(true); } // Triangle is inside the bounding box! // Update it! o.WillUpdateNode(node); o.Apply(node); return(true); }); }
/// <summary> /// Traces the contour of a navmesh. /// /// [Open online documentation to see images] /// /// This image is just used to illustrate the difference between chains and cycles. That it shows a grid graph is not relevant. /// [Open online documentation to see images] /// /// See: <see cref="GetContours(NavGraph)"/> /// </summary> /// <param name="navmesh">The navmesh-like object to trace. This can be a recast or navmesh graph or it could be a single tile in one such graph.</param> /// <param name="results">Will be called once for each contour with the contour as a parameter as well as a boolean indicating if the contour is a cycle or a chain (see second image).</param> public static void GetContours(INavmesh navmesh, System.Action <List <Int3>, bool> results) { // Assume 3 vertices per node var uses = new bool[3]; var outline = new Dictionary <int, int>(); var vertexPositions = new Dictionary <int, Int3>(); var hasInEdge = new HashSet <int>(); navmesh.GetNodes(_node => { var node = _node as TriangleMeshNode; uses[0] = uses[1] = uses[2] = false; if (node != null) { // Find out which edges are shared with other nodes for (int j = 0; j < node.connections.Length; j++) { var other = node.connections[j].node as TriangleMeshNode; // Not necessarily a TriangleMeshNode if (other != null) { int a = node.SharedEdge(other); if (a != -1) { uses[a] = true; } } } // Loop through all edges on the node for (int j = 0; j < 3; j++) { // The edge is not shared with any other node // I.e it is an exterior edge on the mesh if (!uses[j]) { var i1 = j; var i2 = (j + 1) % node.GetVertexCount(); outline[node.GetVertexIndex(i1)] = node.GetVertexIndex(i2); hasInEdge.Add(node.GetVertexIndex(i2)); vertexPositions[node.GetVertexIndex(i1)] = node.GetVertex(i1); vertexPositions[node.GetVertexIndex(i2)] = node.GetVertex(i2); } } } }); Polygon.TraceContours(outline, hasInEdge, (chain, cycle) => { List <Int3> vertices = ListPool <Int3> .Claim(); for (int i = 0; i < chain.Count; i++) { vertices.Add(vertexPositions[chain[i]]); } results(vertices, cycle); }); }
/** Adds obstacles for a graph */ public void AddGraphObstacles(Pathfinding.RVO.Simulator sim, INavmesh ng) { if (obstacles.Count > 0 && lastSim != null && lastSim != sim) { Debug.LogError("Simulator has changed but some old obstacles are still added for the previous simulator. Deleting previous obstacles."); RemoveObstacles(); } // Remember which simulator these obstacles were added to lastSim = sim; // Assume less than 20 vertices per node (actually assumes 3, but I will change that some day) var uses = new int[20]; var outline = new Dictionary <int, int>(); var vertexPositions = new Dictionary <int, Int3>(); var hasInEdge = new HashSet <int>(); ng.GetNodes(_node => { var node = _node as TriangleMeshNode; uses[0] = uses[1] = uses[2] = 0; if (node != null) { // Find out which edges are shared with other nodes for (int j = 0; j < node.connections.Length; j++) { var other = node.connections[j] as TriangleMeshNode; // Not necessarily a TriangleMeshNode if (other != null) { int a = node.SharedEdge(other); if (a != -1) { uses[a] = 1; } } } // Loop through all edges on the node for (int j = 0; j < 3; j++) { // The edge is not shared with any other node // I.e it is an exterior edge on the mesh if (uses[j] == 0) { var i1 = j; var i2 = (j + 1) % node.GetVertexCount(); outline[node.GetVertexIndex(i1)] = node.GetVertexIndex(i2); hasInEdge.Add(node.GetVertexIndex(i2)); vertexPositions[node.GetVertexIndex(i1)] = node.GetVertex(i1); vertexPositions[node.GetVertexIndex(i2)] = node.GetVertex(i2); } } } return(true); }); // Iterate through chains of the navmesh outline. // I.e segments of the outline that are not loops // we need to start these at the beginning of the chain. // Then iterate over all the loops of the outline. // Since they are loops, we can start at any point. for (int k = 0; k < 2; k++) { bool cycles = k == 1; foreach (int startIndex in new List <int>(outline.Keys)) { // Chains (not cycles) need to start at the start of the chain // Cycles can start at any point if (!cycles && hasInEdge.Contains(startIndex)) { continue; } var index = startIndex; var obstacleVertices = new List <Vector3>(); obstacleVertices.Add((Vector3)vertexPositions[index]); while (outline.ContainsKey(index)) { var next = outline[index]; outline.Remove(index); var v = (Vector3)vertexPositions[next]; obstacleVertices.Add(v); if (next == startIndex) { break; } index = next; } if (obstacleVertices.Count > 1) { // TODO: Add layer sim.AddObstacle(obstacleVertices.ToArray(), wallHeight, cycles); } } } }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); IntRect r2 = new IntRect(Mathf.FloorToInt(bounds.min.x * 1000f), Mathf.FloorToInt(bounds.min.z * 1000f), Mathf.FloorToInt(bounds.max.x * 1000f), Mathf.FloorToInt(bounds.max.z * 1000f)); Int3 a = new Int3(r2.xmin, 0, r2.ymin); Int3 b = new Int3(r2.xmin, 0, r2.ymax); Int3 c = new Int3(r2.xmax, 0, r2.ymin); Int3 d = new Int3(r2.xmax, 0, r2.ymax); int ymin = ((Int3)bounds.min).y; int ymax = ((Int3)bounds.max).y; graph.GetNodes(delegate(GraphNode _node) { TriangleMeshNode triangleMeshNode = _node as TriangleMeshNode; bool flag = false; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; for (int i = 0; i < 3; i++) { Int3 vertex = triangleMeshNode.GetVertex(i); Vector3 vector = (Vector3)vertex; if (r2.Contains(vertex.x, vertex.z)) { flag = true; break; } if (vector.x < r.xMin) { num++; } if (vector.x > r.xMax) { num2++; } if (vector.z < r.yMin) { num3++; } if (vector.z > r.yMax) { num4++; } } if (!flag && (num == 3 || num2 == 3 || num3 == 3 || num4 == 3)) { return(true); } for (int j = 0; j < 3; j++) { int i2 = (j <= 1) ? (j + 1) : 0; Int3 vertex2 = triangleMeshNode.GetVertex(j); Int3 vertex3 = triangleMeshNode.GetVertex(i2); if (VectorMath.SegmentsIntersectXZ(a, b, vertex2, vertex3)) { flag = true; break; } if (VectorMath.SegmentsIntersectXZ(a, c, vertex2, vertex3)) { flag = true; break; } if (VectorMath.SegmentsIntersectXZ(c, d, vertex2, vertex3)) { flag = true; break; } if (VectorMath.SegmentsIntersectXZ(d, b, vertex2, vertex3)) { flag = true; break; } } if (flag || triangleMeshNode.ContainsPoint(a) || triangleMeshNode.ContainsPoint(b) || triangleMeshNode.ContainsPoint(c) || triangleMeshNode.ContainsPoint(d)) { flag = true; } if (!flag) { return(true); } int num5 = 0; int num6 = 0; for (int k = 0; k < 3; k++) { Int3 vertex4 = triangleMeshNode.GetVertex(k); if (vertex4.y < ymin) { num6++; } if (vertex4.y > ymax) { num5++; } } if (num6 == 3 || num5 == 3) { return(true); } o.WillUpdateNode(triangleMeshNode); o.Apply(triangleMeshNode); return(true); }); }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { //System.DateTime startTime = System.DateTime.UtcNow; Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); var r2 = new IntRect( Mathf.FloorToInt(bounds.min.x * Int3.Precision), Mathf.FloorToInt(bounds.min.z * Int3.Precision), Mathf.FloorToInt(bounds.max.x * Int3.Precision), Mathf.FloorToInt(bounds.max.z * Int3.Precision) ); var a = new Int3(r2.xmin, 0, r2.ymin); var b = new Int3(r2.xmin, 0, r2.ymax); var c = new Int3(r2.xmax, 0, r2.ymin); var d = new Int3(r2.xmax, 0, r2.ymax); graph.GetNodes(_node => { var node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v = 0; v < 3; v++) { Int3 p = node.GetVertex(v); var vert = (Vector3)p; if (r2.Contains(p.x, p.z)) { inside = true; break; } if (vert.x < r.xMin) { allLeft++; } if (vert.x > r.xMax) { allRight++; } if (vert.z < r.yMin) { allTop++; } if (vert.z > r.yMax) { allBottom++; } } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return(true); } } for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v + 1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (Polygon.Intersects(a, b, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(a, c, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(c, d, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(d, b, vert1, vert2)) { inside = true; break; } } if (node.ContainsPoint(a) || node.ContainsPoint(b) || node.ContainsPoint(c) || node.ContainsPoint(d)) { inside = true; } if (!inside) { return(true); } o.WillUpdateNode(node); o.Apply(node); return(true); }); }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); IntRect r2 = new IntRect(Mathf.FloorToInt(bounds.min.x * 1000f), Mathf.FloorToInt(bounds.min.z * 1000f), Mathf.FloorToInt(bounds.max.x * 1000f), Mathf.FloorToInt(bounds.max.z * 1000f)); Int3 a = new Int3(r2.xmin, 0, r2.ymin); Int3 b = new Int3(r2.xmin, 0, r2.ymax); Int3 c = new Int3(r2.xmax, 0, r2.ymin); Int3 d = new Int3(r2.xmax, 0, r2.ymax); Int3 ia = a; Int3 ib = b; Int3 ic = c; Int3 id = d; graph.GetNodes(delegate(GraphNode _node) { TriangleMeshNode triangleMeshNode = _node as TriangleMeshNode; bool flag = false; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; for (int i = 0; i < 3; i++) { Int3 vertex = triangleMeshNode.GetVertex(i); Vector3 vector = (Vector3)vertex; if (r2.Contains(vertex.x, vertex.z)) { flag = true; break; } if (vector.x < r.xMin) { num++; } if (vector.x > r.xMax) { num2++; } if (vector.z < r.yMin) { num3++; } if (vector.z > r.yMax) { num4++; } } if (!flag && (num == 3 || num2 == 3 || num3 == 3 || num4 == 3)) { return(true); } for (int j = 0; j < 3; j++) { int i2 = (j <= 1) ? (j + 1) : 0; Int3 vertex2 = triangleMeshNode.GetVertex(j); Int3 vertex3 = triangleMeshNode.GetVertex(i2); if (Polygon.Intersects(a, b, vertex2, vertex3)) { flag = true; break; } if (Polygon.Intersects(a, c, vertex2, vertex3)) { flag = true; break; } if (Polygon.Intersects(c, d, vertex2, vertex3)) { flag = true; break; } if (Polygon.Intersects(d, b, vertex2, vertex3)) { flag = true; break; } } if (triangleMeshNode.ContainsPoint(ia) || triangleMeshNode.ContainsPoint(ib) || triangleMeshNode.ContainsPoint(ic) || triangleMeshNode.ContainsPoint(id)) { flag = true; } if (!flag) { return(true); } o.WillUpdateNode(triangleMeshNode); o.Apply(triangleMeshNode); return(true); }); }
/** Adds obstacles for a graph */ public void AddGraphObstacles(Pathfinding.RVO.Simulator sim, NavGraph graph) { if (obstacles.Count > 0 && lastSim != null && lastSim != sim) { Debug.LogError("Simulator has changed but some old obstacles are still added for the previous simulator. Deleting previous obstacles."); RemoveObstacles(); } //Remember which simulator these obstacles were added to lastSim = sim; INavmesh ng = graph as INavmesh; if (ng == null) { return; } //Assume less than 20 vertices per node (actually assumes 3, but I will change that some day) int[] uses = new int[20]; ng.GetNodes(delegate(GraphNode _node) { TriangleMeshNode node = _node as TriangleMeshNode; uses[0] = uses[1] = uses[2] = 0; if (node != null) { //Find out which edges are shared with other nodes for (int j = 0; j < node.connections.Length; j++) { TriangleMeshNode other = node.connections[j] as TriangleMeshNode; // Not necessarily a TriangleMeshNode if (other != null) { int a = node.SharedEdge(other); if (a != -1) { uses[a] = 1; } } } //Loop through all edges on the node for (int j = 0; j < 3; j++) { //The edge is not shared with any other node //I.e it is an exterior edge on the mesh if (uses[j] == 0) { //The two vertices of the edge Vector3 v1 = (Vector3)node.GetVertex(j); Vector3 v2 = (Vector3)node.GetVertex((j + 1) % node.GetVertexCount()); //I think node vertices always should be clockwise, but it's good to be certain /*if (!Polygon.IsClockwise (v1,v2,(Vector3)node.GetVertex((j+2) % node.GetVertexCount()))) { * Vector3 tmp = v2; * v2 = v1; * v1 = tmp; * }*/ #if ASTARDEBUG Debug.DrawLine(v1, v2, Color.red); Debug.DrawRay(v1, Vector3.up * wallHeight, Color.red); #endif //Find out the height of the wall/obstacle we are about to add float height = System.Math.Abs(v1.y - v2.y); height = System.Math.Max(height, 5); //Add the edge as a line obstacle obstacles.Add(sim.AddObstacle(v1, v2, wallHeight)); } } } return(true); }); }
private void DrawTriangleLines() { GL.Begin(GL.LINES); for (int graphIndex = 0; graphIndex < AstarPath.active.graphs.Length; ++graphIndex) { NavGraph graph = AstarPath.active.graphs[graphIndex]; INavmesh ng = graph as INavmesh; if (null != ng) { ng.GetNodes(delegate(GraphNode _node) { // if we are only displaying one region, and this is not that region if (desplaySpecifiedRegion != DisplayAllRegions && desplaySpecifiedRegion != _node.Area) { return(true); } Color theColor = graph.NodeColor(_node, AstarPath.active.debugPathData); GL.Color(theColor); TriangleMeshNode node = _node as TriangleMeshNode; Vector3 vertZero = (Vector3)node.GetVertex(0); Vector3 vertOne = (Vector3)node.GetVertex(1); Vector3 vertTwo = (Vector3)node.GetVertex(2); GL.Vertex(vertZero); GL.Vertex(vertOne); GL.Vertex(vertOne); GL.Vertex(vertTwo); GL.Vertex(vertTwo); GL.Vertex(vertZero); GL.Color(Color.blue); // draw a line to all of the connected nodes (only if a two way connection exists) for (int nodeConnect = 0; nodeConnect < node.connections.Length; nodeConnect++) { TriangleMeshNode connectedNode = node.connections[nodeConnect] as TriangleMeshNode; if (null != connectedNode) { // go over all the nodes that this connected node is connected to in order to check that one of them is the original node, thus a two way connection exists for (int connectedNodeConnect = 0; connectedNodeConnect < connectedNode.connections.Length; connectedNodeConnect++) { TriangleMeshNode originalNode = connectedNode.connections[connectedNodeConnect] as TriangleMeshNode; if (originalNode == node) // is this the original node, meaning a two way connection exists { GL.Vertex((Vector3)node.position); GL.Vertex((Vector3)connectedNode.position); break; } } } } return(true); }); } } GL.End(); }