Skip to content

Commit b8094a3

Browse files
committed
clusterizer: Streamline triangle selection logic
Instead of using the seeds when the adjacency selection didn't yield a result, we use the seeds when the meshlet is going to be split; this covers some cases when adjacency runs out of triangles, and also covers split_factor based splits, slightly improving the flow for flex variant as well.
1 parent 08cb1f7 commit b8094a3

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

src/clusterizer.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -806,9 +806,6 @@ size_t meshopt_buildMeshletsFlex(meshopt_Meshlet* meshlets, unsigned int* meshle
806806
unsigned int seeds[kMeshletMaxSeeds] = {};
807807
size_t seed_count = 0;
808808

809-
assert(initial_seed != ~0u);
810-
seeds[seed_count++] = initial_seed;
811-
812809
meshopt_Meshlet meshlet = {};
813810
size_t meshlet_offset = 0;
814811

@@ -818,30 +815,18 @@ size_t meshopt_buildMeshletsFlex(meshopt_Meshlet* meshlets, unsigned int* meshle
818815
{
819816
Cone meshlet_cone = getMeshletCone(meshlet_cone_acc, meshlet.triangle_count);
820817

821-
unsigned int best_triangle = getNeighborTriangle(meshlet, &meshlet_cone, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, cone_weight);
822-
int best_extra = best_triangle == ~0u ? -1 : (used[indices[best_triangle * 3 + 0]] == 0xff) + (used[indices[best_triangle * 3 + 1]] == 0xff) + (used[indices[best_triangle * 3 + 2]] == 0xff);
818+
unsigned int best_triangle = ~0u;
823819

824820
// for the first triangle, we don't have a meshlet cone yet, so we use the initial seed
821+
// to continue the meshlet, we select an adjacent triangle based on connectivity and spatial scoring
825822
if (meshlet_offset == 0 && meshlet.triangle_count == 0)
826823
best_triangle = initial_seed;
827-
828-
// if the best triangle doesn't fit into current meshlet, the spatial scoring we've used is not very meaningful, so we re-select using topological scoring
829-
if (best_triangle != ~0u && (meshlet.vertex_count + best_extra > max_vertices || meshlet.triangle_count >= max_triangles))
830-
{
831-
seed_count = pruneSeedTriangles(seeds, seed_count, emitted_flags);
832-
if (seed_count + kMeshletAddSeeds <= kMeshletMaxSeeds)
833-
seed_count += appendSeedTriangles(seeds + seed_count, meshlet, meshlet_vertices, indices, adjacency, triangles, live_triangles, cornerx, cornery, cornerz);
834-
835-
unsigned int best_seed = selectSeedTriangle(seeds, seed_count, indices, triangles, live_triangles, cornerx, cornery, cornerz);
836-
837-
// TODO?
838-
best_triangle = best_seed;
839-
// best_triangle = getNeighborTriangle(meshlet, NULL, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, 0.f);
840-
}
824+
else
825+
best_triangle = getNeighborTriangle(meshlet, &meshlet_cone, meshlet_vertices, indices, adjacency, triangles, live_triangles, used, meshlet_expected_radius, cone_weight);
841826

842827
bool split = false;
843828

844-
// when we run out of neighboring triangles we need to switch to spatial search; we currently just pick the closest triangle irrespective of connectivity
829+
// when we run out of adjacent triangles we need to switch to spatial search; we currently just pick the closest triangle irrespective of connectivity
845830
if (best_triangle == ~0u)
846831
{
847832
float position[3] = {meshlet_cone.px, meshlet_cone.py, meshlet_cone.pz};
@@ -852,12 +837,26 @@ size_t meshopt_buildMeshletsFlex(meshopt_Meshlet* meshlets, unsigned int* meshle
852837

853838
best_triangle = index;
854839
split = meshlet.triangle_count >= min_triangles && split_factor > 0 && distance > meshlet_expected_radius * split_factor;
855-
// TODO seeds
856840
}
857841

858842
if (best_triangle == ~0u)
859843
break;
860844

845+
int best_extra = (used[indices[best_triangle * 3 + 0]] == 0xff) + (used[indices[best_triangle * 3 + 1]] == 0xff) + (used[indices[best_triangle * 3 + 2]] == 0xff);
846+
847+
// if the best triangle doesn't fit into current meshlet, we re-select using seeds to maintain global flow
848+
if (split || (meshlet.vertex_count + best_extra > max_vertices || meshlet.triangle_count >= max_triangles))
849+
{
850+
seed_count = pruneSeedTriangles(seeds, seed_count, emitted_flags);
851+
if (seed_count + kMeshletAddSeeds <= kMeshletMaxSeeds)
852+
seed_count += appendSeedTriangles(seeds + seed_count, meshlet, meshlet_vertices, indices, adjacency, triangles, live_triangles, cornerx, cornery, cornerz);
853+
854+
unsigned int best_seed = selectSeedTriangle(seeds, seed_count, indices, triangles, live_triangles, cornerx, cornery, cornerz);
855+
856+
// we may not find a valid seed triangle if the mesh is disconnected as seeds are based on adjacency
857+
best_triangle = best_seed != ~0u ? best_seed : best_triangle;
858+
}
859+
861860
unsigned int a = indices[best_triangle * 3 + 0], b = indices[best_triangle * 3 + 1], c = indices[best_triangle * 3 + 2];
862861
assert(a < vertex_count && b < vertex_count && c < vertex_count);
863862

@@ -899,6 +898,7 @@ size_t meshopt_buildMeshletsFlex(meshopt_Meshlet* meshlets, unsigned int* meshle
899898
meshlet_cone_acc.ny += triangles[best_triangle].ny;
900899
meshlet_cone_acc.nz += triangles[best_triangle].nz;
901900

901+
assert(!emitted_flags[best_triangle]);
902902
emitted_flags[best_triangle] = 1;
903903
}
904904

0 commit comments

Comments
 (0)