Skip to content

import(): AMF, X3D and VRML97; a .pdf or malformed SVG no longer hangs - #219

Merged
revarbat merged 3 commits into
mainfrom
feature/amf-x3d-vrml-import
Sep 30, 2026
Merged

revarbat merged 3 commits into
mainfrom
feature/amf-x3d-vrml-import

Conversation

@revarbat

@revarbat revarbat commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

import() now reads AMF, X3D and VRML97, the three multi-object formats export writes that nothing could read back. Current upstream OpenSCAD removed its AMF importer (bf7a0970b), so all three go beyond it.

Geometry only, like the STL/OBJ/OFF/3MF loaders, but each format's scene structure is honoured:

  • X3D and VRML97
    • Transforms nest and apply in full: translation, rotation, scale, center and scaleOrientation (T·C·R·SR·S·SR⁻¹·C⁻¹).
    • DEF/USE resolves, and ccw FALSE flips winding.
    • IndexedFaceSet polygons are fan-triangulated; a last polygon without -1 still counts.
    • X3D also reads IndexedTriangleSet and TriangleSet.
    • X3D goes through a small real XML parser (comments, CDATA, DOCTYPE, entities). VRML goes through a tokenizer and generic node parser that steps over PROTO, EXTERNPROTO and ROUTE; VRML 1.0 is refused by name.
  • AMF: plain or zipped (read like 3MF), with unit (inch, feet, metre, micron) scaled to mm.
  • What isn't a mesh (X3D/VRML primitives, Inline, AMF constellations) is skipped with a warning, import: '<file>': skipped what is not a mesh: 1 Box, from both the geometry and expression forms of import().

Tested (8 new tests):

  • Round trips: our own AMF, X3D and VRML exports import back at exact volume.
  • Hand-written X3D: a scaled cube, the same cube reused with USE under a rotation, a tetrahedron with ccw="false" and a Box. Expected and got a volume of 13.5, the right bounding box, and the Box warning.
  • Hand-written VRML: the same scene plus PROTO/ROUTE/comments. Expected and got volume 9, and a maximum x of 30, which proves the rotation applied.
  • AMF in inches, plain and zipped: exactly 25.4³, plus the constellation warning.
  • Errors: a face index past its points is an error.

Suites: all 1346 C++ tests pass, all 61 binding tests pass, and BelfrySCAD's full suite (2187) passes against this build.

Also fixes an import() hang. The SVG parser's attribute loop stopped on a character no attribute can start with (a / not followed by >, a stray =) without consuming it, then came back to it forever. A PDF is full of /Name, so import("x.pdf") (routed to the SVG parser) hung for good, and so did a malformed SVG like <a / b>. The loop now steps past such a character, and .pdf is no longer routed to the SVG parser: nothing reads PDF (OpenSCAD doesn't either), so it gets the ordinary "unsupported file type" error. Both files that hung now fail in under half a second, and 3 new tests cover them.

🤖 Generated with Claude Code

revarbat and others added 3 commits September 29, 2026 22:47
The three multi-object formats export writes that nothing could read
back. Geometry only, like the other mesh loaders, but each format's scene
structure is honoured:

- X3D and VRML: Transforms nest and apply in full (translation, rotation,
  scale, center, scaleOrientation), DEF/USE resolves, ccw FALSE flips
  winding, IndexedFaceSet polygons fan-triangulate; X3D also reads
  IndexedTriangleSet and TriangleSet. X3D goes through a small XML
  parser, VRML through a tokenizer and generic node parser that steps
  over PROTO, EXTERNPROTO and ROUTE. VRML 1.0 is refused by name.
- AMF: plain or zipped, unit scaled to millimetres.

What is not a mesh -- X3D/VRML primitives, Inline, AMF constellations --
is reported through LoadedMesh::warnings, which both faces of import()
emit. Current upstream OpenSCAD removed its AMF importer, so all three go
beyond it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SVG parser's attribute loop stopped on a character no attribute can
start with -- a '/' not followed by '>', a stray '=' -- without consuming
it, and came straight back to it forever. A PDF is full of "/Name", so
import("x.pdf"), which routed .pdf to the SVG parser, hung for good; so
did a malformed SVG such as `<a / b>`. The loop now steps past such a
character, and .pdf is no longer routed to the SVG parser at all: nothing
reads PDF (OpenSCAD does not either), so it takes the ordinary
"unsupported file type '.pdf'" error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@revarbat revarbat changed the title import(): AMF, X3D and VRML97 import(): AMF, X3D and VRML97; a .pdf or malformed SVG no longer hangs Sep 30, 2026
@revarbat
revarbat merged commit 96574e9 into main Sep 30, 2026
11 checks passed
@revarbat
revarbat deleted the feature/amf-x3d-vrml-import branch September 30, 2026 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant