int GetBox ( IntRect rect ) {
			if ( count >= arr.Length ) EnsureCapacity ( count+1 );

			arr[count] = new BBTreeBox ( rect );
			count++;
			return count-1;
		}
        // Token: 0x0600251A RID: 9498 RVA: 0x0019D24C File Offset: 0x0019B44C
        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);
            });
        }
		/** Returns a new IntRect which is expanded to contain the point */
		public IntRect ExpandToContain (int x, int y) {
			var r = new IntRect(
			                        System.Math.Min(xmin,x),
			                        System.Math.Min(ymin,y),
			                        System.Math.Max(xmax,x),
			                        System.Math.Max(ymax,y)
			                        );
			return r;
		}
Beispiel #4
0
		/** All nodes inside the shape or if null, the bounding box.
		 * If a shape is supplied, it is assumed to be contained inside the bounding box.
		 * \see GraphUpdateShape.GetBounds
		 */
		private List<GraphNode> GetNodesInArea (Bounds b, GraphUpdateShape shape) {
			if (nodes == null || width*depth != nodes.Length) {
				return null;
			}

			// Get a buffer we can use
			List<GraphNode> inArea = Pathfinding.Util.ListPool<GraphNode>.Claim();

			// Take the bounds and transform it using the matrix
			// Then convert that to a rectangle which contains
			// all nodes that might be inside the 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);

			var originalRect = new IntRect(minX, minZ, maxX, maxZ);

			// Rect which covers the whole grid
			var gridRect = new IntRect(0, 0, width-1, depth-1);

			// Clamp the rect to the grid
			var rect = IntRect.Intersection(originalRect, gridRect);

			// Loop through all nodes in the rectangle
			for (int x = rect.xmin; x <= rect.xmax; x++) {
				for (int z = rect.ymin; z <= rect.ymax; z++) {
					int index = z*width+x;

					GraphNode node = nodes[index];

					// If it is contained in the bounds (and optionally the shape)
					// then add it to the buffer
					if (b.Contains((Vector3)node.position) && (shape == null || shape.Contains((Vector3)node.position))) {
						inArea.Add(node);
					}
				}
			}

			return inArea;
		}
		/** Returns the area of a rect */
		static int RectArea (IntRect r) {
			return r.Width*r.Height;
		}
			public BBTreeBox (MeshNode node) {
				this.node = node;
				var first = node.GetVertex(0);
				var min = new Int2(first.x,first.z);
				Int2 max = min;

				for (int i=1;i<node.GetVertexCount();i++) {
					var p = node.GetVertex(i);
					min.x = Math.Min (min.x,p.x);
					min.y = Math.Min (min.y,p.z);

					max.x = Math.Max (max.x,p.x);
					max.y = Math.Max (max.y,p.z);
				}

				rect = new IntRect (min.x,min.y,max.x,max.y);
				left = right = -1;
			}
Beispiel #7
0
		/** Returns an XZ bounds object with the bounds of a group of tiles.
		  * The bounds object is defined in world units.
		  */
		public Bounds GetTileBounds ( IntRect rect ) {
			return GetTileBounds (rect.xmin, rect.ymin, rect.Width, rect.Height);
		}
Beispiel #8
0
 private static bool RectIntersectsCircle(IntRect r, Vector3 p, float radius)
 {
     if (float.IsPositiveInfinity(radius))
     {
         return true;
     }
     Vector3 vector = p;
     p.x = Math.Max(p.x, (float)r.xmin * 0.001f);
     p.x = Math.Min(p.x, (float)r.xmax * 0.001f);
     p.z = Math.Max(p.z, (float)r.ymin * 0.001f);
     p.z = Math.Min(p.z, (float)r.ymax * 0.001f);
     return (p.x - vector.x) * (p.x - vector.x) + (p.z - vector.z) * (p.z - vector.z) < radius * radius;
 }
Beispiel #9
0
        public static IntRect Union(IntRect a, IntRect b)
        {
            IntRect result = new IntRect(Math.Min(a.xmin, b.xmin), Math.Min(a.ymin, b.ymin), Math.Max(a.xmax, b.xmax), Math.Max(a.ymax, b.ymax));

            return(result);
        }
Beispiel #10
0
 public static bool Intersects(IntRect a, IntRect b)
 {
     return(a.xmin <= b.xmax && a.ymin <= b.ymax && a.xmax >= b.xmin && a.ymax >= b.ymin);
 }
Beispiel #11
0
        public override bool Equals(object _b)
        {
            IntRect intRect = (IntRect)_b;

            return(this.xmin == intRect.xmin && this.xmax == intRect.xmax && this.ymin == intRect.ymin && this.ymax == intRect.ymax);
        }
