From 214cc0564e4c8e57f580159d2908d50dbd1a1423 Mon Sep 17 00:00:00 2001 From: andywiecko Date: Thu, 14 Nov 2024 08:32:41 +0100 Subject: [PATCH] perf: optimize planting triangles removal This commit improves triangle removal performance by approximately 2.5% in the planting seed step. Additionally, it reduces temporary memory allocation by eliminating the `map` buffer entirely. --- Runtime/Triangulator.cs | 71 ++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/Runtime/Triangulator.cs b/Runtime/Triangulator.cs index eabf4f1..dc8beec 100644 --- a/Runtime/Triangulator.cs +++ b/Runtime/Triangulator.cs @@ -2536,7 +2536,7 @@ private struct PlantingSeedStep private NativeArray holes; private readonly Args args; - private bool anyTriangleVisited; + private int tIdMinVisited; public PlantingSeedStep(InputData input, OutputData output, Args args) : this(output, args, input.HoleSeeds) { } @@ -2554,7 +2554,7 @@ public PlantingSeedStep(OutputData output, Args args, NativeArray localH visitedTriangles = default; trianglesQueue = default; - anyTriangleVisited = false; + tIdMinVisited = -1; } public void Execute(Allocator allocator, bool constraintsIsCreated) @@ -2573,7 +2573,7 @@ public void Execute(Allocator allocator, bool constraintsIsCreated) if (holes.IsCreated) PlantHoleSeeds(holes); if (args.RestoreBoundary) PlantBoundarySeeds(); - RemoveVisitedTriangles(allocator); + RemoveVisitedTriangles(); } private bool HalfedgeIsIgnored(int he) => ignoredHalfedges.IsCreated && ignoredHalfedges[he]; @@ -2603,54 +2603,60 @@ private void PlantHoleSeeds(NativeArray holeSeeds) } } - private void RemoveVisitedTriangles(Allocator allocator) + private void RemoveVisitedTriangles() { - if (!anyTriangleVisited) + static void DisableHe(NativeList halfedges, int he, int rId) { - return; + var ohe = halfedges[3 * rId + he]; + if (ohe != -1) + { + halfedges[ohe] = -1; + } } - // Triangles to remove are marked with -1, otherwise they are assigned with incremental id. - var map = new NativeArray(triangles.Length / 3, allocator); - var count = 0; - for (int tId = 0; tId < visitedTriangles.Length; tId++) + static void AdaptHe(NativeList halfedges, int he, int rId, int wId) { - map[tId] = visitedTriangles[tId] ? -1 : count++; + var ohe = halfedges[3 * rId + he]; + halfedges[3 * wId + he] = ohe; + if (ohe != -1) + { + halfedges[ohe] = 3 * wId + he; + } } - int RemapHalfedge(int ohe) + if (tIdMinVisited == -1) { - if (ohe == -1) - { - return -1; - } - var tId = map[ohe / 3]; - return tId == -1 ? -1 : 3 * tId + ohe % 3; + return; } // Reinterpret to a larger struct to make copies of whole triangles slightly more efficient var constrainedHalfedges3 = constrainedHalfedges.AsArray().Reinterpret(1); var triangles3 = triangles.AsArray().Reinterpret(4); - for (int tId = 0; tId < map.Length; tId++) + var wId = tIdMinVisited; + for (int rId = tIdMinVisited; rId < triangles3.Length; rId++) { - var tIdNew = map[tId]; - if (tIdNew != -1) + if (!visitedTriangles[rId]) + { + triangles3[wId] = triangles3[rId]; + constrainedHalfedges3[wId] = constrainedHalfedges3[rId]; + AdaptHe(halfedges, 0, rId, wId); + AdaptHe(halfedges, 1, rId, wId); + AdaptHe(halfedges, 2, rId, wId); + wId++; + } + else { - triangles3[tIdNew] = triangles3[tId]; - constrainedHalfedges3[tIdNew] = constrainedHalfedges3[tId]; - halfedges[3 * tIdNew + 0] = RemapHalfedge(ohe: halfedges[3 * tId + 0]); - halfedges[3 * tIdNew + 1] = RemapHalfedge(ohe: halfedges[3 * tId + 1]); - halfedges[3 * tIdNew + 2] = RemapHalfedge(ohe: halfedges[3 * tId + 2]); + DisableHe(halfedges, 0, rId); + DisableHe(halfedges, 1, rId); + DisableHe(halfedges, 2, rId); } } // Trim the data to reflect removed triangles. - triangles.Length = 3 * count; - constrainedHalfedges.Length = 3 * count; - halfedges.Length = 3 * count; - - map.Dispose(); + triangles.Length = 3 * wId; + constrainedHalfedges.Length = 3 * wId; + halfedges.Length = 3 * wId; } private void PlantSeed(int tId) @@ -2662,7 +2668,7 @@ private void PlantSeed(int tId) visitedTriangles[tId] = true; trianglesQueue.Enqueue(tId); - anyTriangleVisited = true; + tIdMinVisited = tIdMinVisited == -1 ? tId : math.min(tId, tIdMinVisited); // Search outwards from the seed triangle and mark all triangles // until we get to a constrained edge, or a previously visited triangle. @@ -2682,6 +2688,7 @@ private void PlantSeed(int tId) { visitedTriangles[otherId] = true; trianglesQueue.Enqueue(otherId); + tIdMinVisited = math.min(otherId, tIdMinVisited); } } }