98 lines
3.1 KiB
C#
98 lines
3.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using SuperTiled2Unity.Editor.ClipperLib;
|
|
using SuperTiled2Unity.Editor.Geometry;
|
|
using UnityEngine;
|
|
|
|
namespace SuperTiled2Unity.Editor
|
|
{
|
|
public class CollisionClipper
|
|
{
|
|
private const float Multiplier = 1024.0f;
|
|
private const float InvMultiplier = 1.0f / Multiplier;
|
|
|
|
private Clipper m_Clipper = new Clipper();
|
|
private List<Vector2[]> m_RawOpenPaths = new List<Vector2[]>();
|
|
|
|
// Once the clipper is executed we have our list of processed closed and open paths
|
|
public List<Vector2[]> ClosedPaths { get; private set; }
|
|
public List<Vector2[]> OpenPaths { get; private set; }
|
|
|
|
public void AddClosedPath(Vector2[] points)
|
|
{
|
|
var path = ToClipperSpace(points);
|
|
m_Clipper.AddPath(path, PolyType.ptSubject, true);
|
|
}
|
|
|
|
public void AddOpenPath(Vector2[] points)
|
|
{
|
|
// Open paths do not get clipped but we gather them so they can be combined when we execute
|
|
m_RawOpenPaths.Add(points);
|
|
}
|
|
|
|
public void Execute()
|
|
{
|
|
PolyTree solution = new PolyTree();
|
|
m_Clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftEvenOdd);
|
|
|
|
AddConvexPolygonsFromSolution(solution);
|
|
CombineLines();
|
|
}
|
|
|
|
private void AddConvexPolygonsFromSolution(PolyTree solution)
|
|
{
|
|
ClosedPaths = new List<Vector2[]>();
|
|
|
|
// Triangulate the solution
|
|
var triangulator = new Triangulator();
|
|
var triangles = triangulator.TriangulateClipperSolution(solution);
|
|
|
|
// Gather triangles into a collection of convex polygons
|
|
var composition = new ComposeConvexPolygons();
|
|
var convexPolygons = composition.Compose(triangles);
|
|
|
|
foreach (var poly in convexPolygons)
|
|
{
|
|
var transformed = FromClipperSpace(poly);
|
|
ClosedPaths.Add(transformed);
|
|
}
|
|
}
|
|
|
|
private void CombineLines()
|
|
{
|
|
OpenPaths = new List<Vector2[]>();
|
|
|
|
var reduction = new PolylineReduction();
|
|
|
|
foreach (var line in m_RawOpenPaths)
|
|
{
|
|
var transformed = ToClipperSpace(line);
|
|
reduction.AddLine(transformed);
|
|
}
|
|
|
|
var polyLines = reduction.Reduce();
|
|
|
|
foreach (var lines in polyLines)
|
|
{
|
|
var transformed = FromClipperSpace(lines);
|
|
OpenPaths.Add(transformed);
|
|
}
|
|
}
|
|
|
|
private List<IntPoint> ToClipperSpace(Vector2[] points)
|
|
{
|
|
return points.Select(pt => new IntPoint(pt.x * Multiplier, pt.y * Multiplier)).ToList();
|
|
}
|
|
|
|
private Vector2[] FromClipperSpace(List<IntPoint> points)
|
|
{
|
|
return points.Select(pt => new Vector2(pt.X * InvMultiplier, pt.Y * InvMultiplier)).ToArray();
|
|
}
|
|
|
|
private Vector2[] FromClipperSpace(IEnumerable<Vector2> points)
|
|
{
|
|
return points.Select(pt => new Vector2(pt.x * InvMultiplier, pt.y * InvMultiplier)).ToArray();
|
|
}
|
|
}
|
|
}
|