Beispiel #12
0
        public IntRect ExpandToContain(int x, int y)
        {
            IntRect result = new IntRect(Math.Min(this.xmin, x), Math.Min(this.ymin, y), Math.Max(this.xmax, x), Math.Max(this.ymax, y));

            return(result);
        }
Beispiel #13
0
 public BBTreeBox(IntRect rect)
 {
     this.node = null;
     this.rect = rect;
     this.left = (this.right = -1);
 }
Beispiel #14
0
 private static int RectArea(IntRect r)
 {
     return(r.Width * r.Height);
 }
Beispiel #15
0
 private static IntRect ExpandToContain(IntRect r, IntRect r2)
 {
     return(IntRect.Union(r, r2));
 }
Beispiel #16
0
 /** Returns if the two rectangles intersect each other
  */
 public static bool Intersects(IntRect a, IntRect b)
 {
     return(!(a.xmin > b.xmax || a.ymin > b.ymax || a.xmax < b.xmin || a.ymax < b.ymin));
 }
		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;
			});
		}
Beispiel #18
0
        public override bool Equals(object _b)
        {
            IntRect rect = (IntRect)_b;

            return((((this.xmin == rect.xmin) && (this.xmax == rect.xmax)) && (this.ymin == rect.ymin)) && (this.ymax == rect.ymax));
        }
Beispiel #19
0
 public BBTreeBox(IntRect rect)
 {
     this.node = null;
     this.rect = rect;
     this.left = (this.right = -1);
 }
Beispiel #20
0
 public static bool Intersects(IntRect a, IntRect b)
 {
     return((((a.xmin <= b.xmax) && (a.ymin <= b.ymax)) && (a.xmax >= b.xmin)) && (a.ymax >= b.ymin));
 }
Beispiel #21
0
 public static IntRect Union(IntRect a, IntRect b)
 {
     return(new IntRect(Math.Min(a.xmin, b.xmin), Math.Min(a.ymin, b.ymin), Math.Max(a.xmax, b.xmax), Math.Max(a.ymax, b.ymax)));
 }
Beispiel #22
0
        public void ForceUpdate()
        {
            if (this.handler == null)
            {
                throw new Exception("Cannot update graphs. No TileHandler. Do not call the ForceUpdate method in Awake.");
            }
            this.lastUpdateTime = Time.realtimeSinceStartup;
            if (!this.handler.isValid)
            {
                if (!this.handler.graph.exists)
                {
                    this.UseSpecifiedHandler(null);
                    return;
                }
                Debug.Log("TileHandler no longer matched the underlaying graph (possibly because of a graph scan). Recreating TileHandler...");
                this.UseSpecifiedHandler(new TileHandler(this.handler.graph));
                this.handler.CreateTileTypesFromGraph();
                this.forcedReloadRects.Add(new IntRect(int.MinValue, int.MinValue, int.MaxValue, int.MaxValue));
            }
            GridLookup <NavmeshClipper> .Root allItems = this.handler.cuts.AllItems;
            if (this.forcedReloadRects.Count == 0)
            {
                int num = 0;
                for (GridLookup <NavmeshClipper> .Root root = allItems; root != null; root = root.next)
                {
                    if (root.obj.RequiresUpdate())
                    {
                        num++;
                        break;
                    }
                }
                if (num == 0)
                {
                    return;
                }
            }
            bool flag = this.handler.StartBatchLoad();

            for (int i = 0; i < this.forcedReloadRects.Count; i++)
            {
                this.handler.ReloadInBounds(this.forcedReloadRects[i]);
            }
            this.forcedReloadRects.Clear();
            for (GridLookup <NavmeshClipper> .Root root2 = allItems; root2 != null; root2 = root2.next)
            {
                if (root2.obj.RequiresUpdate())
                {
                    this.handler.ReloadInBounds(root2.previousBounds);
                    Rect    bounds = root2.obj.GetBounds(this.handler.graph.transform);
                    IntRect touchingTilesInGraphSpace = this.handler.graph.GetTouchingTilesInGraphSpace(bounds);
                    this.handler.cuts.Move(root2.obj, touchingTilesInGraphSpace);
                    this.handler.ReloadInBounds(touchingTilesInGraphSpace);
                }
            }
            for (GridLookup <NavmeshClipper> .Root root3 = allItems; root3 != null; root3 = root3.next)
            {
                if (root3.obj.RequiresUpdate())
                {
                    root3.obj.NotifyUpdated();
                }
            }
            if (flag)
            {
                this.handler.EndBatchLoad();
            }
        }
		/** Returns the difference in area between \a r and \a r expanded to contain \a r2 */
		static int ExpansionRequired (IntRect r, IntRect r2) {
			int xMin = Math.Min (r.xmin,r2.xmin);
			int xMax = Math.Max (r.xmax,r2.xmax);
			int yMin = Math.Min (r.ymin,r2.ymin);
			int yMax = Math.Max (r.ymax,r2.ymax);

			return (xMax-xMin)*(yMax-yMin)-RectArea (r);
		}
        // Token: 0x060024E4 RID: 9444 RVA: 0x0019B62C File Offset: 0x0019982C
        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);
                    }
                }
            }
        }
