Skip to content

Commit f3e0e9e

Browse files
committed
demo: Extract all metrics output into a separate function
In addition to significantly cleaning up the main processing function, this also ensures that the metrics are consistent, being gathered from the same level. Before this we actually had an issue where some metrics were gathered after simplification and some - before; as a result, some values such as boundary will change between levels of detail compared to the previous output.
1 parent fbc26f8 commit f3e0e9e

File tree

1 file changed

+53
-42
lines changed

1 file changed

+53
-42
lines changed

demo/nanite.cpp

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,55 @@ static int measureUnique(std::vector<int>& used, const std::vector<unsigned int>
498498
return int(vertices);
499499
}
500500

501+
static void dumpMetrics(int level, const std::vector<Cluster>& queue, const std::vector<std::vector<int> >& groups, const std::vector<unsigned int>& remap, const std::vector<unsigned char>& locks, const std::vector<int>& retry)
502+
{
503+
std::vector<int> parents(remap.size());
504+
505+
int clusters = 0;
506+
int triangles = 0;
507+
int full_clusters = 0;
508+
int components = 0;
509+
int xformed = 0;
510+
int boundary = 0;
511+
512+
for (size_t i = 0; i < groups.size(); ++i)
513+
{
514+
for (size_t j = 0; j < groups[i].size(); ++j)
515+
{
516+
const Cluster& cluster = queue[groups[i][j]];
517+
518+
clusters++;
519+
triangles += int(cluster.indices.size() / 3);
520+
full_clusters += cluster.indices.size() == kClusterSize * 3;
521+
components += measureComponents(parents, cluster.indices, remap);
522+
xformed += measureUnique(parents, cluster.indices);
523+
boundary += kUseLocks ? measureUnique(parents, cluster.indices, &locks) : 0;
524+
}
525+
}
526+
527+
int stuck_clusters = 0;
528+
int stuck_triangles = 0;
529+
530+
for (size_t i = 0; i < retry.size(); ++i)
531+
{
532+
const Cluster& cluster = queue[retry[i]];
533+
534+
stuck_clusters++;
535+
stuck_triangles += int(cluster.indices.size() / 3);
536+
}
537+
538+
double avg_group = double(clusters) / double(groups.size());
539+
double inv_clusters = 1.0 / double(clusters);
540+
541+
printf("lod %d: %d clusters (%.1f%% full, %.1f tri/cl, %.1f vtx/cl, %.2f connected, %.1f boundary, %.1f partition), %d triangles",
542+
level, clusters,
543+
double(full_clusters) * inv_clusters * 100, double(triangles) * inv_clusters, double(xformed) * inv_clusters, double(components) * inv_clusters, double(boundary) * inv_clusters, avg_group,
544+
int(triangles));
545+
if (stuck_clusters)
546+
printf("; stuck %d clusters (%d triangles)", stuck_clusters, stuck_triangles);
547+
printf("\n");
548+
}
549+
501550
static bool loadMetis()
502551
{
503552
#ifdef _WIN32
@@ -538,7 +587,6 @@ void nanite(const std::vector<Vertex>& vertices, const std::vector<unsigned int>
538587

539588
int depth = 0;
540589
std::vector<unsigned char> locks(vertices.size());
541-
std::vector<int> parents(vertices.size());
542590

543591
// for cluster connectivity, we need a position-only remap that maps vertices with the same position to the same index
544592
// it's more efficient to build it once; unfortunately, meshopt_generateVertexRemap doesn't support stride so we need to use *Multi version
@@ -551,23 +599,8 @@ void nanite(const std::vector<Vertex>& vertices, const std::vector<unsigned int>
551599
for (size_t i = 0; i < clusters.size(); ++i)
552600
clusters[i].self = bounds(vertices, clusters[i].indices, 0.f);
553601

554-
size_t components_initial = 0;
555-
size_t xformed_initial = 0;
556-
for (size_t i = 0; i < clusters.size(); ++i)
557-
{
558-
components_initial += measureComponents(parents, clusters[i].indices, remap);
559-
xformed_initial += measureUnique(parents, clusters[i].indices);
560-
}
561-
562602
printf("ideal lod chain: %.1f levels\n", log2(double(indices.size() / 3) / double(kClusterSize)));
563603

564-
printf("lod 0: %d clusters (%.1f tri/cl, %.1f vtx/cl, %.2f connected), %d triangles\n",
565-
int(clusters.size()),
566-
double(indices.size() / 3) / double(clusters.size()),
567-
double(xformed_initial) / double(clusters.size()),
568-
double(components_initial) / double(clusters.size()),
569-
int(indices.size() / 3));
570-
571604
std::vector<int> pending(clusters.size());
572605
for (size_t i = 0; i < clusters.size(); ++i)
573606
pending[i] = int(i);
@@ -576,26 +609,20 @@ void nanite(const std::vector<Vertex>& vertices, const std::vector<unsigned int>
576609
while (pending.size() > 1)
577610
{
578611
std::vector<std::vector<int> > groups = partition(clusters, pending, remap);
579-
double avg_group = double(pending.size()) / double(groups.size());
612+
613+
if (kUseLocks)
614+
lockBoundary(locks, groups, clusters, remap);
580615

581616
pending.clear();
582617

583618
std::vector<int> retry;
584619

585620
size_t triangles = 0;
586621
size_t stuck_triangles = 0;
587-
int stuck_clusters = 0;
588-
int full_clusters = 0;
589-
size_t components_lod = 0;
590-
size_t xformed_lod = 0;
591-
size_t boundary_lod = 0;
592622

593623
if (dump && depth == atoi(dump))
594624
dumpObj(vertices, std::vector<unsigned int>());
595625

596-
if (kUseLocks)
597-
lockBoundary(locks, groups, clusters, remap);
598-
599626
// every group needs to be simplified now
600627
for (size_t i = 0; i < groups.size(); ++i)
601628
{
@@ -621,10 +648,6 @@ void nanite(const std::vector<Vertex>& vertices, const std::vector<unsigned int>
621648
std::vector<unsigned int> simplified = simplify(vertices, merged, kUseLocks ? &locks : NULL, target_size, &error);
622649
if (simplified.size() > merged.size() * kSimplifyThreshold)
623650
{
624-
#if TRACE
625-
printf("stuck cluster: simplified %d => %d over threshold\n", int(merged.size() / 3), int(simplified.size() / 3));
626-
#endif
627-
stuck_clusters += groups[i].size();
628651
stuck_triangles += merged.size() / 3;
629652
for (size_t j = 0; j < groups[i].size(); ++j)
630653
retry.push_back(groups[i][j]);
@@ -661,23 +684,11 @@ void nanite(const std::vector<Vertex>& vertices, const std::vector<unsigned int>
661684
pending.push_back(int(clusters.size()) - 1);
662685

663686
triangles += split[j].indices.size() / 3;
664-
full_clusters += split[j].indices.size() == kClusterSize * 3;
665-
components_lod += measureComponents(parents, split[j].indices, remap);
666-
xformed_lod += measureUnique(parents, split[j].indices);
667-
boundary_lod += kUseLocks ? measureUnique(parents, split[j].indices, &locks) : 0;
668687
}
669688
}
670689

671-
double inv_clusters = pending.empty() ? 0 : 1.0 / double(pending.size());
672-
690+
dumpMetrics(depth, clusters, groups, remap, locks, retry);
673691
depth++;
674-
printf("lod %d: %d clusters (%.1f%% full, %.1f tri/cl, %.1f vtx/cl, %.2f connected, %.1f boundary, %.1f partition), %d triangles",
675-
depth, int(pending.size()),
676-
double(full_clusters) * inv_clusters * 100, double(triangles) * inv_clusters, double(xformed_lod) * inv_clusters, double(components_lod) * inv_clusters, double(boundary_lod) * inv_clusters, avg_group,
677-
int(triangles));
678-
if (stuck_clusters)
679-
printf("; stuck %d clusters (%d triangles)", stuck_clusters, int(stuck_triangles));
680-
printf("\n");
681692

682693
if (kUseRetry)
683694
{

0 commit comments

Comments
 (0)