I had opened a PR for this issue, but after receiving feedback from @zeux, switching to doubles are not an acceptable solution.
example_stls.zip
There's a test that reproduces this issue on that PR:
https://github.com/zeux/meshoptimizer/pull/1062/changes#diff-8388a4114e325ed357a660cc215d5a1281f1d0977714e8b52f15e55261bee5d0R1802
I've also attached a repro stl, and the result of the meshopt simplify call.
Here's a visual representation of the issue:
Here's the code I used to generate the failure output.
// Minimal STL -> meshopt_simplify -> STL round trip.
// Usage: ./simplify_stl input.stl output.stl target_index_count target_error
#include <cstdio>
#include <cstring>
#include <vector>
#include "src/meshoptimizer.h"
int main(int argc, char** argv)
{
if (argc != 5)
{
fprintf(stderr, "usage: %s input.stl output.stl target_index_count target_error\n", argv[0]);
return 1;
}
// --- read binary STL as triangle soup (3 unindexed verts per triangle) ---
FILE* in = fopen(argv[1], "rb");
char header[80];
fread(header, 1, 80, in);
unsigned int triCount;
fread(&triCount, sizeof(triCount), 1, in);
std::vector<float> soup(triCount * 3 * 3);
for (unsigned int i = 0; i < triCount; ++i)
{
float normal[3];
fread(normal, sizeof(float), 3, in);
fread(&soup[i * 9], sizeof(float), 9, in);
unsigned short attr;
fread(&attr, sizeof(attr), 1, in);
}
fclose(in);
size_t indexCount = triCount * 3;
// --- weld duplicate positions into an indexed mesh ---
std::vector<unsigned int> remap(indexCount);
size_t vertexCount = meshopt_generateVertexRemap(&remap[0], NULL, indexCount, &soup[0], indexCount, 12);
std::vector<unsigned int> indices(indexCount);
std::vector<float> vertices(vertexCount * 3);
meshopt_remapIndexBuffer(&indices[0], NULL, indexCount, &remap[0]);
meshopt_remapVertexBuffer(&vertices[0], &soup[0], indexCount, 12, &remap[0]);
printf("loaded: %zu triangles, %zu unique vertices\n", indexCount / 3, vertexCount);
// --- simplify ---
size_t targetIndexCount = atoi(argv[3]);
float targetError = atof(argv[4]);
std::vector<unsigned int> result(indexCount);
float error = 0;
size_t resultCount = meshopt_simplify(&result[0], &indices[0], indexCount, &vertices[0], vertexCount, 12,
targetIndexCount, targetError, 0, &error);
result.resize(resultCount);
printf("simplified: %zu triangles, error=%g\n", resultCount / 3, error);
// --- write result back out as binary STL (triangle soup, zero normals) ---
FILE* out = fopen(argv[2], "wb");
memset(header, 0, 80);
fwrite(header, 1, 80, out);
unsigned int outTriCount = (unsigned int)(resultCount / 3);
fwrite(&outTriCount, sizeof(outTriCount), 1, out);
for (size_t i = 0; i < resultCount; i += 3)
{
float normal[3] = {0, 0, 0};
fwrite(normal, sizeof(float), 3, out);
for (int k = 0; k < 3; ++k)
fwrite(&vertices[result[i + k] * 3], sizeof(float), 3, out);
unsigned short attr = 0;
fwrite(&attr, sizeof(attr), 1, out);
}
fclose(out);
return 0;
}
I had opened a PR for this issue, but after receiving feedback from @zeux, switching to doubles are not an acceptable solution.
example_stls.zip
There's a test that reproduces this issue on that PR:
https://github.com/zeux/meshoptimizer/pull/1062/changes#diff-8388a4114e325ed357a660cc215d5a1281f1d0977714e8b52f15e55261bee5d0R1802
I've also attached a repro stl, and the result of the meshopt simplify call.
Here's a visual representation of the issue:
Here's the code I used to generate the failure output.