Beispiel #25
0
		public void UpdateAreaInit (GraphUpdateObject o) {
			
			if (!o.updatePhysics) {
				return;
			}
			
			if (!dynamic) {
				throw new System.Exception ("Recast graph must be marked as dynamic to enable graph updates");
			}
			
			AstarProfiler.Reset ();
			AstarProfiler.StartProfile ("UpdateAreaInit");
			AstarProfiler.StartProfile ("CollectMeshes");
			
			RelevantGraphSurface.UpdateAllPositions ();
			
			List<ExtraMesh> extraMeshes;
			
			Bounds b = o.bounds;
			b.center -= forcedBounds.min;
			
			//Calculate world bounds of all affected tiles
			IntRect r = new IntRect (Mathf.FloorToInt (b.min.x / (tileSizeX*cellSize)), Mathf.FloorToInt (b.min.z / (tileSizeZ*cellSize)), Mathf.FloorToInt (b.max.x / (tileSizeX*cellSize)), Mathf.FloorToInt (b.max.z / (tileSizeZ*cellSize)));
			//Clamp to bounds
			r = IntRect.Intersection (r, new IntRect (0,0,tileXCount-1,tileZCount-1));
			
			Bounds tileBounds = new Bounds();
			
			Vector3 forcedBoundsMin = forcedBounds.min;
			Vector3 forcedBoundsMax = forcedBounds.max;
			
			float tcsx = tileSizeX*cellSize;
			float tcsz = tileSizeZ*cellSize;
			
			tileBounds.SetMinMax(new Vector3 (r.xmin*tcsx, 0, r.ymin*tcsz) + forcedBoundsMin,
						new Vector3 ((r.xmax+1)*tcsx + forcedBoundsMin.x, forcedBoundsMax.y, (r.ymax+1)*tcsz + forcedBoundsMin.z)
				);
			
			int voxelCharacterRadius = Mathf.CeilToInt (characterRadius/cellSize);			
			int borderSize = voxelCharacterRadius + 3;
			
			//Expand borderSize voxels on each side
			tileBounds.Expand (new Vector3 (borderSize,0,borderSize)*cellSize*2);
			Debug.DrawLine (tileBounds.min, tileBounds.max);
			//Debug.Break ();
			
			if (!CollectMeshes (out extraMeshes, tileBounds)) {
				//return;
			}
			
			Voxelize vox = globalVox;
			
			if (vox == null) {
				
				//Create the voxelizer and set all settings
				vox = new Voxelize (cellHeight, cellSize, walkableClimb, walkableHeight, maxSlope);
				
				vox.maxEdgeLength = maxEdgeLength;
				
				if (dynamic) globalVox = vox;
				
			}
			
			vox.inputExtraMeshes = extraMeshes;
			
			AstarProfiler.EndProfile ("CollectMeshes");
			AstarProfiler.EndProfile ("UpdateAreaInit");
		}
Beispiel #26
0
 public IntRect ExpandToContain(int x, int y)
 {
     IntRect result = new IntRect(Math.Min(this.xmin, x), Math.Min(this.ymin, y), Math.Max(this.xmax, x), Math.Max(this.ymax, y));
     return result;
 }
		/** Returns if the two rectangles intersect each other
		 */
		public static bool Intersects (IntRect a, IntRect b) {
			return !(a.xmin > b.xmax || a.ymin > b.ymax || a.xmax < b.xmin || a.ymax < b.ymin);
		}
Beispiel #28
0
 public static bool Intersects(IntRect a, IntRect b)
 {
     return a.xmin <= b.xmax && a.ymin <= b.ymax && a.xmax >= b.xmin && a.ymax >= b.ymin;
 }
