81 lines
2.7 KiB
C#
81 lines
2.7 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using SuperTiled2Unity.Editor.LibTessDotNet;
|
|
using UnityEngine;
|
|
|
|
namespace SuperTiled2Unity.Editor.Geometry
|
|
{
|
|
// Input is a ClipperLib solution and output is a collection of triangles
|
|
public class Triangulator
|
|
{
|
|
public List<Vector2[]> TriangulateClipperSolution(ClipperLib.PolyTree solution)
|
|
{
|
|
var tess = new Tess();
|
|
tess.NoEmptyPolygons = true;
|
|
|
|
// Add a contour for each part of the solution tree
|
|
ClipperLib.PolyNode node = solution.GetFirst();
|
|
while (node != null)
|
|
{
|
|
// Only interested in closed paths
|
|
if (!node.IsOpen)
|
|
{
|
|
// Add a new countor. Holes are automatically generated.
|
|
var vertices = node.Contour.Select(pt => new ContourVertex { Position = new Vec3 { X = pt.X, Y = pt.Y, Z = 0 } }).ToArray();
|
|
tess.AddContour(vertices);
|
|
}
|
|
node = node.GetNext();
|
|
}
|
|
|
|
return TrianglesFromTessellator(tess);
|
|
}
|
|
|
|
public List<Vector2[]> TriangulatePolygon(Vector2[] points)
|
|
{
|
|
var tess = new Tess();
|
|
tess.NoEmptyPolygons = true;
|
|
|
|
var vertices = points.Select(pt => new ContourVertex { Position = new Vec3 { X = pt.x, Y = pt.y, Z = 0 } }).ToArray();
|
|
tess.AddContour(vertices);
|
|
|
|
return TrianglesFromTessellator(tess);
|
|
}
|
|
|
|
private List<Vector2[]> TrianglesFromTessellator(Tess tess)
|
|
{
|
|
var triangles = new List<Vector2[]>();
|
|
|
|
// Do the tessellation
|
|
tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
|
|
|
|
// Extract the triangles
|
|
int numTriangles = tess.ElementCount;
|
|
for (int i = 0; i < numTriangles; i++)
|
|
{
|
|
var v0 = tess.Vertices[tess.Elements[i * 3 + 0]].Position;
|
|
var v1 = tess.Vertices[tess.Elements[i * 3 + 1]].Position;
|
|
var v2 = tess.Vertices[tess.Elements[i * 3 + 2]].Position;
|
|
|
|
var triangle = new List<Vector2>()
|
|
{
|
|
new Vector2(v0.X, v0.Y),
|
|
new Vector2(v1.X, v1.Y),
|
|
new Vector2(v2.X, v2.Y),
|
|
};
|
|
|
|
// Assume each triangle needs to be CCW
|
|
float cross = GeoMath.Cross(triangle[0], triangle[1], triangle[2]);
|
|
if (cross > 0)
|
|
{
|
|
triangle.Reverse();
|
|
}
|
|
|
|
triangles.Add(triangle.ToArray());
|
|
}
|
|
|
|
return triangles;
|
|
}
|
|
|
|
}
|
|
}
|