Beispiel #1
0
        /// <summary>
        /// Sets connection data to a span contained in a neighboring cell.
        /// </summary>
        /// <param name="dir">The direction of the cell.</param>
        /// <param name="i">The index of the span in the neighboring cell.</param>
        /// <param name="s">The <see cref="CompactSpan"/> to set the data for.</param>
        public static void SetConnection(Direction dir, int i, ref CompactSpan s)
        {
            if (i >= NotConnected)
            {
                throw new ArgumentOutOfRangeException("Index of connecting span is too high to be stored. Try increasing cell height.", "i");
            }

            switch (dir)
            {
            case Direction.West:
                s.ConnectionWest = (byte)i;
                break;

            case Direction.North:
                s.ConnectionNorth = (byte)i;
                break;

            case Direction.East:
                s.ConnectionEast = (byte)i;
                break;

            case Direction.South:
                s.ConnectionSouth = (byte)i;
                break;

            default:
                throw new ArgumentException("dir isn't a valid Direction.");
            }
        }
Beispiel #2
0
		public void AddCompactSpan_NoUpperLimit_Success()
		{
			CompactSpan cs = new CompactSpan(10, int.MaxValue);

			Assert.IsFalse(cs.HasUpperBound);
			Assert.AreEqual(cs.ConnectionCount, 0);
		}
Beispiel #3
0
		public void AddCompactSpan_SetConnection_Success()
		{
			CompactSpan cs = new CompactSpan(10, int.MaxValue);
			CompactSpan.SetConnection((Direction)1, 1, ref cs);

			Assert.AreEqual(cs.ConnectionCount, 1);
		}
Beispiel #4
0
		public void AddCompactSpan_GetConnection_Success()
		{
			CompactSpan cs = new CompactSpan(10, int.MaxValue);
			CompactSpan.SetConnection((Direction)1, 50, ref cs);

			Assert.AreEqual(CompactSpan.GetConnection(ref cs, (Direction)1), 50);
			Assert.AreEqual(cs.GetConnection((Direction)1), 50);
		}
Beispiel #5
0
		public void AddCompactSpan_IsConnected_Success()
		{
			CompactSpan cs = new CompactSpan(10, int.MaxValue);
			CompactSpan.SetConnection(Direction.East, 1, ref cs);

			Assert.IsTrue(cs.IsConnected(Direction.East));
			Assert.IsFalse(cs.IsConnected(Direction.West));
		}
Beispiel #6
0
 /// <summary>
 /// Creates a <see cref="CompactSpan"/> from a minimum boundary and a maximum boundary.
 /// </summary>
 /// <param name="min">The minimum.</param>
 /// <param name="max">The maximum.</param>
 /// <param name="span">A <see cref="CompactSpan"/>.</param>
 public static void FromMinMax(int min, int max, out CompactSpan span)
 {
     span.Minimum         = min;
     span.Height          = max - min;
     span.ConnectionWest  = NotConnected;
     span.ConnectionNorth = NotConnected;
     span.ConnectionEast  = NotConnected;
     span.ConnectionSouth = NotConnected;
     span.Region          = RegionId.Null;
 }
Beispiel #7
0
        /// <summary>
        /// Gets the connection data for a neighboring cell in a specified direction.
        /// </summary>
        /// <param name="s">The <see cref="CompactSpan"/> to get the connection data from.</param>
        /// <param name="dir">The direction.</param>
        /// <returns>The index of the span in the neighboring cell.</returns>
        public static int GetConnection(ref CompactSpan s, Direction dir)
        {
            switch (dir)
            {
            case Direction.West:
                return(s.ConnectionWest);

            case Direction.North:
                return(s.ConnectionNorth);

            case Direction.East:
                return(s.ConnectionEast);

            case Direction.South:
                return(s.ConnectionSouth);

            default:
                throw new ArgumentException("dir isn't a valid Direction.");
            }
        }
Beispiel #8
0
 /// <summary>
 /// If two CompactSpans overlap, find the maximum of the new overlapping CompactSpans.
 /// </summary>
 /// <param name="left">The first CompactSpan</param>
 /// <param name="right">The second CompactSpan</param>
 /// <param name="max">The maximum of the overlapping CompactSpans</param>
 public static void OverlapMax(ref CompactSpan left, ref CompactSpan right, out int max)
 {
     if (left.Height == int.MaxValue)
     {
         if (right.Height == int.MaxValue)
         {
             max = int.MaxValue;
         }
         else
         {
             max = right.Minimum + right.Height;
         }
     }
     else if (right.Height == int.MaxValue)
     {
         max = left.Minimum + left.Height;
     }
     else
     {
         max = Math.Min(left.Minimum + left.Height, right.Minimum + right.Height);
     }
 }
