Skip to content

Simplification failure on flat surfaces #1065

Description

@snowbldr

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:

Image

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;
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions