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);
}
}
}