Beispiel #9
0
        /// <summary>
        /// Un-sets connection data from a neighboring cell.
        /// </summary>
        /// <param name="dir">The direction of the cell.</param>
        /// <param name="s">The <see cref="CompactSpan"/> to set the data for.</param>
        public static void UnsetConnection(Direction dir, ref CompactSpan s)
        {
            switch (dir)
            {
            case Direction.West:
                s.ConnectionWest = NotConnected;
                break;

            case Direction.North:
                s.ConnectionNorth = NotConnected;
                break;

            case Direction.East:
                s.ConnectionEast = NotConnected;
                break;

            case Direction.South:
                s.ConnectionSouth = NotConnected;
                break;

            default:
                throw new ArgumentException("dir isn't a valid Direction.");
            }
        }
Beispiel #10
0
		/// <summary>
		/// Un-sets connection data from a neighboring cell.
		/// </summary>
		/// <param name="dir">The direction of the cell.</param>
		/// <param name="s">The <see cref="CompactSpan"/> to set the data for.</param>
		public static void UnsetConnection(Direction dir, ref CompactSpan s)
		{
			switch (dir)
			{
				case Direction.West:
					s.ConnectionWest = NotConnected;
					break;
				case Direction.North:
					s.ConnectionNorth = NotConnected;
					break;
				case Direction.East:
					s.ConnectionEast = NotConnected;
					break;
				case Direction.South:
					s.ConnectionSouth = NotConnected;
					break;
				default:
					throw new ArgumentException("dir isn't a valid Direction.");
			}
		}
Beispiel #11
0
		/// <summary>
		/// Sets connection data to a span contained in a neighboring cell.
		/// </summary>
		/// <param name="dir">The direction of the cell.</param>
		/// <param name="i">The index of the span in the neighboring cell.</param>
		/// <param name="s">The <see cref="CompactSpan"/> to set the data for.</param>
		public static void SetConnection(Direction dir, int i, ref CompactSpan s)
		{
			if (i >= NotConnected)
				throw new ArgumentOutOfRangeException("Index of connecting span is too high to be stored. Try increasing cell height.", "i");

			switch (dir)
			{
				case Direction.West:
					s.ConnectionWest = (byte)i;
					break;
				case Direction.North:
					s.ConnectionNorth = (byte)i;
					break;
				case Direction.East:
					s.ConnectionEast = (byte)i;
					break;
				case Direction.South:
					s.ConnectionSouth = (byte)i;
					break;
				default:
					throw new ArgumentException("dir isn't a valid Direction.");
			}
		}
Beispiel #12
0
		/// <summary>
		/// Creates a <see cref="CompactSpan"/> from a minimum boundary and a maximum boundary.
		/// </summary>
		/// <param name="min">The minimum.</param>
		/// <param name="max">The maximum.</param>
		/// <param name="span">A <see cref="CompactSpan"/>.</param>
		public static void FromMinMax(int min, int max, out CompactSpan span)
		{
			span.Minimum = min;
			span.Height = max - min;
			span.ConnectionWest = NotConnected;
			span.ConnectionNorth = NotConnected;
			span.ConnectionEast = NotConnected;
			span.ConnectionSouth = NotConnected;
			span.Region = RegionId.Null;
		}
Beispiel #13
0
		/// <summary>
		/// If two CompactSpans overlap, find the maximum of the new overlapping CompactSpans.
		/// </summary>
		/// <param name="left">The first CompactSpan</param>
		/// <param name="right">The second CompactSpan</param>
		/// <param name="max">The maximum of the overlapping CompactSpans</param>
		public static void OverlapMax(ref CompactSpan left, ref CompactSpan right, out int max)
		{
			if (left.Height == int.MaxValue)
			{
				if (right.Height == int.MaxValue)
					max = int.MaxValue;
				else
					max = right.Minimum + right.Height;
			}
			else if (right.Height == int.MaxValue)
				max = left.Minimum + left.Height;
			else
				max = Math.Min(left.Minimum + left.Height, right.Minimum + right.Height);
		}
Beispiel #14
0
		/// <summary>
		/// If two CompactSpans overlap, find the minimum of the new overlapping CompactSpans.
		/// </summary>
		/// <param name="left">The first CompactSpan</param>
		/// <param name="right">The second CompactSpan</param>
		/// <param name="min">The minimum of the overlapping ComapctSpans</param>
		public static void OverlapMin(ref CompactSpan left, ref CompactSpan right, out int min)
		{
			min = Math.Max(left.Minimum, right.Minimum);
		}
Beispiel #15
0
		public void SetConnection_InvalidDirection_Success()
		{
			CompactSpan cs = new CompactSpan(10, int.MaxValue);
			Assert.Throws<ArgumentException>(() => CompactSpan.SetConnection((Direction)(-1), 1, ref cs));	
		}
