Skip to content

Commit 0b8d361

Browse files
committed
demo: Add extra statistics for meshlets
We now track the average number of boundary vertices for a meshlet as well as the mean cone half-angle radius; both are relevant for various optimality properties of meshlets depending on the use case.
1 parent 1540be4 commit 0b8d361

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

demo/main.cpp

+31-8
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ static int follow(int* parents, int index)
929929
return index;
930930
}
931931

932-
void meshlets(const Mesh& mesh, bool scan)
932+
void meshlets(const Mesh& mesh, bool scan = false)
933933
{
934934
const size_t max_vertices = 64;
935935
const size_t max_triangles = 124; // NVidia-recommended 126, rounded down to a multiple of 4
@@ -963,9 +963,20 @@ void meshlets(const Mesh& mesh, bool scan)
963963

964964
double avg_vertices = 0;
965965
double avg_triangles = 0;
966+
double avg_boundary = 0;
966967
size_t not_full = 0;
967968
size_t not_connected = 0;
968969

970+
std::vector<int> boundary(mesh.vertices.size());
971+
972+
for (size_t i = 0; i < meshlets.size(); ++i)
973+
{
974+
const meshopt_Meshlet& m = meshlets[i];
975+
976+
for (unsigned int j = 0; j < m.vertex_count; ++j)
977+
boundary[meshlet_vertices[m.vertex_offset + j]]++;
978+
}
979+
969980
for (size_t i = 0; i < meshlets.size(); ++i)
970981
{
971982
const meshopt_Meshlet& m = meshlets[i];
@@ -974,6 +985,10 @@ void meshlets(const Mesh& mesh, bool scan)
974985
avg_triangles += m.triangle_count;
975986
not_full += m.vertex_count < max_vertices;
976987

988+
for (unsigned int j = 0; j < m.vertex_count; ++j)
989+
if (boundary[meshlet_vertices[m.vertex_offset + j]] > 1)
990+
avg_boundary += 1;
991+
977992
// union-find vertices to check if the meshlet is connected
978993
int parents[max_vertices];
979994
for (unsigned int j = 0; j < m.vertex_count; ++j)
@@ -1000,10 +1015,11 @@ void meshlets(const Mesh& mesh, bool scan)
10001015

10011016
avg_vertices /= double(meshlets.size());
10021017
avg_triangles /= double(meshlets.size());
1018+
avg_boundary /= double(meshlets.size());
10031019

1004-
printf("Meshlets%c: %d meshlets (avg vertices %.1f, avg triangles %.1f, not full %d, not connected %d) in %.2f msec\n",
1020+
printf("Meshlets%c: %d meshlets (avg vertices %.1f, avg triangles %.1f, avg boundary %.1f, not full %d, not connected %d) in %.2f msec\n",
10051021
scan ? 'S' : ' ',
1006-
int(meshlets.size()), avg_vertices, avg_triangles, int(not_full), int(not_connected), (end - start) * 1000);
1022+
int(meshlets.size()), avg_vertices, avg_triangles, avg_boundary, int(not_full), int(not_connected), (end - start) * 1000);
10071023

10081024
float camera[3] = {100, 100, 100};
10091025

@@ -1015,6 +1031,7 @@ void meshlets(const Mesh& mesh, bool scan)
10151031
size_t accepted_s8 = 0;
10161032

10171033
std::vector<float> radii(meshlets.size());
1034+
std::vector<float> cones(meshlets.size());
10181035

10191036
double startc = timestamp();
10201037
for (size_t i = 0; i < meshlets.size(); ++i)
@@ -1024,6 +1041,7 @@ void meshlets(const Mesh& mesh, bool scan)
10241041
meshopt_Bounds bounds = meshopt_computeMeshletBounds(&meshlet_vertices[m.vertex_offset], &meshlet_triangles[m.triangle_offset], m.triangle_count, &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex));
10251042

10261043
radii[i] = bounds.radius;
1044+
cones[i] = 90.f - acosf(bounds.cone_cutoff) * (180.f / 3.1415926f);
10271045

10281046
// trivial accept: we can't ever backface cull this meshlet
10291047
accepted += (bounds.cone_cutoff >= 1);
@@ -1047,11 +1065,16 @@ void meshlets(const Mesh& mesh, bool scan)
10471065
double endc = timestamp();
10481066

10491067
double radius_mean = 0;
1068+
double cone_mean = 0;
10501069

10511070
for (size_t i = 0; i < meshlets.size(); ++i)
1071+
{
10521072
radius_mean += radii[i];
1073+
cone_mean += cones[i];
1074+
}
10531075

10541076
radius_mean /= double(meshlets.size());
1077+
cone_mean /= double(meshlets.size());
10551078

10561079
double radius_variance = 0;
10571080

@@ -1067,10 +1090,10 @@ void meshlets(const Mesh& mesh, bool scan)
10671090
for (size_t i = 0; i < meshlets.size(); ++i)
10681091
meshlets_std += radii[i] < radius_mean + radius_stddev;
10691092

1070-
printf("BoundDist: mean %f stddev %f; %.1f%% meshlets are under mean+stddev\n",
1071-
radius_mean,
1072-
radius_stddev,
1073-
double(meshlets_std) / double(meshlets.size()) * 100);
1093+
printf("Bounds : radius mean %f stddev %f; %.1f%% meshlets are under mean+stddev; cone mean half angle %.1f\n",
1094+
radius_mean, radius_stddev,
1095+
double(meshlets_std) / double(meshlets.size()) * 100,
1096+
cone_mean);
10741097

10751098
printf("ConeCull : rejected apex %d (%.1f%%) / center %d (%.1f%%), trivially accepted %d (%.1f%%) in %.2f msec\n",
10761099
int(rejected), double(rejected) / double(meshlets.size()) * 100,
@@ -1392,7 +1415,7 @@ void processDev(const char* path)
13921415
if (!loadMesh(mesh, path))
13931416
return;
13941417

1395-
simplifyAttr(mesh, 0.1f, meshopt_SimplifyPrune);
1418+
meshlets(mesh);
13961419
}
13971420

13981421
void processNanite(const char* path)

0 commit comments

Comments
 (0)