Skip to content

Commit

Permalink
simplify: Reduce the number of passes in some edge cases
Browse files Browse the repository at this point in the history
We previously would stop the pass when we reached the error goal,
computed as the 1.5 * collapse error #k where k is the number of edges
we need to collapse.

This heuristic was designed to provide a balance between stopping too
early, when we could have collapsed more edges in a single pass, and
collapsing too many edges when the next pass could have edges with
smaller error (since they will become available for collapse due to not
being locked anymore).

On some meshes, this resulted in very large number of passes where each
pass would collapse just a few edges. As an extreme example,
hairball.obj had ? passes.
  • Loading branch information
zeux committed Mar 17, 2019
1 parent fccabf8 commit 6fda9ea
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions src/simplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse
}
}

static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, Quadric* vertex_quadrics, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, size_t triangle_collapse_goal, float error_limit)
static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char* collapse_locked, Quadric* vertex_quadrics, const Collapse* collapses, size_t collapse_count, const unsigned int* collapse_order, const unsigned int* remap, const unsigned int* wedge, const unsigned char* vertex_kind, size_t triangle_collapse_goal, float error_goal, float error_limit)
{
size_t edge_collapses = 0;
size_t triangle_collapses = 0;
Expand All @@ -782,6 +782,9 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
if (c.error > error_limit)
break;

if (c.error > error_goal && triangle_collapses > triangle_collapse_goal / 10)
break;

if (triangle_collapses >= triangle_collapse_goal)
break;

Expand Down Expand Up @@ -1151,7 +1154,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
size_t result_count = index_count;

// target_error input is linear; we need to adjust it to match quadricError units
float error_target = target_error * target_error;
float error_limit = target_error * target_error;

while (result_count > target_index_count)
{
Expand Down Expand Up @@ -1179,14 +1182,13 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
const float kPassErrorBound = 1.5f;

float error_goal = edge_collapse_goal < edge_collapse_count ? edge_collapses[collapse_order[edge_collapse_goal]].error * kPassErrorBound : FLT_MAX;
float error_limit = error_goal < error_target ? error_goal : error_target;

for (size_t i = 0; i < vertex_count; ++i)
collapse_remap[i] = unsigned(i);

memset(collapse_locked, 0, vertex_count);

size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, vertex_quadrics, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, triangle_collapse_goal, error_limit);
size_t collapses = performEdgeCollapses(collapse_remap, collapse_locked, vertex_quadrics, edge_collapses, edge_collapse_count, collapse_order, remap, wedge, vertex_kind, triangle_collapse_goal, error_goal, error_limit);

// no edges can be collapsed any more due to hitting the error limit or triangle collapse limit
if (collapses == 0)
Expand Down

0 comments on commit 6fda9ea

Please sign in to comment.