using ProceduralToolkit.LibTessDotNet; using System.Collections.Generic; using UnityEngine; using Mesh = UnityEngine.Mesh; namespace ProceduralToolkit { /// /// LibTessDotNet wrapper /// public class Tessellator { /// /// If true, will remove empty (zero area) polygons. /// public bool removeEmptyPolygons { get => tess.NoEmptyPolygons; set => tess.NoEmptyPolygons = value; } /// /// Vertices of the tessellated mesh. /// public ContourVertex[] vertices => tess.Vertices; /// /// Number of vertices in the tessellated mesh. /// public int vertexCount => tess.VertexCount; /// /// Indices of the tessellated mesh. See for details on data layout. /// public int[] indices => tess.Elements; /// /// Number of elements in the tessellated mesh. /// public int indexCount => tess.ElementCount; private readonly Tess tess = new Tess {NoEmptyPolygons = true}; /// /// Adds a closed contour to be tessellated. /// /// Vertices of the contour. /// /// Orientation of the contour. /// keeps the orientation of the input vertices. /// and /// force the vertices to have a specified orientation. /// public void AddContour(IReadOnlyList vertices, ContourOrientation forceOrientation = ContourOrientation.Original) { var contour = new ContourVertex[vertices.Count]; for (int i = 0; i < vertices.Count; i++) { Vector2 vertex = vertices[i]; contour[i].Position = new Vec3(vertex.x, vertex.y, 0); } tess.AddContour(contour, forceOrientation); } /// /// Adds a closed contour to be tessellated. /// /// Vertices of the contour. /// /// Orientation of the contour. /// keeps the orientation of the input vertices. /// and /// force the vertices to have a specified orientation. /// public void AddContour(IReadOnlyList vertices, ContourOrientation forceOrientation = ContourOrientation.Original) { var contour = new ContourVertex[vertices.Count]; for (int i = 0; i < vertices.Count; i++) { Vector3 vertex = vertices[i]; contour[i].Position = new Vec3(vertex.x, vertex.y, vertex.z); } tess.AddContour(contour, forceOrientation); } /// /// Adds a closed contour to be tessellated. /// /// Vertices of the contour. /// /// Orientation of the contour. /// keeps the orientation of the input vertices. /// and /// force the vertices to have a specified orientation. /// public void AddContour(IReadOnlyList vertices, ContourOrientation forceOrientation = ContourOrientation.Original) { tess.AddContour(vertices, forceOrientation); } /// /// Tessellates the input contours. /// /// Winding rule used for tessellation. See for details. /// Tessellation output type. See for details. /// Number of vertices per polygon if output is polygons. /// Interpolator used to determine the data payload of generated vertices. /// Normal of the input contours. If set to zero, the normal will be calculated during tessellation. public void Tessellate(WindingRule windingRule = WindingRule.EvenOdd, ElementType elementType = ElementType.Polygons, int polySize = 3, CombineCallback combineCallback = null, Vector3 normal = new Vector3()) { tess.Tessellate(windingRule, elementType, polySize, combineCallback, new Vec3(normal.x, normal.y, normal.z)); } /// /// Converts the tessellated mesh to MeshDraft. /// public MeshDraft ToMeshDraft() { var draft = new MeshDraft(); for (int i = 0; i < vertexCount; i++) { Vec3 vertex = vertices[i].Position; draft.vertices.Add(new Vector3(vertex.X, vertex.Y, vertex.Z)); } draft.triangles.AddRange(indices); return draft; } /// /// Converts the tessellated mesh to MeshDraft. /// public void ToMeshDraft(MeshDraft draft) { draft.vertices.Clear(); draft.triangles.Clear(); for (int i = 0; i < vertexCount; i++) { Vec3 vertex = vertices[i].Position; draft.vertices.Add(new Vector3(vertex.X, vertex.Y, vertex.Z)); } draft.triangles.AddRange(indices); } /// /// Converts the tessellated mesh to Mesh. /// public Mesh ToMesh() { return ToMeshDraft().ToMesh(); } /// /// Converts the tessellated mesh to Mesh. /// public void ToMesh(Mesh mesh) { ToMeshDraft().ToMesh(mesh); } } }