mirror of
https://github.com/openharmony/third_party_meshoptimizer.git
synced 2026-07-19 20:03:59 -04:00
simplify: Initial implementation of connected components
For pruning, we need to identify small isolated components that can be removed entirely. This requires computing connected components of the mesh graph. There are two ways to look at connectivity, either triangles connected by edges or vertices connected by edges. Both types of analysis are possible, but for now we use vertex analysis. This is easier to compute, and would not require continuous updates as the triangles get collapsed and recreated during edge simplification. For computing components, we could use union-find or a graph traversal. For now we settle on union-find: it's usually measurably faster on complex meshes, and does not require extra memory for a vertex queue. To compute the components, we first do a classical union-find pass over all edges, and then renumber the roots (and other vertices) sequentially, thus mapping every single vertex into a component id.
This commit is contained in:
@@ -1322,6 +1322,67 @@ static void remapEdgeLoops(unsigned int* loop, size_t vertex_count, const unsign
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int follow(unsigned int* parents, unsigned int index)
|
||||
{
|
||||
while (index != parents[index])
|
||||
{
|
||||
unsigned int parent = parents[index];
|
||||
parents[index] = parents[parent];
|
||||
index = parent;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static size_t buildComponents(unsigned int* components, size_t vertex_count, const unsigned int* indices, size_t index_count, const unsigned int* remap)
|
||||
{
|
||||
for (size_t i = 0; i < vertex_count; ++i)
|
||||
components[i] = unsigned(i);
|
||||
|
||||
for (size_t i = 0; i < index_count; i += 3)
|
||||
{
|
||||
static const int next[4] = {1, 2, 0, 1};
|
||||
|
||||
for (int e = 0; e < 3; ++e)
|
||||
{
|
||||
unsigned int i0 = indices[i + e];
|
||||
unsigned int i1 = indices[i + next[e]];
|
||||
|
||||
unsigned int r0 = remap[i0];
|
||||
unsigned int r1 = remap[i1];
|
||||
|
||||
r0 = follow(components, r0);
|
||||
r1 = follow(components, r1);
|
||||
|
||||
if (r0 != r1)
|
||||
components[r0 < r1 ? r1 : r0] = r0 < r1 ? r0 : r1;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < vertex_count; ++i)
|
||||
if (remap[i] == i)
|
||||
components[i] = follow(components, i);
|
||||
|
||||
unsigned int next_component = 0;
|
||||
|
||||
for (size_t i = 0; i < vertex_count; ++i)
|
||||
if (remap[i] == i)
|
||||
{
|
||||
assert(components[i] <= i);
|
||||
if (components[i] == i)
|
||||
components[i] = next_component++;
|
||||
else
|
||||
components[i] = components[components[i]];
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(remap[i] <= i);
|
||||
components[i] = components[remap[i]];
|
||||
}
|
||||
|
||||
return next_component;
|
||||
}
|
||||
|
||||
struct CellHasher
|
||||
{
|
||||
const unsigned int* vertex_ids;
|
||||
@@ -1736,6 +1797,19 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic
|
||||
if (attribute_count)
|
||||
fillAttributeQuadrics(attribute_quadrics, attribute_gradients, result, index_count, vertex_positions, vertex_attributes, attribute_count);
|
||||
|
||||
unsigned int* components = NULL;
|
||||
|
||||
if (options & meshopt_SimplifyPrune)
|
||||
{
|
||||
components = allocator.allocate<unsigned int>(vertex_count);
|
||||
unsigned int cc = buildComponents(components, vertex_count, indices, index_count, remap);
|
||||
(void)cc;
|
||||
|
||||
#if TRACE
|
||||
printf("components: %d\n", int(cc));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TRACE
|
||||
size_t pass_count = 0;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user