// Copyright (c) 2013-2015 Robert Rouhani and other contributors (see CONTRIBUTORS file). // Licensed under the MIT License - https://raw.github.com/Robmaister/SharpNav/master/LICENSE using System; using System.Collections.Generic; using System.Linq; using SharpNav.Geometry; #if MONOGAME using Vector3 = Microsoft.Xna.Framework.Vector3; #elif OPENTK using Vector3 = OpenTK.Vector3; #elif SHARPDX using Vector3 = SharpDX.Vector3; #endif namespace SharpNav { /// /// A class that filters geometry and applies an to it. /// public class AreaGenerator { private IEnumerable tris; private int triCount; private List, Area>> conditions; private Area defaultArea; /// /// Initializes a new instance of the class. /// /// collection of Triangles. /// The number of triangles to enumerate.. /// Default area. private AreaGenerator(IEnumerable verts, int triCount, Area defaultArea) { this.tris = verts; this.triCount = triCount; this.defaultArea = defaultArea; conditions = new List, Area>>(); } /// /// Create instance from the specified triangles with specified area. /// /// Collection of Triangles. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(IEnumerable tris, Area area) { return new AreaGenerator(tris, tris.Count(), area); } /// /// Create instance from triCount(a integer) specified triangles with specified area /// /// Collection of Triangles. /// The number of triangles to enumerate. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(IEnumerable tris, int triCount, Area area) { return new AreaGenerator(tris, triCount, area); } /// /// Create instance from every specified triangles in array of tris with specified area. /// /// An array of triangles. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(Triangle3[] tris, Area area) { return new AreaGenerator(TriangleEnumerable.FromTriangle(tris, 0, tris.Length), tris.Length, area); } /// /// Create instance from specified triangles in array of tris from tris[triOffset] to tris[triOffset+triCount] with specified area. /// /// An array of triangles. /// Tri offset. /// Tri count. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(Triangle3[] tris, int triOffset, int triCount, Area area) { return new AreaGenerator(TriangleEnumerable.FromTriangle(tris, triOffset, triCount), triCount, area); } /// /// Create instance from the triangles created from points in verts with specified area /// /// An array of Vectors3. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(Vector3[] verts, Area area) { return new AreaGenerator(TriangleEnumerable.FromVector3(verts, 0, 1, verts.Length / 3), verts.Length / 3, area); } /// /// Create instance from the triangles created from points start from verts[0*vertStride+vertOffset] to verts[(triCount-1)*vertStride+vertOffset]with specified area /// /// An array of Vectors3. /// The index of the first Vectex to be enumerated. /// The distance between the start of two triangles. A value of 0 means the data is tightly packed. /// The number of triangles to enumerate.. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(Vector3[] verts, int vertOffset, int vertStride, int triCount, Area area) { return new AreaGenerator(TriangleEnumerable.FromVector3(verts, vertOffset, vertStride, triCount), triCount, area); } /// /// Create instance from the triangles created from points in verts with specified area /// /// An array of vertices. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(float[] verts, Area area) { return new AreaGenerator(TriangleEnumerable.FromFloat(verts, 0, 3, verts.Length / 9), verts.Length / 9, area); } /// /// Create instance from the triangles created from points start from verts[0*vertStride+vertOffset] to verts[(triCount-1)*vertStride+vertOffset]with specified area. /// /// An array of vertices. /// The index of the first float to be enumerated. /// The distance between the start of two vertices. A value of 0 means the data is tightly packed. /// The number of triangles to enumerate. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(float[] verts, int floatOffset, int floatStride, int triCount, Area area) { return new AreaGenerator(TriangleEnumerable.FromFloat(verts, floatOffset, floatStride, triCount), triCount, area); } /// /// Create instance from triangles created from points of verts which is created from array of index of vertices array with specified area /// /// An array of vertices. /// An array of indices. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(Vector3[] verts, int[] inds, Area area) { return new AreaGenerator(TriangleEnumerable.FromIndexedVector3(verts, inds, 0, 1, 0, inds.Length / 3), inds.Length / 3, area); } /// /// Create instance from triangles created from points of verts which is created from array of index of vertices array with specified area /// /// An array of vertices. /// An array of indices. /// The index of the first vertex to be enumerated. /// The distance between the start of two triangles. A value of 0 means the data is tightly packed. /// The index of the first index to be enumerated. /// The number of triangles to enumerate. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(Vector3[] verts, int[] inds, int vertOffset, int vertStride, int indexOffset, int triCount, Area area) { return new AreaGenerator(TriangleEnumerable.FromIndexedVector3(verts, inds, vertOffset, vertStride, indexOffset, triCount), triCount, area); } /// /// Create instance from triangles created from points of verts which is created from array of index of vertices array with specified area /// /// An array of vertices. /// An array of indices. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(float[] verts, int[] inds, Area area) { return new AreaGenerator(TriangleEnumerable.FromIndexedFloat(verts, inds, 0, 3, 0, inds.Length / 3), inds.Length / 3, area); } /// /// Create instance from triangles created from points of verts which is created from array of index of vertices array with specified area /// /// An array of vertices. /// An array of indices. /// The index of the first float to be enumerated. /// The distance between the start of two vertices. A value of 0 means the data is tightly packed. /// The index of the first index to be enumerated. /// The number of triangles to enumerate. /// Area of Triangle. /// A new AreaIdGenerator. public static AreaGenerator From(float[] verts, int[] inds, int floatOffset, int floatStride, int indexOffset, int triCount, Area area) { return new AreaGenerator(TriangleEnumerable.FromIndexedFloat(verts, inds, floatOffset, floatStride, indexOffset, triCount), triCount, area); } /// /// Takes the mesh query, runs it, and outputs the result as an array of . /// /// The result of the query. public Area[] ToArray() { Area[] areas = new Area[triCount]; int i = 0; foreach (var tri in tris) { areas[i] = defaultArea; foreach (var condition in conditions) if (condition.Item1(tri)) areas[i] = condition.Item2; i++; } return areas; } /// /// Marks all triangles above a specified angle with a sepcified area ID. /// /// The minimum angle in radians. /// The area ID to set for triangles above the slope. /// The same instance. public AreaGenerator MarkAboveSlope(float angle, Area area) { conditions.Add(new SharpNav.Tuple, Area>( tri => { Vector3 n = tri.Normal; float a; Vector3Extensions.CalculateSlopeAngle(ref n, out a); return a <= angle; }, area)); return this; } /// /// Marks all triangles below a specified angle with a sepcified area ID. /// /// The maximum angle. /// The area ID to set for triangles below the slope. /// The same instance. public AreaGenerator MarkBelowSlope(float angle, Area area) { conditions.Add(new SharpNav.Tuple, Area>( tri => { Vector3 n = tri.Normal; float a; Vector3Extensions.CalculateSlopeAngle(ref n, out a); return a >= angle; }, area)); return this; } /// /// Marks all triangles around a specified angle with a sepcified area ID. /// /// The angle. /// The maximum allowed difference between the angle and a triangle's angle. /// The area ID to set for triangles around the slope. /// The same instance. public AreaGenerator MarkAtSlope(float angle, float range, Area area) { conditions.Add(new SharpNav.Tuple, Area>( tri => { Vector3 n = tri.Normal; float a; Vector3Extensions.CalculateSlopeAngle(ref n, out a); return a >= angle - range && a <= angle + range; }, area)); return this; } /// /// Marks all triangles below a specified height with a sepcified area ID. /// /// The height threshold of a triangle. /// The area ID to set for triangles below the threshold. /// The same instance. public AreaGenerator MarkBelowHeight(float y, Area area) { conditions.Add(new SharpNav.Tuple, Area>( tri => { if (tri.A.Y <= y || tri.B.Y <= y || tri.C.Y <= y) return true; return false; }, area)); return this; } /// /// Marks all triangles around a specified height with a sepcified area ID. /// /// The height value. /// The maximum allowed difference between the height and a triangle's height. /// The area ID to set for triangles around the height. /// The same instance. public AreaGenerator MarkAtHeight(float y, float radius, Area area) { throw new NotImplementedException(); } /// /// Marks all triangles above a specified height with a sepcified area ID. /// /// The height threshold of a triangle. /// The area ID to set for triangles above the threshold. /// The same instance. public AreaGenerator MarkAboveHeight(float y, Area area) { conditions.Add(new SharpNav.Tuple, Area>( tri => { if (tri.A.Y >= y || tri.B.Y >= y || tri.C.Y >= y) return true; return false; }, area)); return this; } /// /// Marks all triangles that meet a specified condition with a specified area ID. /// /// The condition to be tested on each triangle. /// The area ID to set for triangles that match the condition. /// The same instance. public AreaGenerator MarkCustomFilter(Func func, Area area) { conditions.Add(new SharpNav.Tuple, Area>(func, area)); return this; } } }