Skip to content

feat(exporting): add native glTF 2.0 and GLB export - #515

Open
JarrettSJohnson wants to merge 11 commits into
masterfrom
codex/issue-497-gltf-glb
Open

JarrettSJohnson wants to merge 11 commits into
masterfrom
codex/issue-497-gltf-glb

Conversation

@JarrettSJohnson

@JarrettSJohnson JarrettSJohnson commented Jul 25, 2026 •

Copy link
Copy Markdown
Member

Summary

Implements the glTF/GLB portion of #497 by adding native glTF 2.0 and binary GLB export without the external COLLADA2GLTF conversion step. The exporter preserves geometry scale (1 unit = 1 Å), vertex colors, normals, and transparency for sticks, spheres, cartoons, and surfaces.

  • save file.glb / cmd.get_glb() (returns bytes) and save file.gltf / cmd.get_gltf(filename) (self-contained, base64-embedded buffer).
  • The scene is oriented like the current view and centered on the origin of rotation. geometry_export_mode=1 keeps model space coordinates, matching the COLLADA/OBJ/VRML/IDTF exporters.
  • Native export is opt-in at build time with --json=true and requires nlohmann-json. Without it, .gltf export falls back to collada2gltf as before, and .glb raises a clear error.
  • Adjacent triangles share vertices (exact match on position, normal and color), so surfaces and cartoons have 5-6x fewer vertices than triangle soup (e.g. a 1rx1 surface GLB is 0.6 MB instead of 2.3 MB).
  • Text labels and ellipsoids are skipped with a warning in this first pass.

Testing

  • Coverage for GLB containers, self-contained glTF, representations, colors, normals, transparency, empty scenes, triangle winding vs. normals, and view orientation / geometry_export_mode.
  • Verified the collada2gltf fallback with the native exporter disabled.
  • Imported exports into Blender 5.2.2 (glTF importer reports no issues, 0 inverted triangles) and compared Cycles renders against PyMOL ray traces from the same camera.
  • Verified builds with and without --json=true.

🤖 Generated with Claude Code

JarrettSJohnson and others added 11 commits July 24, 2026 15:55
- Cylinder/cone shafts were wound clockwise relative to their outward
  normals, so viewers that flip back-face normals on double sided
  materials (e.g. three.js) shaded sticks, lines and mesh dark.
- Tilt cone shaft normals by the taper and use r2 for the round nub at
  the cone's second end.
- Orient the exported scene like the current view, centered on the
  origin of rotation, and honor geometry_export_mode=1 (keep model
  space coordinates), consistent with the COLLADA/OBJ/VRML/IDTF
  exporters.
- cmd.get_glb() now returns bytes, like get_collada/get_vrml, and save
  writes them.
- cmd.get_gltf falls back to collada2gltf when PyMOL is built without
  --json=true, so .gltf export does not regress for those builds.
- Tests for triangle winding and view orientation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ray triangle primitives each carry their own copy of the corner
vertices, so surfaces and cartoons were exported as triangle soup. Reuse
vertices whose position, normal, and color match exactly, which recovers
the mesh connectivity (corners are copied from the same representation
data) and skip triangles that collapse to fewer than three vertices.

Surfaces and cartoons have 5-6x fewer vertices, e.g. the 1rx1 surface
GLB shrinks from 2.3 MB to 0.6 MB with identical rendering.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f-glb

# Conflicts:
#	testing/tests/api/test_exporting.py
get_gltf writes the file itself, so it bypassed the atomic write that
save gained in #521 and a failed write could still truncate an existing
.gltf file. Use exporting._write_file_atomic, and cover glb/gltf in the
save failure test (requires_capability now returns a pytest mark, so it
also works in pytest.param).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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