Beispiel #29
0
		/** All nodes inside the shape or if null, the bounding box.
		 * If a shape is supplied, it is assumed to be contained inside the bounding box.
		 * \see GraphUpdateShape.GetBounds
		 */
		private List<GraphNode> GetNodesInArea (Bounds b, GraphUpdateShape shape) {
			
			if (nodes == null || width*depth != nodes.Length) {
				return null;
			}
			
			List<GraphNode> inArea = Pathfinding.Util.ListPool<GraphNode>.Claim ();
			
			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);
			
			IntRect originalRect = new IntRect(minX,minZ,maxX,maxZ);
			IntRect gridRect = new IntRect(0,0,width-1,depth-1);
			
			IntRect rect = IntRect.Intersection (originalRect, gridRect);
			
			for (int x = rect.xmin; x <= rect.xmax;x++) {
				for (int z = rect.ymin;z <= rect.ymax;z++) {
					
					int index = z*width+x;
					
					GraphNode node = nodes[index];
					
					if (b.Contains ((Vector3)node.position) && (shape == null || shape.Contains ((Vector3)node.position))) {
						inArea.Add (node);
					}
				}
			}
			
			return inArea;
		}
Beispiel #30
0
 public static IntRect Union(IntRect a, IntRect b)
 {
     IntRect result = new IntRect(Math.Min(a.xmin, b.xmin), Math.Min(a.ymin, b.ymin), Math.Max(a.xmax, b.xmax), Math.Max(a.ymax, b.ymax));
     return result;
 }
Beispiel #31
0
        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);
                            }
                        }
                    }
                }
            }
        }
Beispiel #32
0
        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;
			});
		}
        /// <summary>Creates a list for every tile and adds every mesh that touches a tile to the corresponding list</summary>
        List <RasterizationMesh>[] PutMeshesIntoTileBuckets(List <RasterizationMesh> meshes, IntRect tileBuckets)
        {
            var bucketCount     = tileBuckets.Width * tileBuckets.Height;
            var result          = new List <RasterizationMesh> [bucketCount];
            var borderExpansion = new Vector3(1, 0, 1) * TileBorderSizeInWorldUnits * 2;

            for (int i = 0; i < result.Length; i++)
            {
                result[i] = ListPool <RasterizationMesh> .Claim();
            }

            var offset = new Int2(-tileBuckets.xmin, -tileBuckets.ymin);
            var clamp  = new IntRect(0, 0, tileBuckets.Width - 1, tileBuckets.Height - 1);

            for (int i = 0; i < meshes.Count; i++)
            {
                var mesh   = meshes[i];
                var bounds = mesh.bounds;
                // Expand borderSize voxels on each side
                bounds.Expand(borderExpansion);

                var rect = GetTouchingTiles(bounds);
                rect = IntRect.Intersection(rect.Offset(offset), clamp);
                for (int z = rect.ymin; z <= rect.ymax; z++)
                {
                    for (int x = rect.xmin; x <= rect.xmax; x++)
                    {
                        result[x + z * tileBuckets.Width].Add(mesh);
                    }
                }
            }

            return(result);
        }
Beispiel #35
0
 private static int ExpansionRequired(IntRect r, IntRect r2)
 {
     int num = Math.Min(r.xmin, r2.xmin);
     int num2 = Math.Max(r.xmax, r2.xmax);
     int num3 = Math.Min(r.ymin, r2.ymin);
     int num4 = Math.Max(r.ymax, r2.ymax);
     return (num2 - num) * (num4 - num3) - BBTree.RectArea(r);
 }
Beispiel #36
0
        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");
        }
Beispiel #37
0
 private int GetBox(IntRect rect)
 {
     if (this.count >= this.arr.Length)
     {
         this.EnsureCapacity(this.count + 1);
     }
     this.arr[this.count] = new BBTree.BBTreeBox(rect);
     this.count++;
     return this.count - 1;
 }
Beispiel #38
0
        public void AddNeighboursRec(List <QuadtreeNode> arr, QuadtreeNodeHolder holder, int depth, int x, int y, IntRect bounds, QuadtreeNode dontInclude)
        {
            int     num = 1 << Math.Min(this.editorHeightLog2, this.editorWidthLog2) - depth;
            IntRect a   = new IntRect(x, y, x + num, y + num);

            if (!IntRect.Intersects(a, bounds))
            {
                return;
            }
            if (holder.node != null)
            {
                if (holder.node != dontInclude)
                {
                    arr.Add(holder.node);
                }
            }
            else
            {
                this.AddNeighboursRec(arr, holder.c0, depth + 1, x, y, bounds, dontInclude);
                this.AddNeighboursRec(arr, holder.c1, depth + 1, x + num / 2, y, bounds, dontInclude);
                this.AddNeighboursRec(arr, holder.c2, depth + 1, x + num / 2, y + num / 2, bounds, dontInclude);
                this.AddNeighboursRec(arr, holder.c3, depth + 1, x, y + num / 2, bounds, dontInclude);
            }
        }
