Skip to content

Commit

Permalink
simplify: Remove target_error from simplifySloppy
Browse files Browse the repository at this point in the history
Also expand documentation for simplify/simplifySloppy and add
ACCELERATE_BINARY option back which allows us to skip binary passes.
It's not clear whether we're going to *really* need binary passes for
performance - I'd like to either figure out a way to only use binary
data (which could be substantially faster), or a way to never use it
(which could be substantially less code).
  • Loading branch information
zeux committed Feb 6, 2019
1 parent d1f600c commit 2152028
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 16 deletions.
3 changes: 1 addition & 2 deletions demo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,9 @@ void simplifySloppy(const Mesh& mesh)

float threshold = 0.2f;
size_t target_index_count = size_t(mesh.indices.size() * threshold);
float target_error = 1e-3f;

lod.indices.resize(mesh.indices.size());
lod.indices.resize(meshopt_simplifySloppy(&lod.indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_index_count, target_error));
lod.indices.resize(meshopt_simplifySloppy(&lod.indices[0], &mesh.indices[0], mesh.indices.size(), &mesh.vertices[0].px, mesh.vertices.size(), sizeof(Vertex), target_index_count));

lod.vertices.resize(mesh.vertices.size());
lod.vertices.resize(meshopt_optimizeVertexFetch(&lod.vertices[0], &lod.indices[0], lod.indices.size(), &mesh.vertices[0], mesh.vertices.size(), sizeof(Vertex)));
Expand Down
19 changes: 16 additions & 3 deletions src/meshoptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ MESHOPTIMIZER_API int meshopt_decodeVertexBuffer(void* destination, size_t verte
/**
* Experimental: Mesh simplifier
* Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible
* The algorithm tries to preserve mesh topology and can stop short of the target goal based on topology constraints or target error.
* If not all attributes from the input mesh are required, it's recommended to reindex the mesh using meshopt_generateShadowIndexBuffer prior to simplification.
* Returns the number of indices after simplification, with destination containing new index data
* The resulting index buffer references vertices from the original vertex buffer.
* If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
Expand All @@ -200,7 +202,18 @@ MESHOPTIMIZER_API int meshopt_decodeVertexBuffer(void* destination, size_t verte
*/
MESHOPTIMIZER_EXPERIMENTAL 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);

MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(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);
/**
* Experimental: Mesh simplifier (sloppy)
* Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
* The algorithm doesn't preserve mesh topology but is always able to reach target triangle count.
* Returns the number of indices after simplification, with destination containing new index data
* The resulting index buffer references vertices from the original vertex buffer.
* If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended.
*
* destination must contain enough space for the target index buffer
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
*/
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(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);

/**
* Mesh stripifier
Expand Down Expand Up @@ -532,12 +545,12 @@ inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_co
}

template <typename T>
inline size_t meshopt_simplifySloppy(T* destination, const T* 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)
inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count)
{
meshopt_IndexAdapter<T> in(0, indices, index_count);
meshopt_IndexAdapter<T> out(destination, 0, index_count);

return meshopt_simplifySloppy(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error);
return meshopt_simplifySloppy(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count);
}

template <typename T>
Expand Down
36 changes: 25 additions & 11 deletions src/simplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include <stdio.h>
#endif

// Should we use binary passes to accelerate discovery of the initial region
#define SLOP_ACCELERATE_BINARY 1

// Should we filter duplicate triangles? Normally there's few of them, but in some meshes there's a lot. Filtering is done after targeting...
#define SLOP_FILTER_DUPLICATES 1

Expand Down Expand Up @@ -908,6 +911,7 @@ struct TriangleHasher
}
};

#if SLOP_ACCELERATE_BINARY
static void computeVertexIds(unsigned int* vertex_ids, const Vector3* vertex_positions, size_t vertex_count)
{
for (size_t i = 0; i < vertex_count; ++i)
Expand Down Expand Up @@ -980,6 +984,7 @@ static size_t fillVertexCellsPow2(HashCell* table, size_t table_size, unsigned i

return cell_count;
}
#endif

static size_t fillVertexCells(HashCell* table, size_t table_size, unsigned int* vertex_cells, const Vector3* vertex_positions, size_t vertex_count, int grid_size)
{
Expand Down Expand Up @@ -1279,10 +1284,8 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
return result_count;
}

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)
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)
{
(void)target_error; // TODO

using namespace meshopt;

assert(index_count % 3 == 0);
Expand All @@ -1307,11 +1310,21 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind
printf("target: %d cells, %d triangles\n", int(target_cell_count), int(target_index_count / 3));
#endif

unsigned int* vertex_cells = allocator.allocate<unsigned int>(vertex_count);
unsigned int* vertex_cells_temp = allocator.allocate<unsigned int>(vertex_count);

// TODO: we don't need a table this large if we're limiting the number of unique elements we're adding to the table
// Especially if we can alloc this *after* the counting pass, with an approx *2 size or whatever?
size_t table_size = hashBuckets2(vertex_count);
HashCell* table = allocator.allocate<HashCell>(table_size);

#if SLOP_ACCELERATE_BINARY
unsigned int* vertex_ids = allocator.allocate<unsigned int>(vertex_count);
computeVertexIds(vertex_ids, vertex_positions, vertex_count);

size_t count_table_size = hashBuckets2(target_cell_count * 4);
unsigned char* count_table = allocator.allocate<unsigned char>(count_table_size);
#endif

int bits = 10;

Expand All @@ -1323,7 +1336,11 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind
if (unsigned(grid_size * grid_size * grid_size) < target_cell_count)
continue;

#if SLOP_ACCELERATE_BINARY
size_t cells = countVertexCellsPow2(count_table, count_table_size, vertex_ids, vertex_count, grid_size);
#else
size_t cells = fillVertexCells(table, table_size, vertex_cells, vertex_positions, vertex_count, grid_size);
#endif

#if TRACE
printf("binary pass %d: cell count %d, grid size %d, cell size %.4f\n", pass, int(cells), grid_size, 1.f / float(grid_size));
Expand All @@ -1338,14 +1355,6 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind

size_t cell_count = 0;

unsigned int* vertex_cells = allocator.allocate<unsigned int>(vertex_count);
unsigned int* vertex_cells_temp = allocator.allocate<unsigned int>(vertex_count);

// TODO: we don't need a table this large if we're limiting the number of unique elements we're adding to the table
// Especially if we can alloc this *after* the counting pass, with an approx *2 size or whatever?
size_t table_size = hashBuckets2(vertex_count);
HashCell* table = allocator.allocate<HashCell>(table_size);

// invariant: # of triangles in min_grid <= target_count
// note that we do *not* validate that max_grid is over target_count - it basically almost is, since it has >target_cell_count cells,
// but even when this is violated our algorithm will just converge to a somewhat simpler mesh.
Expand All @@ -1355,7 +1364,12 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind
// note that we are *not* guaranteed that min_grid gives us <target_index_count triangles! because of this, we need to iteratively adjust it until it does
while (min_grid > 1)
{
#if SLOP_ACCELERATE_BINARY
size_t cells = fillVertexCellsPow2(table, table_size, vertex_cells, vertex_ids, vertex_count, min_grid);
#else
size_t cells = fillVertexCells(table, table_size, vertex_cells, vertex_positions, vertex_count, min_grid);
#endif

size_t triangles = countTriangles(vertex_cells, indices, index_count);

#if TRACE
Expand Down

0 comments on commit 2152028

Please sign in to comment.