Skip to content

Commit

Permalink
Merge pull request #720 from zeux/simp-debug
Browse files Browse the repository at this point in the history
simplify: Rework internal debug visualization code
  • Loading branch information
zeux authored Jul 12, 2024
2 parents f16ee88 + 3c6f9b0 commit 284b2fa
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 61 deletions.
78 changes: 32 additions & 46 deletions gltf/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,13 @@ static Stream* getStream(Mesh& mesh, cgltf_attribute_type type, int index = 0)
return NULL;
}

static void simplifyMesh(Mesh& mesh, float threshold, bool attributes, bool aggressive, bool lock_borders)
static void simplifyMesh(Mesh& mesh, float threshold, bool attributes, bool aggressive, bool lock_borders, bool debug = false)
{
enum
{
meshopt_SimplifyInternalDebug = 1 << 30
};

assert(mesh.type == cgltf_primitive_type_triangles);

if (mesh.indices.empty())
Expand All @@ -543,7 +548,11 @@ static void simplifyMesh(Mesh& mesh, float threshold, bool attributes, bool aggr
size_t target_index_count = size_t(double(mesh.indices.size() / 3) * threshold) * 3;
float target_error = 1e-2f;
float target_error_aggressive = 1e-1f;
unsigned int options = lock_borders ? meshopt_SimplifyLockBorder : 0;
unsigned int options = 0;
if (lock_borders)
options |= meshopt_SimplifyLockBorder;
if (debug)
options |= meshopt_SimplifyInternalDebug;

const Stream* attr = getStream(mesh, cgltf_attribute_type_color);
attr = attr ? attr : getStream(mesh, cgltf_attribute_type_normal);
Expand Down Expand Up @@ -784,10 +793,6 @@ void processMesh(Mesh& mesh, const Settings& settings)
}

#ifndef NDEBUG
extern MESHOPTIMIZER_API unsigned char* meshopt_simplifyDebugKind;
extern MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop;
extern MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack;

void debugSimplify(const Mesh& source, Mesh& kinds, Mesh& loops, float ratio, bool attributes)
{
Mesh mesh = source;
Expand All @@ -799,27 +804,9 @@ void debugSimplify(const Mesh& source, Mesh& kinds, Mesh& loops, float ratio, bo
reindexMesh(mesh);
filterTriangles(mesh);

// before simplification we need to setup target kind/loop arrays
size_t vertex_count = mesh.streams[0].data.size();

std::vector<unsigned char> kind(vertex_count);
std::vector<unsigned int> loop(vertex_count);
std::vector<unsigned int> loopback(vertex_count);
std::vector<unsigned char> live(vertex_count);

meshopt_simplifyDebugKind = &kind[0];
meshopt_simplifyDebugLoop = &loop[0];
meshopt_simplifyDebugLoopBack = &loopback[0];

simplifyMesh(mesh, ratio, attributes, /* aggressive= */ false, /* lock_borders= */ false);

meshopt_simplifyDebugKind = NULL;
meshopt_simplifyDebugLoop = NULL;
meshopt_simplifyDebugLoopBack = NULL;

// fill out live info
for (size_t i = 0; i < mesh.indices.size(); ++i)
live[mesh.indices[i]] = true;
simplifyMesh(mesh, ratio, attributes, /* aggressive= */ false, /* lock_borders= */ false, /* debug= */ true);

// color palette for display
static const Attr kPalette[] = {
Expand Down Expand Up @@ -850,38 +837,37 @@ void debugSimplify(const Mesh& source, Mesh& kinds, Mesh& loops, float ratio, bo

// transform kind/loop data into lines & points
Stream colors = {cgltf_attribute_type_color};
colors.data.resize(vertex_count);

for (size_t i = 0; i < vertex_count; ++i)
colors.data[i] = kPalette[kind[i]];
colors.data.resize(vertex_count, kPalette[0]);

kinds.type = cgltf_primitive_type_points;

kinds.streams.push_back(colors);

for (size_t i = 0; i < vertex_count; ++i)
if (live[i] && kind[i] != 0)
kinds.indices.push_back(unsigned(i));

loops.type = cgltf_primitive_type_lines;

loops.streams.push_back(colors);

for (size_t i = 0; i < vertex_count; ++i)
if (live[i] && (kind[i] == 1 || kind[i] == 2))
for (size_t i = 0; i < mesh.indices.size(); i += 3)
{
for (int k = 0; k < 3; ++k)
{
if (loop[i] != ~0u && live[loop[i]])
const unsigned int mask = (1 << 28) - 1;
unsigned int v = mesh.indices[i + k];
unsigned int next = mesh.indices[i + (k + 1) % 3];
unsigned int vk = (v >> 28) & 7;
unsigned int vl = v >> 31;

if (vk)
{
loops.indices.push_back(unsigned(i));
loops.indices.push_back(loop[i]);
colors.data[v & mask] = kPalette[vk];
kinds.indices.push_back(v & mask);
}

if (loopback[i] != ~0u && live[loopback[i]])
if (vl)
{
loops.indices.push_back(loopback[i]);
loops.indices.push_back(unsigned(i));
loops.indices.push_back(v & mask);
loops.indices.push_back(next & mask);
}
}
}

kinds.streams.push_back(colors);
loops.streams.push_back(colors);
}

void debugMeshlets(const Mesh& source, Mesh& meshlets, int max_vertices, bool scan)
Expand Down
33 changes: 18 additions & 15 deletions src/simplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1546,12 +1546,11 @@ static float interpolate(float y, float x0, float y0, float x1, float y1, float

} // namespace meshopt

#ifndef NDEBUG
// Note: this is only exposed for debug visualization purposes; do *not* use these in debug builds
MESHOPTIMIZER_API unsigned char* meshopt_simplifyDebugKind = NULL;
MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop = NULL;
MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = NULL;
#endif
// Note: this is only exposed for debug visualization purposes; do *not* use
enum
{
meshopt_SimplifyInternalDebug = 1 << 30
};

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 char* vertex_lock, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
{
Expand All @@ -1561,7 +1560,7 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic
assert(vertex_positions_stride >= 12 && vertex_positions_stride <= 256);
assert(vertex_positions_stride % sizeof(float) == 0);
assert(target_index_count <= index_count);
assert((options & ~(meshopt_SimplifyLockBorder | meshopt_SimplifySparse | meshopt_SimplifyErrorAbsolute)) == 0);
assert((options & ~(meshopt_SimplifyLockBorder | meshopt_SimplifySparse | meshopt_SimplifyErrorAbsolute | meshopt_SimplifyInternalDebug)) == 0);
assert(vertex_attributes_stride >= attribute_count * sizeof(float) && vertex_attributes_stride <= 256);
assert(vertex_attributes_stride % sizeof(float) == 0);
assert(attribute_count <= kMaxAttributes);
Expand Down Expand Up @@ -1705,16 +1704,20 @@ size_t meshopt_simplifyEdge(unsigned int* destination, const unsigned int* indic
printf("result: %d triangles, error: %e; total %d passes\n", int(result_count / 3), sqrtf(result_error), int(pass_count));
#endif

#ifndef NDEBUG
if (meshopt_simplifyDebugKind)
memcpy(meshopt_simplifyDebugKind, vertex_kind, vertex_count);
// if debug visualization data is requested, fill it instead of index data; for simplicity, this doesn't work with sparsity
if ((options & meshopt_SimplifyInternalDebug) && !sparse_remap)
{
assert(Kind_Count <= 8 && vertex_count < (1 << 28)); // 3 bit kind, 1 bit loop

if (meshopt_simplifyDebugLoop)
memcpy(meshopt_simplifyDebugLoop, loop, vertex_count * sizeof(unsigned int));
for (size_t i = 0; i < result_count; i += 3)
{
unsigned int a = result[i + 0], b = result[i + 1], c = result[i + 2];

if (meshopt_simplifyDebugLoopBack)
memcpy(meshopt_simplifyDebugLoopBack, loopback, vertex_count * sizeof(unsigned int));
#endif
result[i + 0] |= (vertex_kind[a] << 28) | (unsigned(loop[a] == b || loopback[b] == a) << 31);
result[i + 1] |= (vertex_kind[b] << 28) | (unsigned(loop[b] == c || loopback[c] == b) << 31);
result[i + 2] |= (vertex_kind[c] << 28) | (unsigned(loop[c] == a || loopback[a] == c) << 31);
}
}

// convert resulting indices back into the dense space of the larger mesh
if (sparse_remap)
Expand Down

0 comments on commit 284b2fa

Please sign in to comment.