Beispiel #39
0
 public BBTreeBox(MeshNode node)
 {
     this.node = node;
     Int3 vertex = node.GetVertex(0);
     Int2 @int = new Int2(vertex.x, vertex.z);
     Int2 int2 = @int;
     for (int i = 1; i < node.GetVertexCount(); i++)
     {
         Int3 vertex2 = node.GetVertex(i);
         @int.x = Math.Min(@int.x, vertex2.x);
         @int.y = Math.Min(@int.y, vertex2.z);
         int2.x = Math.Max(int2.x, vertex2.x);
         int2.y = Math.Max(int2.y, vertex2.z);
     }
     this.rect = new IntRect(@int.x, @int.y, int2.x, int2.y);
     this.left = (this.right = -1);
 }
Beispiel #40
0
 public BBTreeBox(IntRect rect)
 {
     this.nodeOffset = -1;
     this.rect       = rect;
     this.left       = (this.right = -1);
 }
Beispiel #41
0
		/** Returns a rect containing the indices of all tiles by rounding the specified bounds to tile borders */
		public IntRect GetTouchingTilesRound ( Bounds b ) {
			b.center -= forcedBounds.min;

			//Calculate world bounds of all affected tiles
			var r = new IntRect (Mathf.RoundToInt (b.min.x / (tileSizeX*cellSize)), Mathf.RoundToInt (b.min.z / (tileSizeZ*cellSize)), Mathf.RoundToInt (b.max.x / (tileSizeX*cellSize))-1, Mathf.RoundToInt (b.max.z / (tileSizeZ*cellSize))-1);
			//Clamp to bounds
			r = IntRect.Intersection (r, new IntRect (0,0,tileXCount-1,tileZCount-1));
			return r;
		}
Beispiel #42
0
        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);
            });
        }
			public BBTreeBox (IntRect rect) {
				node = null;
				this.rect = rect;
				left = right = -1;
			}
Beispiel #44
0
        /// <summary>Async method for moving the graph</summary>
        IEnumerator UpdateGraphCoroutine()
        {
            // Find the direction that we want to move the graph in.
            // Calcuculate this in graph space (where a distance of one is the size of one node)
            Vector3 dir = PointToGraphSpace(target.position) - PointToGraphSpace(graph.center);

            // Snap to a whole number of nodes
            dir.x = Mathf.Round(dir.x);
            dir.z = Mathf.Round(dir.z);
            dir.y = 0;

            // Nothing do to
            if (dir == Vector3.zero)
            {
                yield break;
            }

            // Number of nodes to offset in each direction
            Int2 offset = new Int2(-Mathf.RoundToInt(dir.x), -Mathf.RoundToInt(dir.z));

            // Move the center (this is in world units, so we need to convert it back from graph space)
            graph.center += graph.transform.TransformVector(dir);
            graph.UpdateTransform();

            // Cache some variables for easier access
            int width = graph.width;
            int depth = graph.depth;

            GridNodeBase[] nodes;
            // Layers are required when handling LayeredGridGraphs
            int layers = graph.LayerCount;

            nodes = graph.nodes;

            // Create a temporary buffer required for the calculations
            if (buffer == null || buffer.Length != width * depth)
            {
                buffer = new GridNodeBase[width * depth];
            }

            // Check if we have moved less than a whole graph width all directions
            // If we have moved more than this we can just as well recalculate the whole graph
            if (Mathf.Abs(offset.x) <= width && Mathf.Abs(offset.y) <= depth)
            {
                IntRect recalculateRect = new IntRect(0, 0, offset.x, offset.y);

                // If offset.x < 0, adjust the rect
                if (recalculateRect.xmin > recalculateRect.xmax)
                {
                    int tmp2 = recalculateRect.xmax;
                    recalculateRect.xmax = width + recalculateRect.xmin;
                    recalculateRect.xmin = width + tmp2;
                }

                // If offset.y < 0, adjust the rect
                if (recalculateRect.ymin > recalculateRect.ymax)
                {
                    int tmp2 = recalculateRect.ymax;
                    recalculateRect.ymax = depth + recalculateRect.ymin;
                    recalculateRect.ymin = depth + tmp2;
                }

                // Connections need to be recalculated for the neighbours as well, so we need to expand the rect by 1
                var connectionRect = recalculateRect.Expand(1);

                // Makes sure the rect stays inside the grid
                connectionRect = IntRect.Intersection(connectionRect, new IntRect(0, 0, width, depth));

                // Offset each node by the #offset variable
                // nodes which would end up outside the graph
                // will wrap around to the other side of it
                for (int l = 0; l < layers; l++)
                {
                    int layerOffset = l * width * depth;
                    for (int z = 0; z < depth; z++)
                    {
                        int pz = z * width;
                        int tz = ((z + offset.y + depth) % depth) * width;
                        for (int x = 0; x < width; x++)
                        {
                            buffer[tz + ((x + offset.x + width) % width)] = nodes[layerOffset + pz + x];
                        }
                    }

                    yield return(null);

                    // Copy the nodes back to the graph
                    // and set the correct indices
                    for (int z = 0; z < depth; z++)
                    {
                        int pz = z * width;
                        for (int x = 0; x < width; x++)
                        {
                            int newIndex = pz + x;
                            var node     = buffer[newIndex];
                            if (node != null)
                            {
                                node.NodeInGridIndex = newIndex;
                            }
                            nodes[layerOffset + newIndex] = node;
                        }

                        // Calculate the limits for the region that has been wrapped
                        // to the other side of the graph
                        int xmin, xmax;
                        if (z >= recalculateRect.ymin && z < recalculateRect.ymax)
                        {
                            xmin = 0;
                            xmax = depth;
                        }
                        else
                        {
                            xmin = recalculateRect.xmin;
                            xmax = recalculateRect.xmax;
                        }

                        for (int x = xmin; x < xmax; x++)
                        {
                            var node = buffer[pz + x];
                            if (node != null)
                            {
                                // Clear connections on all nodes that are wrapped and placed on the other side of the graph.
                                // This is both to clear any custom connections (which do not really make sense after moving the node)
                                // and to prevent possible exceptions when the node will later (possibly) be destroyed because it was
                                // not needed anymore (only for layered grid graphs).
                                node.ClearConnections(false);
                            }
                        }
                    }

                    yield return(null);
                }

                // The calculation will only update approximately this number of
                // nodes per frame. This is used to keep CPU load per frame low
                int yieldEvery = 1000;
                // To avoid the update taking too long, make yieldEvery somewhat proportional to the number of nodes that we are going to update
                int approxNumNodesToUpdate = Mathf.Max(Mathf.Abs(offset.x), Mathf.Abs(offset.y)) * Mathf.Max(width, depth);
                yieldEvery = Mathf.Max(yieldEvery, approxNumNodesToUpdate / 10);
                int counter = 0;

                // Recalculate the nodes
                // Take a look at the image in the docs for the UpdateGraph method
                // to see which nodes are being recalculated.
                for (int z = 0; z < depth; z++)
                {
                    int xmin, xmax;
                    if (z >= recalculateRect.ymin && z < recalculateRect.ymax)
                    {
                        xmin = 0;
                        xmax = width;
                    }
                    else
                    {
                        xmin = recalculateRect.xmin;
                        xmax = recalculateRect.xmax;
                    }

                    for (int x = xmin; x < xmax; x++)
                    {
                        graph.RecalculateCell(x, z, false, false);
                    }

                    counter += (xmax - xmin);

                    if (counter > yieldEvery)
                    {
                        counter = 0;
                        yield return(null);
                    }
                }

                for (int z = 0; z < depth; z++)
                {
                    int xmin, xmax;
                    if (z >= connectionRect.ymin && z < connectionRect.ymax)
                    {
                        xmin = 0;
                        xmax = width;
                    }
                    else
                    {
                        xmin = connectionRect.xmin;
                        xmax = connectionRect.xmax;
                    }

                    for (int x = xmin; x < xmax; x++)
                    {
                        graph.CalculateConnections(x, z);
                    }

                    counter += (xmax - xmin);

                    if (counter > yieldEvery)
                    {
                        counter = 0;
                        yield return(null);
                    }
                }

                yield return(null);

                // Calculate all connections for the nodes along the boundary
                // of the graph, these always need to be updated
                /// <summary>TODO: Optimize to not traverse all nodes in the graph, only those at the edges</summary>
                for (int z = 0; z < depth; z++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        if (x == 0 || z == 0 || x == width - 1 || z == depth - 1)
                        {
                            graph.CalculateConnections(x, z);
                        }
                    }
                }
            }
            else
            {
                // The calculation will only update approximately this number of
                // nodes per frame. This is used to keep CPU load per frame low
                int yieldEvery = Mathf.Max(depth * width / 20, 1000);
                int counter    = 0;
                // Just update all nodes
                for (int z = 0; z < depth; z++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        graph.RecalculateCell(x, z);
                    }
                    counter += width;
                    if (counter > yieldEvery)
                    {
                        counter = 0;
                        yield return(null);
                    }
                }

                // Recalculate the connections of all nodes
                for (int z = 0; z < depth; z++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        graph.CalculateConnections(x, z);
                    }
                    counter += width;
                    if (counter > yieldEvery)
                    {
                        counter = 0;
                        yield return(null);
                    }
                }
            }
        }
		/** Returns true if \a p is within \a radius from \a r.
		 * Correctly handles cases where \a radius is positive infinity.
		  */
		static bool RectIntersectsCircle (IntRect r, Vector3 p, float radius) {

			if (float.IsPositiveInfinity(radius)) return true;

			Vector3 po = p;
			p.x = Math.Max (p.x, r.xmin*Int3.PrecisionFactor);
			p.x = Math.Min (p.x, r.xmax*Int3.PrecisionFactor);
			p.z = Math.Max (p.z, r.ymin*Int3.PrecisionFactor);
			p.z = Math.Min (p.z, r.ymax*Int3.PrecisionFactor);

			// XZ squared magnitude comparison
			return (p.x-po.x)*(p.x-po.x) + (p.z-po.z)*(p.z-po.z) < radius*radius;
		}
