Interoperability · STL & OBJ

STL & OBJ — the mesh spokes

STL is where B-rep meets the printer. NativeCAD's STL export runs the kernel's own tessellator — the same one the browser viewer and the headless batch pipeline use — and its options are the clearest example of the speed dial: you choose the fidelity, the budget, or reuse a mesh you already paid for. Import wiring shipped 2026-08-29: a triangle soup is not a B-rep, so a .stl or .obj import publishes a distinct mesh body rather than pretending to be a solid.

Import — cad_import

STL and OBJ both parse into the same mesh channel: the result carries a meshId, never a solidId, and every solid-taking verb (fillet, boolean, DFM check) refuses a later reference to it by absence of a body — the same honest refusal a sheet-only IGES import gets, rather than a silent no-op or a crash. Nothing about the file's own geometry is rewritten unless you ask.

OptionKindWhat it does
healbehavior Runs ops/meshHeal.js's weld / de-degenerate / re-orient / fill-holes pass and attaches its report as imported.heal. Off by default — a raw import never silently rewrites the file's own geometry.
unitsbehavior STL and OBJ declare no reliable unit of their own; the importer defaults to millimetres, and units overrides it the same way it does on every other format.

Reconstruction — cad_mesh_to_brep

A mesh body is not a dead end. cad_mesh_to_brep segments the triangles, recognizes planes/cylinders/cones/spheres/tori and fits the rest, then sews and heals the result back into an editable, fillet-able, STEP-round-trippable B-rep — reverse engineering, not just import. Mesh in; reconstruct to B-rep, measured on the RECON sprint's own scoreboard against the input mesh itself (ops/meshCompare.js, full scoreboard →): bracket −0.017 % volume error, 12 cylinder + 6 plane faces recovered as an editable extrude + hole_pattern plan (CADSF-1415); the real STL sample below, nativecad-plate.stl, comes back the same way at +0.010 % (CADSF-1415, pinned again on the real file in CADSF-1419). See the NURBS ops showcase for a live before/after pair on a real STL, with a download of both the input mesh and the reconstructed STEP.

Export — cad_export_body format:"stl"

OptionKindWhat it does
binarybehavior Binary STL by default; false streams ASCII STL for tools and diffs that want text.
tolerancespeed Chord tolerance in mm — the max deviation between triangles and the true surface. Smaller is finer, slower, bigger; omit for the kernel default.
maxTrianglesspeed A hard triangle budget: the tessellator adapts its resolution to come in at or under it, and the response's lod field reports what was achieved — including an explicit shortfall flag rather than a silent overrun.
handlespeed Reuse a mesh from a prior cad_tessellate_body call instead of re-tessellating — export twice, tessellate once.
healGeometrybehavior Attempt to heal small topology defects (gaps, sliver faces) before tessellating. Off by default so healing is a choice, never a surprise.
ofskips translation Export one named body out of a multi-body document instead of everything.

Try it

STL nativecad-plate.stl 156 KB

The kernel-authored sample plate, watertight at 3,188 triangles from the default chord tolerance — drag it into any slicer.

Also available in the browser modeler

The live modeler opens STL and OBJ by drag-drop the same way it always has: the mesh lands as a registered body in the feature tree (selectable, measurable, mass-properties-capable), and a non-watertight mesh is offered healing — showing exactly what was welded, filled, and refused. Operations a triangle soup genuinely cannot support (you can't fillet a facet) show as named capability locks rather than silently disappearing. The kernel-verb heal above runs the same ops/meshHeal.js pass.

Roadmap: 3MF import (the slicer round-trip, mesh channel like STL/OBJ) shipped alongside this wave — see the 3MF page.