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> /// Updates an area in the list graph. /// Recalculates possibly affected connections, i.e all connectionlines passing trough the bounds of the guo will be recalculated /// </summary> void IUpdatableGraph.UpdateArea(GraphUpdateObject guo) { if (nodes == null) { return; } for (int i = 0; i < nodeCount; i++) { var node = nodes[i]; if (guo.bounds.Contains((Vector3)node.position)) { guo.WillUpdateNode(node); guo.Apply(node); } } if (guo.updatePhysics) { // Use a copy of the bounding box, we should not change the GUO's bounding box since it might be used for other graph updates Bounds bounds = guo.bounds; if (thickRaycast) { // Expand the bounding box to account for the thick raycast bounds.Expand(thickRaycastRadius * 2); } // Create a temporary list used for holding connection data List <Connection> tmpList = Pathfinding.Util.ListPool <Connection> .Claim(); for (int i = 0; i < nodeCount; i++) { PointNode node = nodes[i]; var nodePos = (Vector3)node.position; List <Connection> conn = null; for (int j = 0; j < nodeCount; j++) { if (j == i) { continue; } var otherNodePos = (Vector3)nodes[j].position; // Check if this connection intersects the bounding box. // If it does we need to recalculate that connection. if (VectorMath.SegmentIntersectsBounds(bounds, nodePos, otherNodePos)) { float dist; PointNode other = nodes[j]; bool contains = node.ContainsConnection(other); bool validConnection = IsValidConnection(node, other, out dist); // Fill the 'conn' list when we need to change a connection if (conn == null && (contains != validConnection)) { tmpList.Clear(); conn = tmpList; conn.AddRange(node.connections); } if (!contains && validConnection) { // A new connection should be added uint cost = (uint)Mathf.RoundToInt(dist * Int3.FloatPrecision); conn.Add(new Connection(other, cost)); RegisterConnectionLength((other.position - node.position).sqrMagnitudeLong); } else if (contains && !validConnection) { // A connection should be removed for (int q = 0; q < conn.Count; q++) { if (conn[q].node == other) { conn.RemoveAt(q); break; } } } } } // Save the new connections if any were changed if (conn != null) { node.connections = conn.ToArray(); node.SetConnectivityDirty(); } } // Release buffers back to the pool Pathfinding.Util.ListPool <Connection> .Release(ref tmpList); } }
// Token: 0x060004C2 RID: 1218 RVA: 0x000293EC File Offset: 0x000277EC 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); }); }
public new void UpdateArea(GraphUpdateObject o) { if (nodes == null || nodes.Length != width*depth*layerCount) { Debug.LogWarning ("The Grid Graph is not scanned, cannot update area "); //Not scanned return; } //Copy the bounds Bounds b = o.bounds; //Matrix inverse //node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F)); Vector3 min, max; GetBoundsMinMax (b,inverseMatrix,out min, out max); int minX = Mathf.RoundToInt (min.x-0.5F); int maxX = Mathf.RoundToInt (max.x-0.5F); int minZ = Mathf.RoundToInt (min.z-0.5F); int maxZ = Mathf.RoundToInt (max.z-0.5F); //We now have coordinates in local space (i.e 1 unit = 1 node) IntRect originalRect = new IntRect(minX,minZ,maxX,maxZ); IntRect affectRect = originalRect; IntRect gridRect = new IntRect(0,0,width-1,depth-1); IntRect physicsRect = originalRect; Matrix4x4 debugMatrix = matrix; debugMatrix *= Matrix4x4.TRS (new Vector3(0.5f,0,0.5f),Quaternion.identity,Vector3.one); #if ASTARDEBUG originalRect.DebugDraw (debugMatrix,Color.red); #endif bool willChangeWalkability = o.updatePhysics || o.modifyWalkability; bool willChangeNodeInstances = (o is LayerGridGraphUpdate ? ((LayerGridGraphUpdate)o).recalculateNodes : false); bool preserveExistingNodes = (o is LayerGridGraphUpdate ? ((LayerGridGraphUpdate)o).preserveExistingNodes : true); if (o.trackChangedNodes && willChangeNodeInstances) { Debug.LogError ("Cannot track changed nodes when creating or deleting nodes.\nWill not update LayerGridGraph"); return; } //Calculate the largest bounding box which might be affected if (o.updatePhysics && !o.modifyWalkability) { //Add the collision.diameter margin for physics calls if (collision.collisionCheck) { Vector3 margin = new Vector3 (collision.diameter,0,collision.diameter)*0.5F; min -= margin*1.02F;//0.02 safety margin, physics is rarely very accurate max += margin*1.02F; physicsRect = new IntRect( Mathf.RoundToInt (min.x-0.5F), Mathf.RoundToInt (min.z-0.5F), Mathf.RoundToInt (max.x-0.5F), Mathf.RoundToInt (max.z-0.5F) ); affectRect = IntRect.Union (physicsRect, affectRect); } } if (willChangeWalkability && erodeIterations > 0) { //Add affect radius for erosion. +1 for updating connectivity info at the border affectRect = affectRect.Expand (erodeIterations+1); } IntRect clampedRect = IntRect.Intersection (affectRect,gridRect); //Mark nodes that might be changed if (!willChangeNodeInstances) { for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { for (int y=0;y<layerCount;y++) { o.WillUpdateNode (nodes[y*width*depth + z*width+x]); } } } } //Update Physics if (o.updatePhysics && !o.modifyWalkability) { collision.Initialize (matrix,nodeSize); clampedRect = IntRect.Intersection (physicsRect,gridRect); bool addedNodes = false; for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { /** \todo FIX */ addedNodes |= RecalculateCell (x,z,preserveExistingNodes); } } for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; CalculateConnections (nodes,node,x,z,y); } } } if (addedNodes) { AstarPath.active.DataUpdate(); } } //Apply GUO clampedRect = IntRect.Intersection (originalRect, gridRect); for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; if (willChangeWalkability) { node.walkable = node.Bit15; o.Apply (node); node.Bit15 = node.walkable; } else { o.Apply (node); } } } } #if ASTARDEBUG physicsRect.DebugDraw (debugMatrix,Color.blue); affectRect.DebugDraw (debugMatrix,Color.black); #endif //Recalculate connections if (willChangeWalkability && erodeIterations == 0) { clampedRect = IntRect.Intersection (affectRect, gridRect); for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; CalculateConnections (nodes,node,x,z,y); } } } } else if (willChangeWalkability && erodeIterations > 0) { clampedRect = IntRect.Union (originalRect, physicsRect); IntRect erosionRect1 = clampedRect.Expand (erodeIterations); IntRect erosionRect2 = erosionRect1.Expand (erodeIterations); erosionRect1 = IntRect.Intersection (erosionRect1,gridRect); erosionRect2 = IntRect.Intersection (erosionRect2,gridRect); #if ASTARDEBUG erosionRect1.DebugDraw (debugMatrix,Color.magenta); erosionRect2.DebugDraw (debugMatrix,Color.cyan); #endif /* all nodes inside clampedRect might have had their walkability changed all nodes inside erosionRect1 might get affected by erosion from clampedRect and erosionRect2 all nodes inside erosionRect2 (but outside erosionRect1) will be reset to previous walkability after calculation since their erosion might not be correctly calculated (nodes outside erosionRect2 would maybe have effect) */ for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; bool tmp = node.walkable; node.walkable = node.Bit15; if (!erosionRect1.Contains (x,z)) { //Save the border's walkabilty data in bit 16 (will be reset later) node.Bit16 = tmp; } } } } for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; #if ASTARDEBUG if (!node.walkable) Debug.DrawRay ((Vector3)node.position, Vector3.up*2,Color.red); #endif CalculateConnections (nodes,node,x,z,y); } } } //Erode the walkable area ErodeWalkableArea (erosionRect2.xmin,erosionRect2.ymin,erosionRect2.xmax+1,erosionRect2.ymax+1); for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { if (erosionRect1.Contains (x,z)) continue; for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; //Restore temporarily stored data node.walkable = node.Bit16; } } } //Recalculate connections of all affected nodes for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { for (int y=0;y<layerCount;y++) { int index = y*width*depth + z*width+x; LevelGridNode node = nodes[index] as LevelGridNode; if (node == null) continue; CalculateConnections (nodes,node,x,z,y); } } } } //Debug.LogError ("No support for Graph Updates to Layered Grid Graphs"); }
// Token: 0x060025C3 RID: 9667 RVA: 0x001A1AF0 File Offset: 0x0019FCF0 void IUpdatableGraph.UpdateArea(GraphUpdateObject guo) { if (this.nodes == null) { return; } for (int i = 0; i < this.nodeCount; i++) { PointNode pointNode = this.nodes[i]; if (guo.bounds.Contains((Vector3)pointNode.position)) { guo.WillUpdateNode(pointNode); guo.Apply(pointNode); } } if (guo.updatePhysics) { Bounds bounds = guo.bounds; if (this.thickRaycast) { bounds.Expand(this.thickRaycastRadius * 2f); } List <Connection> list = ListPool <Connection> .Claim(); for (int j = 0; j < this.nodeCount; j++) { PointNode pointNode2 = this.nodes[j]; Vector3 a = (Vector3)pointNode2.position; List <Connection> list2 = null; for (int k = 0; k < this.nodeCount; k++) { if (k != j) { Vector3 b = (Vector3)this.nodes[k].position; if (VectorMath.SegmentIntersectsBounds(bounds, a, b)) { PointNode pointNode3 = this.nodes[k]; bool flag = pointNode2.ContainsConnection(pointNode3); float num; bool flag2 = this.IsValidConnection(pointNode2, pointNode3, out num); if (list2 == null && flag != flag2) { list.Clear(); list2 = list; list2.AddRange(pointNode2.connections); } if (!flag && flag2) { uint cost = (uint)Mathf.RoundToInt(num * 1000f); list2.Add(new Connection(pointNode3, cost, byte.MaxValue)); } else if (flag && !flag2) { for (int l = 0; l < list2.Count; l++) { if (list2[l].node == pointNode3) { list2.RemoveAt(l); break; } } } } } } if (list2 != null) { pointNode2.connections = list2.ToArray(); } } ListPool <Connection> .Release(ref list); } }
/** Updates an area in the list graph. * Recalculates possibly affected connections, i.e all connectionlines passing trough the bounds of the \a guo will be recalculated * \astarpro */ public void UpdateArea(GraphUpdateObject guo) { if (nodes == null) { return; } for (int i=0;i<nodes.Length;i++) { if (guo.bounds.Contains ((Vector3)nodes[i].position)) { guo.WillUpdateNode (nodes[i]); guo.Apply (nodes[i]); } } if (guo.updatePhysics) { //Use a copy of the bounding box, we should not change the GUO's bounding box since it might be used for other graph updates Bounds bounds = guo.bounds; if (thickRaycast) { //Expand the bounding box to account for the thick raycast bounds.Expand (thickRaycastRadius*2); } //Create two temporary arrays used for holding new connections and costs List<Node> tmp_arr = Pathfinding.Util.ListPool<Node>.Claim (); List<int> tmp_arr2 =Pathfinding.Util.ListPool<int>.Claim (); for (int i=0;i<nodes.Length;i++) { Node node = nodes[i]; Vector3 a = (Vector3)node.position; List<Node> conn = null; List<int> costs = null; for (int j=0;j<nodes.Length;j++) { if (j==i) continue; Vector3 b = (Vector3)nodes[j].position; if (Polygon.LineIntersectsBounds (bounds,a,b)) { float dist; Node other = nodes[j]; bool contains = node.ContainsConnection (other); //Note, the IsValidConnection test will actually only be done once //no matter what,so there is no performance penalty there if (!contains && IsValidConnection (node,other, out dist)) { //Debug.DrawLine (a+Vector3.up*0.1F,b+Vector3.up*0.1F,Color.green); if (conn == null) { tmp_arr.Clear(); tmp_arr2.Clear (); conn = tmp_arr; costs = tmp_arr2; conn.AddRange (node.connections); costs.AddRange (node.connectionCosts); } int cost = Mathf.RoundToInt (dist*Int3.FloatPrecision); conn.Add (other); costs.Add (cost); } else if (contains && !IsValidConnection (node,other, out dist)) { //Debug.DrawLine (a+Vector3.up*0.5F*Random.value,b+Vector3.up*0.5F*Random.value,Color.red); if (conn == null) { tmp_arr.Clear(); tmp_arr2.Clear (); conn = tmp_arr; costs = tmp_arr2; conn.AddRange (node.connections); costs.AddRange (node.connectionCosts); } int p = conn.IndexOf (other); //Shouldn't have to check for it, but who knows what might go wrong if (p != -1) { conn.RemoveAt (p); costs.RemoveAt (p); } } } } if (conn != null) { node.connections = conn.ToArray (); node.connectionCosts = costs.ToArray (); } } Pathfinding.Util.ListPool<Node>.Release (tmp_arr); Pathfinding.Util.ListPool<int>.Release (tmp_arr2); } }
public static void UpdateArea (GraphUpdateObject o, NavGraph graph) { INavmesh navgraph = graph as INavmesh; if (navgraph == null) { Debug.LogError ("Update Area on NavMesh must be called with a graph implementing INavmesh"); return; } if (graph.nodes == null || graph.nodes.Length == 0) { Debug.LogError ("NavGraph hasn't been generated yet or does not contain any nodes"); return;// new NNInfo (); } //System.DateTime startTime = System.DateTime.Now; Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect (bounds.min.x,bounds.min.z,bounds.max.x,bounds.max.z); 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 for (int i=0;i<graph.nodes.Length;i++) { MeshNode node = graph.nodes[i] as MeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v=0;v<3;v++) { Vector3 vert = (Vector3)navgraph.vertices[node[v]]; Vector2 vert2D = new Vector2 (vert.x,vert.z); if (r.Contains (vert2D)) { //Debug.DrawRay (vert,Vector3.up,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) { continue; } } for (int v=0;v<3;v++) { int v2 = v > 1 ? 0 : v+1; Vector3 vert1 = (Vector3)navgraph.vertices[node[v]]; Vector3 vert2 = (Vector3)navgraph.vertices[node[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 (!inside && ContainsPoint (node,a,navgraph.vertices)) { inside = true; }//Debug.DrawRay (a+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside && ContainsPoint (node,b,navgraph.vertices)) { inside = true; } //Debug.DrawRay (b+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside && ContainsPoint (node,c,navgraph.vertices)) { inside = true; }//Debug.DrawRay (c+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside && ContainsPoint (node,d,navgraph.vertices)) { inside = true; }//Debug.DrawRay (d+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside) { continue; } o.WillUpdateNode(node); o.Apply (node); //Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.blue); //Debug.DrawLine (vertices[node.v2],vertices[node.v3],Color.blue); //Debug.DrawLine (vertices[node.v3],vertices[node.v1],Color.blue); //Debug.Break (); } //System.DateTime endTime = System.DateTime.Now; //float theTime = (endTime-startTime).Ticks*0.0001F; //Debug.Log ("Intersecting bounds with navmesh took "+theTime.ToString ("0.000")+" ms"); }
/** Updates an area in the list graph. * Recalculates possibly affected connections, i.e all connectionlines passing trough the bounds of the \a guo will be recalculated * \astarpro */ public void UpdateArea(GraphUpdateObject guo) { if (nodes == null) { return; } for (int i = 0; i < nodeCount; i++) { if (guo.bounds.Contains((Vector3)nodes[i].position)) { guo.WillUpdateNode(nodes[i]); guo.Apply(nodes[i]); } } if (guo.updatePhysics) { //Use a copy of the bounding box, we should not change the GUO's bounding box since it might be used for other graph updates Bounds bounds = guo.bounds; if (thickRaycast) { //Expand the bounding box to account for the thick raycast bounds.Expand(thickRaycastRadius * 2); } //Create two temporary arrays used for holding new connections and costs List <GraphNode> tmp_arr = Pathfinding.Util.ListPool <GraphNode> .Claim(); List <uint> tmp_arr2 = Pathfinding.Util.ListPool <uint> .Claim(); for (int i = 0; i < nodeCount; i++) { PointNode node = nodes[i]; var a = (Vector3)node.position; List <GraphNode> conn = null; List <uint> costs = null; for (int j = 0; j < nodeCount; j++) { if (j == i) { continue; } var b = (Vector3)nodes[j].position; if (VectorMath.SegmentIntersectsBounds(bounds, a, b)) { float dist; PointNode other = nodes[j]; bool contains = node.ContainsConnection(other); bool validConnection = IsValidConnection(node, other, out dist); if (!contains && validConnection) { // A new connection should be added if (conn == null) { tmp_arr.Clear(); tmp_arr2.Clear(); conn = tmp_arr; costs = tmp_arr2; conn.AddRange(node.connections); costs.AddRange(node.connectionCosts); } uint cost = (uint)Mathf.RoundToInt(dist * Int3.FloatPrecision); conn.Add(other); costs.Add(cost); } else if (contains && !validConnection) { // A connection should be removed if (conn == null) { tmp_arr.Clear(); tmp_arr2.Clear(); conn = tmp_arr; costs = tmp_arr2; conn.AddRange(node.connections); costs.AddRange(node.connectionCosts); } int p = conn.IndexOf(other); //Shouldn't have to check for it, but who knows what might go wrong if (p != -1) { conn.RemoveAt(p); costs.RemoveAt(p); } } } } // Save the new connections if any were changed if (conn != null) { node.connections = conn.ToArray(); node.connectionCosts = costs.ToArray(); } } // Release buffers back to the pool Pathfinding.Util.ListPool <GraphNode> .Release(tmp_arr); Pathfinding.Util.ListPool <uint> .Release(tmp_arr2); } }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { Bounds bounds = o.bounds; Rect rect = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); IntRect irect = 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(irect.xmin, 0, irect.ymin); Int3 b = new Int3(irect.xmin, 0, irect.ymax); Int3 c = new Int3(irect.xmax, 0, irect.ymin); Int3 d = new Int3(irect.xmax, 0, irect.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 (irect.Contains(vertex.x, vertex.z)) { flag = true; break; } if (vector.x < rect.xMin) { num++; } if (vector.x > rect.xMax) { num2++; } if (vector.z < rect.yMin) { num3++; } if (vector.z > rect.yMax) { num4++; } } if (!flag && (num == 3 || num2 == 3 || num3 == 3 || num4 == 3)) { return; } for (int j = 0; j < 3; j++) { int i2 = (j > 1) ? 0 : (j + 1); 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; } 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; } o.WillUpdateNode(triangleMeshNode); o.Apply(triangleMeshNode); }); }
// Token: 0x06002570 RID: 9584 RVA: 0x001A2E38 File Offset: 0x001A1038 public static void UpdateArea(GraphUpdateObject o, INavmeshHolder graph) { Bounds bounds = graph.transform.InverseTransform(o.bounds); IntRect irect = new IntRect(Mathf.FloorToInt(bounds.min.x * 1000f), Mathf.FloorToInt(bounds.min.z * 1000f), Mathf.CeilToInt(bounds.max.x * 1000f), Mathf.CeilToInt(bounds.max.z * 1000f)); Int3 a = new Int3(irect.xmin, 0, irect.ymin); Int3 b = new Int3(irect.xmin, 0, irect.ymax); Int3 c = new Int3(irect.xmax, 0, irect.ymin); Int3 d = new Int3(irect.xmax, 0, irect.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 vertexInGraphSpace = triangleMeshNode.GetVertexInGraphSpace(i); if (irect.Contains(vertexInGraphSpace.x, vertexInGraphSpace.z)) { flag = true; break; } if (vertexInGraphSpace.x < irect.xmin) { num++; } if (vertexInGraphSpace.x > irect.xmax) { num2++; } if (vertexInGraphSpace.z < irect.ymin) { num3++; } if (vertexInGraphSpace.z > irect.ymax) { num4++; } } if (!flag && (num == 3 || num2 == 3 || num3 == 3 || num4 == 3)) { return; } for (int j = 0; j < 3; j++) { int i2 = (j > 1) ? 0 : (j + 1); Int3 vertexInGraphSpace2 = triangleMeshNode.GetVertexInGraphSpace(j); Int3 vertexInGraphSpace3 = triangleMeshNode.GetVertexInGraphSpace(i2); if (VectorMath.SegmentsIntersectXZ(a, b, vertexInGraphSpace2, vertexInGraphSpace3)) { flag = true; break; } if (VectorMath.SegmentsIntersectXZ(a, c, vertexInGraphSpace2, vertexInGraphSpace3)) { flag = true; break; } if (VectorMath.SegmentsIntersectXZ(c, d, vertexInGraphSpace2, vertexInGraphSpace3)) { flag = true; break; } if (VectorMath.SegmentsIntersectXZ(d, b, vertexInGraphSpace2, vertexInGraphSpace3)) { flag = true; break; } } if (flag || triangleMeshNode.ContainsPointInGraphSpace(a) || triangleMeshNode.ContainsPointInGraphSpace(b) || triangleMeshNode.ContainsPointInGraphSpace(c) || triangleMeshNode.ContainsPointInGraphSpace(d)) { flag = true; } if (!flag) { return; } int num5 = 0; int num6 = 0; for (int k = 0; k < 3; k++) { Int3 vertexInGraphSpace4 = triangleMeshNode.GetVertexInGraphSpace(k); if (vertexInGraphSpace4.y < ymin) { num6++; } if (vertexInGraphSpace4.y > ymax) { num5++; } } if (num6 == 3 || num5 == 3) { return; } o.WillUpdateNode(triangleMeshNode); o.Apply(triangleMeshNode); }); }
/** Updates an area in the list graph. * Recalculates possibly affected connections, i.e all connectionlines passing trough the bounds of the \a guo will be recalculated * \astarpro */ public void UpdateArea(GraphUpdateObject guo) { if (nodes == null) { return; } for (int i = 0; i < nodeCount; i++) { if (guo.bounds.Contains((Vector3)nodes[i].position)) { guo.WillUpdateNode(nodes[i]); guo.Apply(nodes[i]); } } if (guo.updatePhysics) { //Use a copy of the bounding box, we should not change the GUO's bounding box since it might be used for other graph updates Bounds bounds = guo.bounds; if (thickRaycast) { //Expand the bounding box to account for the thick raycast bounds.Expand(thickRaycastRadius * 2); } //Create two temporary arrays used for holding new connections and costs List <GraphNode> tmp_arr = Pathfinding.Util.ListPool <GraphNode> .Claim(); List <uint> tmp_arr2 = Pathfinding.Util.ListPool <uint> .Claim(); for (int i = 0; i < nodeCount; i++) { PointNode node = nodes[i] as PointNode; Vector3 a = (Vector3)node.position; List <GraphNode> conn = null; List <uint> costs = null; for (int j = 0; j < nodeCount; j++) { if (j == i) { continue; } Vector3 b = (Vector3)nodes[j].position; if (Polygon.LineIntersectsBounds(bounds, a, b)) { float dist; PointNode other = nodes[j] as PointNode; bool contains = node.ContainsConnection(other); //Note, the IsValidConnection test will actually only be done once //no matter what,so there is no performance penalty there if (!contains && IsValidConnection(node, other, out dist)) { //Debug.DrawLine (a+Vector3.up*0.1F,b+Vector3.up*0.1F,Color.green); if (conn == null) { tmp_arr.Clear(); tmp_arr2.Clear(); conn = tmp_arr; costs = tmp_arr2; conn.AddRange(node.connections); costs.AddRange(node.connectionCosts); } uint cost = (uint)Mathf.RoundToInt(dist * Int3.FloatPrecision); conn.Add(other); costs.Add(cost); } else if (contains && !IsValidConnection(node, other, out dist)) { //Debug.DrawLine (a+Vector3.up*0.5F*Random.value,b+Vector3.up*0.5F*Random.value,Color.red); if (conn == null) { tmp_arr.Clear(); tmp_arr2.Clear(); conn = tmp_arr; costs = tmp_arr2; conn.AddRange(node.connections); costs.AddRange(node.connectionCosts); } int p = conn.IndexOf(other); //Shouldn't have to check for it, but who knows what might go wrong if (p != -1) { conn.RemoveAt(p); costs.RemoveAt(p); } } } } if (conn != null) { node.connections = conn.ToArray(); node.connectionCosts = costs.ToArray(); } } Pathfinding.Util.ListPool <GraphNode> .Release(tmp_arr); Pathfinding.Util.ListPool <uint> .Release(tmp_arr2); } }
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; // 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, NavGraph graph) { INavmesh navgraph = graph as INavmesh; if (navgraph == null) { Debug.LogError("Update Area on NavMesh must be called with a graph implementing INavmesh"); return; } if (graph.nodes == null || graph.nodes.Length == 0) { Debug.LogError("NavGraph hasn't been generated yet or does not contain any nodes"); return; // new NNInfo (); } //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); 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 for (int i = 0; i < graph.nodes.Length; i++) { MeshNode node = graph.nodes[i] as MeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v = 0; v < 3; v++) { Vector3 vert = (Vector3)navgraph.vertices[node[v]]; Vector2 vert2D = new Vector2(vert.x, vert.z); if (r.Contains(vert2D)) { //Debug.DrawRay (vert,Vector3.up,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) { continue; } } for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v + 1; Vector3 vert1 = (Vector3)navgraph.vertices[node[v]]; Vector3 vert2 = (Vector3)navgraph.vertices[node[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 (!inside && ContainsPoint(node, a, navgraph.vertices)) { inside = true; } //Debug.DrawRay (a+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside && ContainsPoint(node, b, navgraph.vertices)) { inside = true; } //Debug.DrawRay (b+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside && ContainsPoint(node, c, navgraph.vertices)) { inside = true; } //Debug.DrawRay (c+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside && ContainsPoint(node, d, navgraph.vertices)) { inside = true; } //Debug.DrawRay (d+Vector3.right*0.01F*i,Vector3.up,Color.red); } if (!inside) { continue; } o.WillUpdateNode(node); o.Apply(node); //Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.blue); //Debug.DrawLine (vertices[node.v2],vertices[node.v3],Color.blue); //Debug.DrawLine (vertices[node.v3],vertices[node.v1],Color.blue); //Debug.Break (); } //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"); }
// Token: 0x0600253A RID: 9530 RVA: 0x001A1218 File Offset: 0x0019F418 void IUpdatableGraph.UpdateArea(GraphUpdateObject o) { if (this.nodes == null || this.nodes.Length != this.width * this.depth * this.layerCount) { Debug.LogWarning("The Grid Graph is not scanned, cannot update area "); return; } IntRect a; IntRect a2; IntRect intRect; bool flag; int num; base.CalculateAffectedRegions(o, out a, out a2, out intRect, out flag, out num); bool flag2 = o is LayerGridGraphUpdate && ((LayerGridGraphUpdate)o).recalculateNodes; bool flag3 = (o is LayerGridGraphUpdate) ? ((LayerGridGraphUpdate)o).preserveExistingNodes : (!o.resetPenaltyOnPhysics); if (o.trackChangedNodes && flag2) { Debug.LogError("Cannot track changed nodes when creating or deleting nodes.\nWill not update LayerGridGraph"); return; } IntRect b = new IntRect(0, 0, this.width - 1, this.depth - 1); IntRect intRect2 = IntRect.Intersection(a2, b); if (!flag2) { for (int i = intRect2.xmin; i <= intRect2.xmax; i++) { for (int j = intRect2.ymin; j <= intRect2.ymax; j++) { for (int k = 0; k < this.layerCount; k++) { o.WillUpdateNode(this.nodes[k * this.width * this.depth + j * this.width + i]); } } } } if (o.updatePhysics && !o.modifyWalkability) { this.collision.Initialize(base.transform, this.nodeSize); intRect2 = IntRect.Intersection(intRect, b); for (int l = intRect2.xmin; l <= intRect2.xmax; l++) { for (int m = intRect2.ymin; m <= intRect2.ymax; m++) { this.RecalculateCell(l, m, !flag3, false); } } for (int n = intRect2.xmin; n <= intRect2.xmax; n++) { for (int num2 = intRect2.ymin; num2 <= intRect2.ymax; num2++) { this.CalculateConnections(n, num2); } } } intRect2 = IntRect.Intersection(a, b); for (int num3 = intRect2.xmin; num3 <= intRect2.xmax; num3++) { for (int num4 = intRect2.ymin; num4 <= intRect2.ymax; num4++) { for (int num5 = 0; num5 < this.layerCount; num5++) { int num6 = num5 * this.width * this.depth + num4 * this.width + num3; LevelGridNode levelGridNode = this.nodes[num6]; if (levelGridNode != null) { if (flag) { levelGridNode.Walkable = levelGridNode.WalkableErosion; if (o.bounds.Contains((Vector3)levelGridNode.position)) { o.Apply(levelGridNode); } levelGridNode.WalkableErosion = levelGridNode.Walkable; } else if (o.bounds.Contains((Vector3)levelGridNode.position)) { o.Apply(levelGridNode); } } } } } if (flag && num == 0) { intRect2 = IntRect.Intersection(a2, b); for (int num7 = intRect2.xmin; num7 <= intRect2.xmax; num7++) { for (int num8 = intRect2.ymin; num8 <= intRect2.ymax; num8++) { this.CalculateConnections(num7, num8); } } return; } if (flag && num > 0) { IntRect a3 = IntRect.Union(a, intRect).Expand(num); IntRect intRect3 = a3.Expand(num); a3 = IntRect.Intersection(a3, b); intRect3 = IntRect.Intersection(intRect3, b); for (int num9 = intRect3.xmin; num9 <= intRect3.xmax; num9++) { for (int num10 = intRect3.ymin; num10 <= intRect3.ymax; num10++) { for (int num11 = 0; num11 < this.layerCount; num11++) { int num12 = num11 * this.width * this.depth + num10 * this.width + num9; LevelGridNode levelGridNode2 = this.nodes[num12]; if (levelGridNode2 != null) { bool walkable = levelGridNode2.Walkable; levelGridNode2.Walkable = levelGridNode2.WalkableErosion; if (!a3.Contains(num9, num10)) { levelGridNode2.TmpWalkable = walkable; } } } } } for (int num13 = intRect3.xmin; num13 <= intRect3.xmax; num13++) { for (int num14 = intRect3.ymin; num14 <= intRect3.ymax; num14++) { this.CalculateConnections(num13, num14); } } base.ErodeWalkableArea(intRect3.xmin, intRect3.ymin, intRect3.xmax + 1, intRect3.ymax + 1); for (int num15 = intRect3.xmin; num15 <= intRect3.xmax; num15++) { for (int num16 = intRect3.ymin; num16 <= intRect3.ymax; num16++) { if (!a3.Contains(num15, num16)) { for (int num17 = 0; num17 < this.layerCount; num17++) { int num18 = num17 * this.width * this.depth + num16 * this.width + num15; LevelGridNode levelGridNode3 = this.nodes[num18]; if (levelGridNode3 != null) { levelGridNode3.Walkable = levelGridNode3.TmpWalkable; } } } } } for (int num19 = intRect3.xmin; num19 <= intRect3.xmax; num19++) { for (int num20 = intRect3.ymin; num20 <= intRect3.ymax; num20++) { this.CalculateConnections(num19, num20); } } } }
public new void UpdateArea(GraphUpdateObject o) { if (this.nodes == null || this.nodes.Length != this.width * this.depth * this.layerCount) { Debug.LogWarning("The Grid Graph is not scanned, cannot update area "); return; } Bounds bounds = o.bounds; Vector3 a; Vector3 a2; GridGraph.GetBoundsMinMax(bounds, this.inverseMatrix, out a, out a2); int xmin = Mathf.RoundToInt(a.x - 0.5f); int xmax = Mathf.RoundToInt(a2.x - 0.5f); int ymin = Mathf.RoundToInt(a.z - 0.5f); int ymax = Mathf.RoundToInt(a2.z - 0.5f); IntRect intRect = new IntRect(xmin, ymin, xmax, ymax); IntRect intRect2 = intRect; IntRect b = new IntRect(0, 0, this.width - 1, this.depth - 1); IntRect intRect3 = intRect; bool flag = o.updatePhysics || o.modifyWalkability; bool flag2 = o is LayerGridGraphUpdate && ((LayerGridGraphUpdate)o).recalculateNodes; bool preserveExistingNodes = !(o is LayerGridGraphUpdate) || ((LayerGridGraphUpdate)o).preserveExistingNodes; int num = (!o.updateErosion) ? 0 : this.erodeIterations; if (o.trackChangedNodes && flag2) { Debug.LogError("Cannot track changed nodes when creating or deleting nodes.\nWill not update LayerGridGraph"); return; } if (o.updatePhysics && !o.modifyWalkability && this.collision.collisionCheck) { Vector3 a3 = new Vector3(this.collision.diameter, 0f, this.collision.diameter) * 0.5f; a -= a3 * 1.02f; a2 += a3 * 1.02f; intRect3 = new IntRect(Mathf.RoundToInt(a.x - 0.5f), Mathf.RoundToInt(a.z - 0.5f), Mathf.RoundToInt(a2.x - 0.5f), Mathf.RoundToInt(a2.z - 0.5f)); intRect2 = IntRect.Union(intRect3, intRect2); } if (flag || num > 0) { intRect2 = intRect2.Expand(num + 1); } IntRect intRect4 = IntRect.Intersection(intRect2, b); if (!flag2) { for (int i = intRect4.xmin; i <= intRect4.xmax; i++) { for (int j = intRect4.ymin; j <= intRect4.ymax; j++) { for (int k = 0; k < this.layerCount; k++) { o.WillUpdateNode(this.nodes[k * this.width * this.depth + j * this.width + i]); } } } } if (o.updatePhysics && !o.modifyWalkability) { this.collision.Initialize(this.matrix, this.nodeSize); intRect4 = IntRect.Intersection(intRect3, b); bool flag3 = false; for (int l = intRect4.xmin; l <= intRect4.xmax; l++) { for (int m = intRect4.ymin; m <= intRect4.ymax; m++) { flag3 |= this.RecalculateCell(l, m, preserveExistingNodes); } } for (int n = intRect4.xmin; n <= intRect4.xmax; n++) { for (int num2 = intRect4.ymin; num2 <= intRect4.ymax; num2++) { for (int num3 = 0; num3 < this.layerCount; num3++) { int num4 = num3 * this.width * this.depth + num2 * this.width + n; LevelGridNode levelGridNode = this.nodes[num4]; if (levelGridNode != null) { this.CalculateConnections(this.nodes, levelGridNode, n, num2, num3); } } } } } intRect4 = IntRect.Intersection(intRect, b); for (int num5 = intRect4.xmin; num5 <= intRect4.xmax; num5++) { for (int num6 = intRect4.ymin; num6 <= intRect4.ymax; num6++) { for (int num7 = 0; num7 < this.layerCount; num7++) { int num8 = num7 * this.width * this.depth + num6 * this.width + num5; LevelGridNode levelGridNode2 = this.nodes[num8]; if (levelGridNode2 != null) { if (flag) { levelGridNode2.Walkable = levelGridNode2.WalkableErosion; if (o.bounds.Contains((Vector3)levelGridNode2.position)) { o.Apply(levelGridNode2); } levelGridNode2.WalkableErosion = levelGridNode2.Walkable; } else if (o.bounds.Contains((Vector3)levelGridNode2.position)) { o.Apply(levelGridNode2); } } } } } if (flag && num == 0) { intRect4 = IntRect.Intersection(intRect2, b); for (int num9 = intRect4.xmin; num9 <= intRect4.xmax; num9++) { for (int num10 = intRect4.ymin; num10 <= intRect4.ymax; num10++) { for (int num11 = 0; num11 < this.layerCount; num11++) { int num12 = num11 * this.width * this.depth + num10 * this.width + num9; LevelGridNode levelGridNode3 = this.nodes[num12]; if (levelGridNode3 != null) { this.CalculateConnections(this.nodes, levelGridNode3, num9, num10, num11); } } } } } else if (flag && num > 0) { IntRect a4 = IntRect.Union(intRect, intRect3).Expand(num); IntRect a5 = a4.Expand(num); a4 = IntRect.Intersection(a4, b); a5 = IntRect.Intersection(a5, b); for (int num13 = a5.xmin; num13 <= a5.xmax; num13++) { for (int num14 = a5.ymin; num14 <= a5.ymax; num14++) { for (int num15 = 0; num15 < this.layerCount; num15++) { int num16 = num15 * this.width * this.depth + num14 * this.width + num13; LevelGridNode levelGridNode4 = this.nodes[num16]; if (levelGridNode4 != null) { bool walkable = levelGridNode4.Walkable; levelGridNode4.Walkable = levelGridNode4.WalkableErosion; if (!a4.Contains(num13, num14)) { levelGridNode4.TmpWalkable = walkable; } } } } } for (int num17 = a5.xmin; num17 <= a5.xmax; num17++) { for (int num18 = a5.ymin; num18 <= a5.ymax; num18++) { for (int num19 = 0; num19 < this.layerCount; num19++) { int num20 = num19 * this.width * this.depth + num18 * this.width + num17; LevelGridNode levelGridNode5 = this.nodes[num20]; if (levelGridNode5 != null) { this.CalculateConnections(this.nodes, levelGridNode5, num17, num18, num19); } } } } this.ErodeWalkableArea(a5.xmin, a5.ymin, a5.xmax + 1, a5.ymax + 1); for (int num21 = a5.xmin; num21 <= a5.xmax; num21++) { for (int num22 = a5.ymin; num22 <= a5.ymax; num22++) { if (!a4.Contains(num21, num22)) { for (int num23 = 0; num23 < this.layerCount; num23++) { int num24 = num23 * this.width * this.depth + num22 * this.width + num21; LevelGridNode levelGridNode6 = this.nodes[num24]; if (levelGridNode6 != null) { levelGridNode6.Walkable = levelGridNode6.TmpWalkable; } } } } } for (int num25 = a5.xmin; num25 <= a5.xmax; num25++) { for (int num26 = a5.ymin; num26 <= a5.ymax; num26++) { for (int num27 = 0; num27 < this.layerCount; num27++) { int num28 = num27 * this.width * this.depth + num26 * this.width + num25; LevelGridNode levelGridNode7 = this.nodes[num28]; if (levelGridNode7 != null) { this.CalculateConnections(this.nodes, levelGridNode7, num25, num26, num27); } } } } } }
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); }); }
// Token: 0x0600052A RID: 1322 RVA: 0x0002D6B8 File Offset: 0x0002BAB8 public void UpdateArea(GraphUpdateObject guo) { if (this.nodes == null) { return; } for (int i = 0; i < this.nodeCount; i++) { if (guo.bounds.Contains((Vector3)this.nodes[i].position)) { guo.WillUpdateNode(this.nodes[i]); guo.Apply(this.nodes[i]); } } if (guo.updatePhysics) { Bounds bounds = guo.bounds; if (this.thickRaycast) { bounds.Expand(this.thickRaycastRadius * 2f); } List <GraphNode> list = ListPool <GraphNode> .Claim(); List <uint> list2 = ListPool <uint> .Claim(); for (int j = 0; j < this.nodeCount; j++) { PointNode pointNode = this.nodes[j]; Vector3 a = (Vector3)pointNode.position; List <GraphNode> list3 = null; List <uint> list4 = null; for (int k = 0; k < this.nodeCount; k++) { if (k != j) { Vector3 b = (Vector3)this.nodes[k].position; if (Polygon.LineIntersectsBounds(bounds, a, b)) { PointNode pointNode2 = this.nodes[k]; bool flag = pointNode.ContainsConnection(pointNode2); float num; if (!flag && this.IsValidConnection(pointNode, pointNode2, out num)) { if (list3 == null) { list.Clear(); list2.Clear(); list3 = list; list4 = list2; list3.AddRange(pointNode.connections); list4.AddRange(pointNode.connectionCosts); } uint item = (uint)Mathf.RoundToInt(num * 1000f); list3.Add(pointNode2); list4.Add(item); } else if (flag && !this.IsValidConnection(pointNode, pointNode2, out num)) { if (list3 == null) { list.Clear(); list2.Clear(); list3 = list; list4 = list2; list3.AddRange(pointNode.connections); list4.AddRange(pointNode.connectionCosts); } int num2 = list3.IndexOf(pointNode2); if (num2 != -1) { list3.RemoveAt(num2); list4.RemoveAt(num2); } } } } } if (list3 != null) { pointNode.connections = list3.ToArray(); pointNode.connectionCosts = list4.ToArray(); } } ListPool <GraphNode> .Release(list); ListPool <uint> .Release(list2); } }
/** Internal function to update an area of the graph. * \todo Messy code, clean it up. */ public void UpdateArea(GraphUpdateObject o) { if (nodes == null) { Debug.LogWarning ("The Grid Graph is not scanned, cannot update area "); //Not scanned return; } //Copy the bounds Bounds b = o.bounds; //Matrix inverse //node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F)); Vector3 min, max; GetBoundsMinMax (b,inverseMatrix,out min, out max); int minX = Mathf.RoundToInt (min.x-0.5F); int maxX = Mathf.RoundToInt (max.x-0.5F); int minZ = Mathf.RoundToInt (min.z-0.5F); int maxZ = Mathf.RoundToInt (max.z-0.5F); //We now have coordinates in local space (i.e 1 unit = 1 node) int ominx = minX; int omaxx = maxX; int ominz = minZ; int omaxz = maxZ; if (o.updatePhysics && !o.modifyWalkability) { //Add the collision.diameter margin for physics calls if (collision.collisionCheck) { Vector3 margin = new Vector3 (collision.diameter,0,collision.diameter)*0.5F; min -= margin*1.02F;//0.02 safety margin, physics is rarely very accurate max += margin*1.02F; #if DEBUG Debug.DrawLine (matrix.MultiplyPoint3x4(min),matrix.MultiplyPoint3x4(max),Color.cyan); #endif minX = Mathf.RoundToInt (min.x-0.5F); maxX = Mathf.RoundToInt (max.x-0.5F); minZ = Mathf.RoundToInt (min.z-0.5F); maxZ = Mathf.RoundToInt (max.z-0.5F); } collision.Initialize (matrix,nodeSize); for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0) { continue; } if (z >= depth || x >= width) { break; } int index = z*width+x; GridNode node = nodes[index] as GridNode; //Register that this node will eventually have some settings changed o.WillUpdateNode (node); UpdateNodePositionCollision (node,x,z); } } } //This is the area inside the bounding box, call Apply on it for (int x = ominx;x <= omaxx;x++) { for (int z = ominz;z <= omaxz;z++) { if (x < 0 || z < 0) { continue; } if (z >= depth || x >= width) { break; } int index = z*width+x; GridNode node = nodes[index] as GridNode; if (!o.updatePhysics || o.modifyWalkability) { //Register that this node will eventually have some settings changed //If the above IF evaluates to false, the node will already have been added before in the function o.WillUpdateNode (node); } node.walkable = node.WalkableErosion; o.Apply (node); node.WalkableErosion = node.walkable; } } //Recalculate connections if ((o.updatePhysics || o.modifyWalkability) && erodeIterations == 0) { //Add some margin minX--; maxX++; minZ--; maxZ++; for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) { continue; } int index = z*width+x; GridNode node = nodes[index] as GridNode; CalculateConnections (graphNodes,x,z,node); } } //Remove margin minX++; maxX--; minZ++; maxZ--; } if ((o.updatePhysics || o.modifyWalkability) && erodeIterations > 0) { minX -= erodeIterations; maxX += erodeIterations; minZ -= erodeIterations; maxZ += erodeIterations; for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) { continue; } int index = z*width+x; GridNode node = nodes[index] as GridNode; node.walkable = node.WalkableErosion; } } //Add some margin minX--; maxX++; minZ--; maxZ++; //Loop through all nodes at the edge of the current bounds and swap their walkable and WalkableErosion flags for (int x=minX, z=minZ;x<= maxX;x++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; //Debug.DrawRay (node.position,Vector3.up,Color.red); node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int x=minX, z=maxZ;x<= maxX;x++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; //Debug.DrawRay (node.position,Vector3.up,Color.red); node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int z=minZ, x=minX;z<= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; //Debug.DrawRay (node.position,Vector3.up,Color.red); node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int z=minZ, x=maxX;z<= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; //Debug.DrawRay (node.position,Vector3.up,Color.red); node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } //Remove margin minX++; maxX--; minZ++; maxZ--; //Calculate connections for all nodes for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) { continue; } int index = z*width+x; GridNode node = nodes[index] as GridNode; CalculateConnections (graphNodes,x,z,node); } } //Erode function uses < not <= maxX++; maxZ++; /*for (int x = minX;x < maxX;x++) { for (int z = minZ;z < maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) { continue; } int index = z*width+x; GridNode node = graphNodes[index]; //Debug.DrawRay (node.position,Vector3.up*0.5F,Color.green); } }*/ //Erode area ErodeWalkableArea (minX,minZ,maxX,maxZ); maxX--; maxZ--; //Add some margin minX--; maxX++; minZ--; maxZ++; for (int x=minX, z=minZ;x<= maxX;x++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int x=minX, z=maxZ;x<= maxX;x++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int z=minZ, x=minX;z<= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int z=minZ, x=maxX;z<= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) continue; GridNode node = nodes[z*width+x] as GridNode; bool tmp = node.walkable; node.walkable = node.WalkableErosion; node.WalkableErosion = tmp; } for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) { continue; } int index = z*width+x; GridNode node = nodes[index] as GridNode; CalculateConnections (graphNodes,x,z,node); } } //Remove margin minX++; maxX--; minZ++; maxZ--; } }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { //System.DateTime startTime = System.DateTime.UtcNow; var bounds = o.bounds; var 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); var ia = (Int3)a; var ib = (Int3)b; var ic = (Int3)c; var id = (Int3)d; //for (int i=0;i<nodes.Length;i++) { graph.GetNodes(delegate(GraphNode _node) { var node = _node as TriangleMeshNode; var inside = false; var allLeft = 0; var allRight = 0; var allTop = 0; var allBottom = 0; for (var v = 0; v < 3; v++) { var p = node.GetVertex(v); var 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 (!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 (var v = 0; v < 3; v++) { var v2 = v > 1 ? 0 : v + 1; var vert1 = node.GetVertex(v); var 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) { //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, INavmeshHolder graph) { Bounds bounds = graph.transform.InverseTransform(o.bounds); // Bounding rectangle with integer coordinates var irect = new IntRect( Mathf.FloorToInt(bounds.min.x * Int3.Precision), Mathf.FloorToInt(bounds.min.z * Int3.Precision), Mathf.CeilToInt(bounds.max.x * Int3.Precision), Mathf.CeilToInt(bounds.max.z * Int3.Precision) ); // Corners of the bounding rectangle var a = new Int3(irect.xmin, 0, irect.ymin); var b = new Int3(irect.xmin, 0, irect.ymax); var c = new Int3(irect.xmax, 0, irect.ymin); var d = new Int3(irect.xmax, 0, irect.ymax); var ymin = ((Int3)bounds.min).y; var ymax = ((Int3)bounds.max).y; // Loop through all nodes and check if they intersect the bounding box 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.GetVertexInGraphSpace(v); if (irect.Contains(p.x, p.z)) { inside = true; break; } if (p.x < irect.xmin) { allLeft++; } if (p.x > irect.xmax) { allRight++; } if (p.z < irect.ymin) { allTop++; } if (p.z > irect.ymax) { allBottom++; } } if (!inside && (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3)) { return; } // 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.GetVertexInGraphSpace(v); Int3 vert2 = node.GetVertexInGraphSpace(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.ContainsPointInGraphSpace(a) || node.ContainsPointInGraphSpace(b) || node.ContainsPointInGraphSpace(c) || node.ContainsPointInGraphSpace(d)) { inside = true; } if (!inside) { return; } int allAbove = 0; int allBelow = 0; // Check y coordinate for (int v = 0; v < 3; v++) { Int3 p = node.GetVertexInGraphSpace(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; } // Triangle is inside the bounding box! // Update it! o.WillUpdateNode(node); o.Apply(node); }); }
/** Internal function to update an area of the graph. */ public void UpdateArea (GraphUpdateObject o) { if (nodes == null || nodes.Length != width*depth) { Debug.LogWarning ("The Grid Graph is not scanned, cannot update area "); //Not scanned return; } //Copy the bounds Bounds b = o.bounds; Vector3 min, max; GetBoundsMinMax (b,inverseMatrix,out min, out max); int minX = Mathf.RoundToInt (min.x-0.5F); int maxX = Mathf.RoundToInt (max.x-0.5F); int minZ = Mathf.RoundToInt (min.z-0.5F); int maxZ = Mathf.RoundToInt (max.z-0.5F); //We now have coordinates in local space (i.e 1 unit = 1 node) IntRect originalRect = new IntRect(minX,minZ,maxX,maxZ); IntRect affectRect = originalRect; IntRect gridRect = new IntRect(0,0,width-1,depth-1); IntRect physicsRect = originalRect; int erosion = o.updateErosion ? erodeIterations : 0; #if ASTARDEBUG Matrix4x4 debugMatrix = matrix; debugMatrix *= Matrix4x4.TRS (new Vector3(0.5f,0,0.5f),Quaternion.identity,Vector3.one); originalRect.DebugDraw (debugMatrix,Color.red); #endif bool willChangeWalkability = o.updatePhysics || o.modifyWalkability; //Calculate the largest bounding box which might be affected if (o.updatePhysics && !o.modifyWalkability) { //Add the collision.diameter margin for physics calls if (collision.collisionCheck) { Vector3 margin = new Vector3 (collision.diameter,0,collision.diameter)*0.5F; min -= margin*1.02F;//0.02 safety margin, physics is rarely very accurate max += margin*1.02F; physicsRect = new IntRect( Mathf.RoundToInt (min.x-0.5F), Mathf.RoundToInt (min.z-0.5F), Mathf.RoundToInt (max.x-0.5F), Mathf.RoundToInt (max.z-0.5F) ); affectRect = IntRect.Union (physicsRect, affectRect); } } if (willChangeWalkability || erosion > 0) { //Add affect radius for erosion. +1 for updating connectivity info at the border affectRect = affectRect.Expand (erosion + 1); } IntRect clampedRect = IntRect.Intersection (affectRect,gridRect); //Mark nodes that might be changed for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { o.WillUpdateNode (nodes[z*width+x]); } } //Update Physics if (o.updatePhysics && !o.modifyWalkability) { collision.Initialize (matrix,nodeSize); clampedRect = IntRect.Intersection (physicsRect,gridRect); for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { int index = z*width+x; GridNode node = nodes[index]; UpdateNodePositionCollision (node,x,z, o.resetPenaltyOnPhysics); } } } //Apply GUO clampedRect = IntRect.Intersection (originalRect, gridRect); for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { int index = z*width+x; GridNode node = nodes[index]; if (willChangeWalkability) { node.Walkable = node.WalkableErosion; if (o.bounds.Contains ((Vector3)node.position)) o.Apply (node); node.WalkableErosion = node.Walkable; } else { if (o.bounds.Contains ((Vector3)node.position)) o.Apply (node); } } } #if ASTARDEBUG physicsRect.DebugDraw (debugMatrix,Color.blue); affectRect.DebugDraw (debugMatrix,Color.black); #endif //Recalculate connections if (willChangeWalkability && erosion == 0) { clampedRect = IntRect.Intersection (affectRect, gridRect); for (int x = clampedRect.xmin; x <= clampedRect.xmax;x++) { for (int z = clampedRect.ymin;z <= clampedRect.ymax;z++) { int index = z*width+x; GridNode node = nodes[index]; CalculateConnections (nodes,x,z,node); } } } else if (willChangeWalkability && erosion > 0) { clampedRect = IntRect.Union (originalRect, physicsRect); IntRect erosionRect1 = clampedRect.Expand (erosion); IntRect erosionRect2 = erosionRect1.Expand (erosion); erosionRect1 = IntRect.Intersection (erosionRect1,gridRect); erosionRect2 = IntRect.Intersection (erosionRect2,gridRect); #if ASTARDEBUG erosionRect1.DebugDraw (debugMatrix,Color.magenta); erosionRect2.DebugDraw (debugMatrix,Color.cyan); #endif /* all nodes inside clampedRect might have had their walkability changed all nodes inside erosionRect1 might get affected by erosion from clampedRect and erosionRect2 all nodes inside erosionRect2 (but outside erosionRect1) will be reset to previous walkability after calculation since their erosion might not be correctly calculated (nodes outside erosionRect2 would maybe have effect) */ for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { int index = z*width+x; GridNode node = nodes[index]; bool tmp = node.Walkable; node.Walkable = node.WalkableErosion; if (!erosionRect1.Contains (x,z)) { //Save the border's walkabilty data (will be reset later) node.TmpWalkable = tmp; } } } for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { int index = z*width+x; GridNode node = nodes[index]; #if ASTARDEBUG if (!node.Walkable) Debug.DrawRay ((Vector3)node.position, Vector3.up*2,Color.red); #endif CalculateConnections (nodes,x,z,node); } } //Erode the walkable area ErodeWalkableArea (erosionRect2.xmin,erosionRect2.ymin,erosionRect2.xmax+1,erosionRect2.ymax+1); for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { if (erosionRect1.Contains (x,z)) continue; int index = z*width+x; GridNode node = nodes[index]; //Restore temporarily stored data node.Walkable = node.TmpWalkable; } } //Recalculate connections of all affected nodes for (int x = erosionRect2.xmin; x <= erosionRect2.xmax;x++) { for (int z = erosionRect2.ymin;z <= erosionRect2.ymax;z++) { int index = z*width+x; GridNode node = nodes[index]; CalculateConnections (nodes,x,z,node); } } } }
public void UpdateArea (GraphUpdateObject o) { if (graphNodes == null || nodes == null) { Debug.LogWarning ("The Grid Graph is not scanned, cannot update area "); //Not scanned return; } //Copy the bounds Bounds b = o.bounds; //Matrix inverse //node.position = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F)); Vector3 min = inverseMatrix.MultiplyPoint3x4 (b.min); Vector3 max = inverseMatrix.MultiplyPoint3x4 (b.max); int minX = Mathf.RoundToInt (min.x-0.5F); int maxX = Mathf.RoundToInt (max.x-0.5F); int minZ = Mathf.RoundToInt (min.z-0.5F); int maxZ = Mathf.RoundToInt (max.z-0.5F); //We now have coordinates in local space (i.e 1 unit = 1 node) int ominx = minX; int omaxx = maxX; int ominz = minZ; int omaxz = maxZ; if (o.updatePhysics && !o.modifyWalkability) { //Add the collision.diameter margin for physics calls if (collision.collisionCheck) { Vector3 margin = new Vector3 (collision.diameter,0,collision.diameter)*0.5F; min -= margin*1.02F;//0.02 safety margin, physics is rarely very accurate max += margin*1.02F; Debug.DrawLine (matrix.MultiplyPoint3x4(min),matrix.MultiplyPoint3x4(max),Color.cyan); minX = Mathf.RoundToInt (min.x-0.5F); maxX = Mathf.RoundToInt (max.x-0.5F); minZ = Mathf.RoundToInt (min.z-0.5F); maxZ = Mathf.RoundToInt (max.z-0.5F); } collision.Initialize (matrix,nodeSize); for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0) { continue; } if (z >= depth || x >= width) { break; } int index = z*width+x; GridNode node = graphNodes[index]; //Register that this node will eventually have some settings changed o.WillUpdateNode (node); UpdateNodePositionCollision (node,x,z); } } } //This is the area inside the bounding box, call Apply on it for (int x = ominx;x <= omaxx;x++) { for (int z = ominz;z <= omaxz;z++) { if (x < 0 || z < 0) { continue; } if (z >= depth || x >= width) { break; } int index = z*width+x; GridNode node = graphNodes[index]; if (!o.updatePhysics || o.modifyWalkability) { //Register that this node will eventually have some settings changed //If the above IF evaluates to false, the node will already have been added before in the function o.WillUpdateNode (node); } o.Apply (node); } } //Recalculate connections if (o.updatePhysics || o.modifyWalkability) { //Add some margin minX--; //Mathf.Clamp (minX-1,0,width); maxX++; //Mathf.Clamp (maxX+1,0,width); minZ--; //Mathf.Clamp (minZ-1,0,depth); maxZ++; //Mathf.Clamp (maxZ+1,0,depth); for (int x = minX;x <= maxX;x++) { for (int z = minZ;z <= maxZ;z++) { if (x < 0 || z < 0 || x >= width || z >= depth) { continue; } int index = z*width+x; GridNode node = graphNodes[index]; CalculateConnections (graphNodes,x,z,node); } } } }