Beispiel #46
0
        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);
            });
        }
		/** Returns a new rect which contains both \a r and \a r2 */
		static IntRect ExpandToContain (IntRect r, IntRect r2) {
			return IntRect.Union(r,r2);
		}
Beispiel #48
0
 public BBTreeBox(IntRect rect)
 {
     nodeOffset = -1;
     this.rect  = rect;
     left       = right = -1;
 }
Beispiel #49
0
		public void AddNeighboursRec (List<QuadtreeNode> arr, QuadtreeNodeHolder holder, int depth, int x, int y, IntRect bounds, QuadtreeNode dontInclude) {
			var width = 1 << (Math.Min (editorHeightLog2,editorWidthLog2)-depth);
			var r = new IntRect(x,y,x+width,y+width);
			if (!IntRect.Intersects (r,bounds)) return;
			
			if (holder.node != null) {
				if (holder.node != dontInclude) {
					arr.Add (holder.node);
				}
			} else {
				AddNeighboursRec (arr, holder.c0, depth+1,x        , y          , bounds, dontInclude);
				AddNeighboursRec (arr, holder.c1, depth+1,x+width/2, y          , bounds, dontInclude);
				AddNeighboursRec (arr, holder.c2, depth+1,x+width/2, y + width/2, bounds, dontInclude);
				AddNeighboursRec (arr, holder.c3, depth+1,x        , y + width/2, bounds, dontInclude);
			}
		}
Beispiel #50
0
 public BBTreeBox(int nodeOffset, IntRect rect)
 {
     this.nodeOffset = nodeOffset;
     this.rect       = rect;
     left            = right = -1;
 }
