Skip to content

Commit

Permalink
perf: optimize planting triangles removal
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
andywiecko committed Nov 14, 2024
1 parent 4f68f7e commit 9e991df
Showing 1 changed file with 39 additions and 32 deletions.
71 changes: 39 additions & 32 deletions Runtime/Triangulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2536,7 +2536,7 @@ private struct PlantingSeedStep
private NativeArray<T2> holes;

private readonly Args args;
private bool anyTriangleVisited;
private int tIdMinVisited;

public PlantingSeedStep(InputData<T2> input, OutputData<T2> output, Args args) : this(output, args, input.HoleSeeds) { }

Expand All @@ -2554,7 +2554,7 @@ public PlantingSeedStep(OutputData<T2> output, Args args, NativeArray<T2> localH
visitedTriangles = default;
trianglesQueue = default;

anyTriangleVisited = false;
tIdMinVisited = -1;
}

public void Execute(Allocator allocator, bool constraintsIsCreated)
Expand All @@ -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];
Expand Down Expand Up @@ -2603,54 +2603,60 @@ private void PlantHoleSeeds(NativeArray<T2> holeSeeds)
}
}

private void RemoveVisitedTriangles(Allocator allocator)
private void RemoveVisitedTriangles()
{
if (!anyTriangleVisited)
static void DisableHe(NativeList<int> 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<int>(triangles.Length / 3, allocator);
var count = 0;
for (int tId = 0; tId < visitedTriangles.Length; tId++)
static void AdaptHe(NativeList<int> 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<bool3>(1);
var triangles3 = triangles.AsArray().Reinterpret<int3>(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)
Expand All @@ -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.
Expand All @@ -2682,6 +2688,7 @@ private void PlantSeed(int tId)
{
visitedTriangles[otherId] = true;
trianglesQueue.Enqueue(otherId);
tIdMinVisited = math.min(otherId, tIdMinVisited);
}
}
}
Expand Down

0 comments on commit 9e991df

Please sign in to comment.