Beispiel #16
0
		public void SetConnection_TooHigh_Success()
		{
			CompactSpan cs = new CompactSpan(10, int.MaxValue);
			Assert.Throws<ArgumentOutOfRangeException>(() => CompactSpan.SetConnection((Direction)2, 300, ref cs));
		}
Beispiel #17
0
		/// <summary>
		/// Gets the connection data for a neighboring cell in a specified direction.
		/// </summary>
		/// <param name="s">The <see cref="CompactSpan"/> to get the connection data from.</param>
		/// <param name="dir">The direction.</param>
		/// <returns>The index of the span in the neighboring cell.</returns>
		public static int GetConnection(ref CompactSpan s, Direction dir)
		{
			switch (dir)
			{
				case Direction.West:
					return s.ConnectionWest;
				case Direction.North:
					return s.ConnectionNorth;
				case Direction.East:
					return s.ConnectionEast;
				case Direction.South:
					return s.ConnectionSouth;
				default:
					throw new ArgumentException("dir isn't a valid Direction.");
			}
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="CompactHeightfield"/> class.
        /// </summary>
        /// <param name="field">A <see cref="Heightfield"/> to build from.</param>
        /// <param name="walkableHeight">The maximum difference in height to filter.</param>
        /// <param name="walkableClimb">The maximum difference in slope to filter.</param>
        public CompactHeightfield(Heightfield field, int walkableHeight, int walkableClimb)
        {
            this.bounds = field.Bounds;
            this.width = field.Width;
            this.height = field.Height;
            this.length = field.Length;
            this.cellSize = field.CellSizeXZ;
            this.cellHeight = field.CellHeight;

            int spanCount = field.SpanCount;
            cells = new CompactCell[width * length];
            spans = new CompactSpan[spanCount];
            areas = new Area[spanCount];

            //iterate over the Heightfield's cells
            int spanIndex = 0;
            for (int i = 0; i < cells.Length; i++)
            {
                //get the heightfield span list, skip if empty
                var fs = field[i].Spans;
                if (fs.Count == 0)
                    continue;

                CompactCell c = new CompactCell(spanIndex, 0);

                //convert the closed spans to open spans
                int lastInd = fs.Count - 1;
                for (int j = 0; j < lastInd; j++)
                {
                    var s = fs[j];
                    if (s.Area.IsWalkable)
                    {
                        CompactSpan.FromMinMax(s.Maximum, fs[j + 1].Minimum, out spans[spanIndex]);
                        areas[spanIndex] = s.Area;
                        spanIndex++;
                        c.Count++;
                    }
                }

                //the last closed span that has an "infinite" height
                var lastS = fs[lastInd];
                if (lastS.Area.IsWalkable)
                {
                    spans[spanIndex] = new CompactSpan(fs[lastInd].Maximum, int.MaxValue);
                    areas[spanIndex] = lastS.Area;
                    spanIndex++;
                    c.Count++;
                }

                cells[i] = c;
            }

            //set neighbor connections
            for (int z = 0; z < length; z++)
            {
                for (int x = 0; x < width; x++)
                {
                    CompactCell c = cells[z * width + x];
                    for (int i = c.StartIndex, end = c.StartIndex + c.Count; i < end; i++)
                    {
                        CompactSpan s = spans[i];

                        for (var dir = Direction.West; dir <= Direction.South; dir++)
                        {
                            int dx = x + dir.GetHorizontalOffset();
                            int dz = z + dir.GetVerticalOffset();

                            if (dx < 0 || dz < 0 || dx >= width || dz >= length)
                                continue;

                            CompactCell dc = cells[dz * width + dx];
                            for (int j = dc.StartIndex, cellEnd = dc.StartIndex + dc.Count; j < cellEnd; j++)
                            {
                                CompactSpan ds = spans[j];

                                int overlapBottom, overlapTop;
                                CompactSpan.OverlapMin(ref s, ref ds, out overlapBottom);
                                CompactSpan.OverlapMax(ref s, ref ds, out overlapTop);

                                //Make sure that the agent can walk to the next span and that the span isn't a huge drop or climb
                                if ((overlapTop - overlapBottom) >= walkableHeight && Math.Abs(ds.Minimum - s.Minimum) <= walkableClimb)
                                {
                                    int con = j - dc.StartIndex;
                                    CompactSpan.SetConnection(dir, con, ref spans[i]);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #19
0
 /// <summary>
 /// If two CompactSpans overlap, find the minimum of the new overlapping CompactSpans.
 /// </summary>
 /// <param name="left">The first CompactSpan</param>
 /// <param name="right">The second CompactSpan</param>
 /// <param name="min">The minimum of the overlapping ComapctSpans</param>
 public static void OverlapMin(ref CompactSpan left, ref CompactSpan right, out int min)
 {
     min = Math.Max(left.Minimum, right.Minimum);
 }