using System.Buffers; namespace Sandbox.Navigation.Generation; [SkipHotload] internal class ContourSet : IDisposable { /// /// A list of the contours in the set. /// public List Contours = new List( 128 ); /// /// The minimum bounds in world space. [(x, y, z)] /// public Vector3 BMin = new Vector3(); /// /// The maximum bounds in world space. [(x, y, z)] /// public Vector3 BMax = new Vector3(); /// /// The size of each cell. (On the xz-plane.) /// public float CellSize; /// /// The height of each cell. (The minimum increment along the y-axis.) */ /// public float CellHeight; /// /// The width of the set. (Along the x-axis in cell units.) /// public int Width; /// /// The height of the set. (Along the z-axis in cell units.) /// public int Height; /// /// The AABB border size used to generate the source data from which the contours were derived. /// public int BorderSize; /// /// The max edge error that this contour set was simplified with. /// public float MaxError; public void Clear() { Contours.Clear(); } public void Dispose() { foreach ( var c in Contours ) { c.Dispose(); } } } [SkipHotload] internal class Contour : IDisposable { public Span Vertices => verticesArray.AsSpan( 0, VertexCount * 4 ); //< Simplified contour vertex and connection data. [Size: 4 * #nverts] private int[] verticesArray; public int VertexCount { get; private set; } //< The number of vertices in the simplified contour. public int Region; //< The region id of the contour. public int Area; //< The area id of the contour. public Contour( int vertexCount ) { VertexCount = vertexCount; verticesArray = ArrayPool.Shared.Rent( vertexCount * 4 ); } public void Dispose() { if ( verticesArray != null ) { ArrayPool.Shared.Return( verticesArray ); verticesArray = null; } } public static void MergeContours( Contour ca, Contour cb, int ia, int ib ) { int maxVerts = ca.VertexCount + cb.VertexCount + 2; int[] vertsArr = ArrayPool.Shared.Rent( maxVerts * 4 ); int nv = 0; // Copy contour A. for ( int i = 0; i <= ca.VertexCount; ++i ) { int dst = nv * 4; int src = ((ia + i) % ca.VertexCount) * 4; vertsArr[dst + 0] = ca.Vertices[src + 0]; vertsArr[dst + 1] = ca.Vertices[src + 1]; vertsArr[dst + 2] = ca.Vertices[src + 2]; vertsArr[dst + 3] = ca.Vertices[src + 3]; nv++; } // Copy contour B for ( int i = 0; i <= cb.VertexCount; ++i ) { int dst = nv * 4; int src = ((ib + i) % cb.VertexCount) * 4; vertsArr[dst + 0] = cb.Vertices[src + 0]; vertsArr[dst + 1] = cb.Vertices[src + 1]; vertsArr[dst + 2] = cb.Vertices[src + 2]; vertsArr[dst + 3] = cb.Vertices[src + 3]; nv++; } if ( ca.verticesArray != null ) { ArrayPool.Shared.Return( ca.verticesArray ); } ca.verticesArray = vertsArr; ca.VertexCount = nv; cb.Dispose(); cb.VertexCount = 0; } }