I build a 3D file conversion tool. Last week I spent two days chasing a bug where converting a CAD assembly produced a mesh that looked perfect and was quietly broken.
The symptom
A STEP assembly with 108 solids. The conversion completed. The preview rendered. Every part was visibly there — correct shape, correct position. Then the QA pass reported that several closed parts were non-manifold.
That shouldn't be possible. A closed solid tessellates to a closed mesh. If it goes in watertight, it comes out watertight.
Narrowing it down
I instrumented each stage.
All 108 solids were read from the STEP file without error. All 108 tessellated individually, each producing a closed, manifold mesh. Verified, one at a time.
Then they were combined, and 84 triangles disappeared.
The cause
After tessellating each solid, the pipeline welded coincident vertices — a standard cleanup step. Two vertices at the same position become one, which removes duplicates and shrinks the output.
The problem is that it ran globally, across the whole assembly.
Where two parts touch — a shaft in a bore, a plate against a plate — both solids have surfaces at the same coordinates. Those vertices are coincident, but they belong to different solids. Welding them merged the two surfaces into one, and the triangles describing the interface between the parts became degenerate and were dropped.
84 triangles, every one of them an interface between two parts that were supposed to stay separate. Every solid that touched another came out with a hole where the contact had been.
Why it's nasty
Nothing errors. The geometry looks right in a viewer, because the holes are internal — at contact faces, hidden inside the model.
You find out downstream. A slicer refuses the file, or a CAD package imports it as a surface body instead of a solid and every operation you reach for is greyed out.
The fix was to keep per-solid topology separate: weld within a solid, never across. 108 solids in, 108 out.
The second bug, which was worse
While I was in there, I found the mesher was being called with the CPU count in the position where the relative deflection parameter belongs. Wrong argument, wrong slot. Parallel meshing was never actually enabled.
That invalidated every performance measurement I'd taken up to that point. Once fixed, sewing on a large assembly went from 655 seconds to 28.
The lesson I keep relearning: when a number looks wrong, check the call signature before you optimise anything.
What this means if you convert meshes
If you're running any mesh converter over assemblies, the thing to check isn't whether the file opened. It's solid count in versus solid count out, and whether each solid is still closed.
A converter reporting "done" is telling you it finished. Not that the result is usable.
I ended up building that verification into my own tool because of this bug — it reports watertightness, manifold edges and solid count before you commit to anything (stlfixtool.com). But the check matters whatever you're using.
Top comments (0)