Skip to content

Commit

Permalink
Added API to specify which vertices to lock when simplifying
Browse files Browse the repository at this point in the history
  • Loading branch information
oisyn committed Sep 19, 2023
1 parent 41d9362 commit 2c59655
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 12 deletions.
11 changes: 10 additions & 1 deletion src/meshoptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,15 @@ enum
*/
MESHOPTIMIZER_API size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error);

/**
* Mesh simplifier which locks a given list of vertices
* Works like meshopt_simplify, but accept a list of vertices not allowed to collapse. Other vertices are still allowed to collapse onto locked vertices.
*
* locked_vertices points to an array of vertex indices, denoting which vertices are to be locked. Can be NULL if locked_vertex_count is 0.
* locked_vertex_count number of elements in the locked_vertices array.
*/
MESHOPTIMIZER_API size_t meshopt_simplifyWithLocks(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const unsigned int* locked_vertices, size_t locked_vertex_count, size_t target_index_count, float target_error, unsigned int options, float* result_error);

/**
* Experimental: Mesh simplifier with attribute metric
* The algorithm ehnahces meshopt_simplify by incorporating attribute values into the error metric used to prioritize simplification order; see meshopt_simplify documentation for details.
Expand All @@ -356,7 +365,7 @@ MESHOPTIMIZER_API size_t meshopt_simplify(unsigned int* destination, const unsig
* attribute_weights should have attribute_count floats in total; the weights determine relative priority of attributes between each other and wrt position. The recommended weight range is [1e-3..1e-1], assuming attribute data is in [0..1] range.
* TODO target_error/result_error currently use combined distance+attribute error; this may change in the future
*/
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* result_error);
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned int* locked_vertices, size_t locked_vertex_count, size_t target_index_count, float target_error, unsigned int options, float* result_error);

/**
* Experimental: Mesh simplifier (sloppy)
Expand Down
34 changes: 23 additions & 11 deletions src/simplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ static bool hasEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned int
return false;
}

static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge, unsigned int options)
static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge, const unsigned int* locked_vertices, size_t locked_vertex_count, unsigned int options)
{
memset(loop, -1, vertex_count * sizeof(unsigned int));
memset(loopback, -1, vertex_count * sizeof(unsigned int));
Expand Down Expand Up @@ -362,6 +362,9 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
}
}

for (size_t i = 0; i < locked_vertex_count; i++)
result[remap[locked_vertices[i]]] = Kind_Locked;

if (options & meshopt_SimplifyLockBorder)
for (size_t i = 0; i < vertex_count; ++i)
if (result[i] == Kind_Border)
Expand Down Expand Up @@ -571,7 +574,7 @@ static float quadricError(const Quadric& Q, const QuadricGrad* G, size_t attribu
}

// TODO: weight normalization is breaking attribute error somehow
float s = 1;// Q.w == 0.f ? 0.f : 1.f / Q.w;
float s = 1; // Q.w == 0.f ? 0.f : 1.f / Q.w;

return fabsf(r) * s;
}
Expand Down Expand Up @@ -1423,7 +1426,7 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop = 0;
MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0;
#endif

size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned int* locked_vertices, size_t locked_vertex_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
{
using namespace meshopt;

Expand Down Expand Up @@ -1454,7 +1457,7 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic
unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
unsigned int* loop = allocator.allocate<unsigned int>(vertex_count);
unsigned int* loopback = allocator.allocate<unsigned int>(vertex_count);
classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge, options);
classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge, locked_vertices, locked_vertex_count, options);

#if TRACE
size_t unique_positions = 0;
Expand Down Expand Up @@ -1589,12 +1592,17 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic

size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
{
return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, NULL, 0, NULL, 0, target_index_count, target_error, options, out_result_error);
return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, NULL, 0, NULL, 0, NULL, 0, target_index_count, target_error, options, out_result_error);
}

size_t meshopt_simplifyWithLocks(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const unsigned int* locked_vertices, size_t locked_vertex_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
{
return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, NULL, 0, NULL, 0, locked_vertices, locked_vertex_count, target_index_count, target_error, options, out_result_error);
}

size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, const float* vertex_attributes_data, size_t vertex_attributes_stride, const float* attribute_weights, size_t attribute_count, const unsigned int* locked_vertices, size_t locked_vertex_count, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
{
return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, vertex_attributes_data, vertex_attributes_stride, attribute_weights, attribute_count, target_index_count, target_error, options, out_result_error);
return meshopt_simplifyEdge(destination, indices, index_count, vertex_positions_data, vertex_count, vertex_positions_stride, vertex_attributes_data, vertex_attributes_stride, attribute_weights, attribute_count, locked_vertices, locked_vertex_count, target_index_count, target_error, options, out_result_error);
}

size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
Expand Down Expand Up @@ -1647,14 +1655,16 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind

// we clamp the prediction of the grid size to make sure that the search converges
int grid_size = next_grid_size;
grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1 : grid_size;
grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1
: grid_size;

computeVertexIds(vertex_ids, vertex_positions, vertex_count, grid_size);
size_t triangles = countTriangles(vertex_ids, indices, index_count);

#if TRACE
printf("pass %d (%s): grid size %d, triangles %d, %s\n",
pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp" : "binary",
pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp"
: "binary",
grid_size, int(triangles),
(triangles <= target_index_count / 3) ? "under" : "over");
#endif
Expand Down Expand Up @@ -1776,14 +1786,16 @@ size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_pos

// we clamp the prediction of the grid size to make sure that the search converges
int grid_size = next_grid_size;
grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1 : grid_size;
grid_size = (grid_size <= min_grid) ? min_grid + 1 : (grid_size >= max_grid) ? max_grid - 1
: grid_size;

computeVertexIds(vertex_ids, vertex_positions, vertex_count, grid_size);
size_t vertices = countVertexCells(table, table_size, vertex_ids, vertex_count);

#if TRACE
printf("pass %d (%s): grid size %d, vertices %d, %s\n",
pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp" : "binary",
pass, (pass == 0) ? "guess" : (pass <= kInterpolationPasses) ? "lerp"
: "binary",
grid_size, int(vertices),
(vertices <= target_vertex_count) ? "under" : "over");
#endif
Expand Down

0 comments on commit 2c59655

Please sign in to comment.