diff --git a/demo/nanite.cpp b/demo/nanite.cpp index f05b9304..6ec74810 100644 --- a/demo/nanite.cpp +++ b/demo/nanite.cpp @@ -51,7 +51,7 @@ struct Cluster }; const size_t kClusterSize = 128; -const bool kUseLocks = false; +const bool kUseLocks = true; static LODBounds bounds(const std::vector& vertices, const std::vector& indices, float error) { @@ -276,7 +276,7 @@ static std::vector clusterize(const std::vector& vertices, cons } #ifdef METIS -static std::vector > partitionMetis(const std::vector& clusters, const std::vector& pending) +static std::vector > partitionMetis(const std::vector& clusters, const std::vector& pending, const std::vector& remap) { std::vector > result; @@ -288,8 +288,8 @@ static std::vector > partitionMetis(const std::vector& for (size_t j = 0; j < cluster.indices.size(); ++j) { - int v0 = cluster.indices[j + 0]; - int v1 = cluster.indices[j + (j % 3 == 2 ? -2 : 1)]; + int v0 = remap[cluster.indices[j + 0]]; + int v1 = remap[cluster.indices[j + (j % 3 == 2 ? -2 : 1)]]; std::vector& list = edges[std::make_pair(std::min(v0, v1), std::max(v0, v1))]; if (list.empty() || list.back() != int(i)) @@ -360,14 +360,16 @@ static std::vector > partitionMetis(const std::vector& } #endif -static std::vector > partition(const std::vector& clusters, const std::vector& pending) +static std::vector > partition(const std::vector& clusters, const std::vector& pending, const std::vector& remap) { #ifdef METIS static const char* metis = getenv("METIS"); if (metis && atoi(metis) >= 1) - return partitionMetis(clusters, pending); + return partitionMetis(clusters, pending, remap); #endif + (void)remap; + std::vector > result; size_t last_indices = 0; @@ -388,12 +390,10 @@ static std::vector > partition(const std::vector& clus return result; } -static void lockBoundary(std::vector& locks, const std::vector >& groups, const std::vector& clusters) +static void lockBoundary(std::vector& locks, const std::vector >& groups, const std::vector& clusters, const std::vector& remap) { std::vector groupmap(locks.size(), -1); - memset(&locks[0], 0, locks.size()); - for (size_t i = 0; i < groups.size(); ++i) for (size_t j = 0; j < groups[i].size(); ++j) { @@ -402,13 +402,22 @@ static void lockBoundary(std::vector& locks, const std::vector simplify(const std::vector& vertices, const std::vector& indices, const std::vector* locks, size_t target_count, float* error = NULL) @@ -460,10 +469,16 @@ void nanite(const std::vector& vertices, const std::vector int depth = 0; std::vector locks(vertices.size()); + // for cluster connectivity, we need a position-only remap that maps vertices with the same position to the same index + // it's more efficient to build it once; unfortunately, meshopt_generateVertexRemap doesn't support stride so we need to use *Multi version + std::vector remap(vertices.size()); + meshopt_Stream position = {&vertices[0].px, sizeof(float) * 3, sizeof(Vertex)}; + meshopt_generateVertexRemapMulti(&remap[0], &indices[0], indices.size(), vertices.size(), &position, 1); + // merge and simplify clusters until we can't merge anymore while (pending.size() > 1) { - std::vector > groups = partition(clusters, pending); + std::vector > groups = partition(clusters, pending, remap); pending.clear(); std::vector retry; @@ -478,7 +493,7 @@ void nanite(const std::vector& vertices, const std::vector dumpObj(vertices, std::vector()); if (kUseLocks) - lockBoundary(locks, groups, clusters); + lockBoundary(locks, groups, clusters, remap); // every group needs to be simplified now for (size_t i = 0; i < groups.size(); ++i)