问题
I'm creating a 2D game in Unity which has procedurally placed tiles. I want to simplify the collision geometry using Angus Johnson's Clipper library (specifically the union function), but I'm running into an issue with the library returning empty solutions and I'm not sure why.
For reference, here are the Polygon Colliders I've been using to test.
And here is a simplified version of the function I'm using to combine the geometry:
List<List<Vector2>> unitedPolygons = new List<List<Vector2>>();
Clipper clipper = new Clipper();
Paths solution = new Paths();
ClipperOffset offset = new ClipperOffset();
//Use a scaling factor for floats and convert the Polygon Colliders' points to Clipper's desired format
int scalingFactor = 10000;
for (int i = 0; i < polygons.Count; i++)
{
Path allPolygonsPath = new Path(polygons[i].points.Length);
for (int j = 0; j < polygons[i].points.Length; j++)
{
allPolygonsPath.Add(new IntPoint(Mathf.Floor(polygons[i].points[j].x * scalingFactor), Mathf.Floor(polygons[i].points[j].y * scalingFactor)));
}
bool succeeded = clipper.AddPath(allPolygonsPath, PolyType.ptSubject, true);
}
//Execute the union
bool success = clipper.Execute(ClipType.ctUnion, solution);
Debug.Log("Polygons after union: " + solution.Count);
//Offset the polygons
offset.AddPaths(solution, JoinType.jtMiter, EndType.etClosedPolygon);
offset.Execute(ref solution, 5f);
//Convert back to a format Unity can use
foreach (Path path in solution)
{
List<Vector2> unitedPolygon = new List<Vector2>();
foreach (IntPoint point in path)
{
unitedPolygon.Add(new Vector2(point.X / (float)scalingFactor, point.Y / (float)scalingFactor));
}
unitedPolygons.Add(unitedPolygon);
}
return unitedPolygons;
What I've discovered through debugging is that the first Execute (for the union) is returning an empty solution. I've figured out that the "BuildResult" function in the "Clipper" class is indeed running, and "m_PolyOuts" has data in it, but the "Pts" property of the "OutRec"s in that list are all null. I can't figure out where this happens or if they were ever set in the first place.
I'm convinced this is proper behavior and I'm just using the library wrong, but I can't find any documentation or examples explaining what I need to change to make the union succeed.
Thanks.
EDIT: I've narrowed it down a bit more. During "ExecuteInteral" in the Clipper class, the "Pts" lists aren't null until the "FixupOutPolygon" function is run. After that, all of the lists are null. "JoinCommonEdges" also makes a couple of the lists null, but not all of them.
回答1:
I've been working on my own game project as well and stumbled upon similar problem with Clipper. What worked for me in this case was instead of writing this:
clipper.Execute(ClipType.ctUnion, solution);
... I specified PolyFillType for Execute method:
clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
I'm not sure why it worked for me but I think it's due to the fact that some Paths can share common edges so with the default pftEvenOdd filling rule it gets cut out.
来源:https://stackoverflow.com/questions/45492416/confused-on-clipper-in-c-sharp