Beispiel #51
0
		public void UpdateArea (GraphUpdateObject guo) {
			
			Bounds b = guo.bounds;
			b.center -= forcedBounds.min;
			
			//Figure out which tiles are affected
			IntRect r = new IntRect (Mathf.FloorToInt (b.min.x / (tileSizeX*cellSize)), Mathf.FloorToInt (b.min.z / (tileSizeZ*cellSize)), Mathf.FloorToInt (b.max.x / (tileSizeX*cellSize)), Mathf.FloorToInt (b.max.z / (tileSizeZ*cellSize)));
			//Clamp to bounds
			r = IntRect.Intersection (r, new IntRect (0,0,tileXCount-1,tileZCount-1));
			
			if (!guo.updatePhysics) {
				
				
				for ( int z=r.ymin;z<=r.ymax;z++) {
					for ( int x=r.xmin;x<=r.xmax;x++) {
						NavmeshTile tile = tiles[z*tileXCount + x];
						tile.flag = true;
					}
				}
				
				for ( int z=r.ymin;z<=r.ymax;z++) {
					for ( int x=r.xmin;x<=r.xmax;x++) {
						NavmeshTile tile = tiles[z*tileXCount + x];
						if ( tile.flag ) {
							tile.flag = false;
							
							NavMeshGraph.UpdateArea (guo, tile);
						}
					}
				}
				
				return;
			}
			
			if (!dynamic) {
				throw new System.Exception ("Recast graph must be marked as dynamic to enable graph updates with updatePhysics = true");
			}
			
			Voxelize vox = globalVox;
			
			if (vox == null) {
				throw new System.InvalidOperationException ("No Voxelizer object. UpdateAreaInit should have been called before this function.");
			}
			
			
			
			AstarProfiler.StartProfile ("Init");
				
			/** \bug No bounds checking */
			
			//r.DebugDraw (Matrix4x4.TRS (forcedBounds.min, Quaternion.identity, new Vector3 (tileSize*cellSize, 1, tileSize*cellSize)), Color.red);
			
			//Debug.Break ();
			
			
			
			AstarProfiler.StartProfile ("RemoveConnections");
			
			
			
			for (int x=r.xmin;x<=r.xmax;x++) {
				for (int z=r.ymin;z<=r.ymax;z++) {
					RemoveConnectionsFromTile (tiles[x + z*tileXCount]);
				}
			}
			
			
			
			AstarProfiler.EndProfile ("RemoveConnections");
			
			AstarProfiler.StartProfile ("Build Tiles");
			
			for (int x=r.xmin;x<=r.xmax;x++) {
				for (int z=r.ymin;z<=r.ymax;z++) {
					BuildTileMesh (vox, x,z);
				}
			}
			
			
			
			AstarProfiler.EndProfile ("Build Tiles");
			
			
			AstarProfiler.StartProfile ("ConnectTiles");
			uint graphIndex = (uint)AstarPath.active.astarData.GetGraphIndex (this);
			
			for (int x=r.xmin;x<=r.xmax;x++) {
				for (int z=r.ymin;z<=r.ymax;z++) {
					NavmeshTile tile = tiles[x + z*tileXCount];
					GraphNode[] nodes = tile.nodes;
					
					for (int i=0;i<nodes.Length;i++) nodes[i].GraphIndex = graphIndex;
				}
			}
			
			
			
			//Connect the newly create tiles with the old tiles and with each other
			r = r.Expand (1);
			//Clamp to bounds
			r = IntRect.Intersection (r, new IntRect (0,0,tileXCount-1,tileZCount-1));
			
			for (int x=r.xmin;x<=r.xmax;x++) {
				for (int z=r.ymin;z<=r.ymax;z++) {
					if (x < tileXCount-1 && r.Contains (x+1, z)) {
						ConnectTiles (tiles[x + z*tileXCount], tiles[x+1 + z*tileXCount]);
					}
					if (z < tileZCount-1 && r.Contains (x, z+1)) {
						ConnectTiles (tiles[x + z*tileXCount], tiles[x + (z+1)*tileXCount]);
					}
				}
			}
			
			AstarProfiler.EndProfile ("ConnectTiles");
			AstarProfiler.PrintResults ();
		}
        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));
            VInt3   a      = new VInt3(r2.xmin, 0, r2.ymin);
            VInt3   b      = new VInt3(r2.xmin, 0, r2.ymax);
            VInt3   c      = new VInt3(r2.xmax, 0, r2.ymin);
            VInt3   d      = new VInt3(r2.xmax, 0, r2.ymax);
            VInt3   ia     = a;
            VInt3   ib     = b;
            VInt3   ic     = c;
            VInt3   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++)
                {
                    VInt3 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) ? 0 : (j + 1);
                    VInt3 vertex2 = triangleMeshNode.GetVertex(j);
                    VInt3 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 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");
		
		}
Beispiel #54
0
        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) ? (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;
                }
                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);
            });
        }
		/** Returns a new rect which contains both input rects.
		 * This rectangle may contain areas outside both input rects as well in some cases.
		 */
		public static IntRect Union (IntRect a, IntRect b) {
			var r = new IntRect(
			                        System.Math.Min(a.xmin,b.xmin),
			                        System.Math.Min(a.ymin,b.ymin),
			                        System.Math.Max(a.xmax,b.xmax),
			                        System.Math.Max(a.ymax,b.ymax)
			                        );

			return r;
		}
Beispiel #56
0
        public override bool Equals(System.Object _b)
        {
            IntRect b = (IntRect)_b;

            return(xmin == b.xmin && xmax == b.xmax && ymin == b.ymin && ymax == b.ymax);
        }
        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");
        }
        public void AddNeighboursRec(List <QuadtreeNode> arr, QuadtreeNodeHolder holder, int depth, int x, int y, IntRect bounds, QuadtreeNode dontInclude)
        {
            int width = 1 << (System.Math.Min(editorHeightLog2, editorWidthLog2) - depth);
            var r     = new IntRect(x, y, x + width, y + width);

            if (!IntRect.Intersects(r, bounds))
            {
                return;
            }

            if (holder.node != null)
            {
                if (holder.node != dontInclude)
                {
                    arr.Add(holder.node);
                }
            }
            else
            {
                AddNeighboursRec(arr, holder.c0, depth + 1, x, y, bounds, dontInclude);
                AddNeighboursRec(arr, holder.c1, depth + 1, x + width / 2, y, bounds, dontInclude);
                AddNeighboursRec(arr, holder.c2, depth + 1, x + width / 2, y + width / 2, bounds, dontInclude);
                AddNeighboursRec(arr, holder.c3, depth + 1, x, y + width / 2, bounds, dontInclude);
            }
        }
Beispiel #59
0
		/** 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);
					}
				}
			}
		}
Beispiel #60
0
 public BBTreeBox(IntRect rect)
 {
     node      = null;
     this.rect = rect;
     left      = right = -1;
 }