mc3togltf Converter
Standalone CLI tool: converts .mc3.xml to glTF 2.0 JSON or self-contained GLB.
Purpose
mc3togltf is a standalone command-line binary — separate from the editor — that takes an MC3 XML scene as input and writes a glTF 2.0 file (JSON + external .bin) or a GLB (self-contained binary). It is required for the editor's File → Export GLB command (Ctrl+E).
Usage
# Export to GLB (binary, self-contained)
./cmake-build-debug/mc3togltf/mc3togltf test/house.mc3.xml /tmp/house.glb
# Export to glTF JSON (+ external .bin)
./cmake-build-debug/mc3togltf/mc3togltf test/house.mc3.xml /tmp/house.gltf
# Allow approximate CSG export (children as separate meshes)
./cmake-build-debug/mc3togltf/mc3togltf --allow-approximate-csg scene.mc3.xml out.glb
Building
mc3togltf is included in the top-level build and builds automatically with ninja -C cmake-build-debug. The binary lands at cmake-build-debug/mc3togltf/mc3togltf.
The converter has no dependency on CNA, ImGui, or any graphics library — only the core mc3 library and tinyxml2.
Export Support Matrix
| Feature | Exported | Notes |
|---|---|---|
| Box, Cube | ✅ | |
| Sphere | ✅ | |
| Cylinder, Cone | ✅ | |
| Plane | ✅ | size is vec2 (W × D) |
| Torus, Capsule, Disk | ✅ | |
| Grid, Ico-sphere | ✅ | |
| Extrude (all path types) | ✅ | |
Mesh (src= OBJ) | ✅ | OBJ loaded at export time |
| Materials (PBR, textures) | ✅ | |
| Lights, Cameras | ✅ | |
| Instances (definitions) | ✅ | Expanded to meshes at export |
| Animation: position/rotation/scale | ✅ | Exported as glTF animations[] |
| Animation: visible, deform.*, material.* | ❌ | No glTF equivalent; silently skipped |
| CSG (union/difference/intersection) | ⚠️ | Hard fail by default; use --allow-approximate-csg to export children as separate meshes |
Key Source Files
| File | Role |
|---|---|
src/main.cpp | CLI entry point: parse args, call Mc3Document::loadFromFile(), call GltfExporter, write output. |
src/GltfExporter.hpp/.cpp | Converts an MC3 document to glTF JSON or GLB. Handles geometry, materials, textures, and animations. |
src/MeshBuilder.hpp/.cpp | Tessellates MC3 objects (primitives, extrusions, groups) into triangle meshes for glTF accessors. |
src/MathUtils.hpp | Inline math: Euler → quaternion, matrix operations. |
test/gltf_test.py | Python test suite: 39 assertions on the output glTF/GLB JSON. |
Export Pipeline
.mc3.xml
│
▼ Mc3Document::loadFromFile() (shared core mc3 library)
MC3 Document (in-memory)
│
▼ GltfExporter::exportDocument()
│
├── For each object: MeshBuilder → triangulated geometry
│ → glTF mesh / primitive / accessor / bufferView
│
├── For each material → glTF material (PBR metallic-roughness)
│
├── For each texture → glTF image + sampler + texture
│
├── For each Mc3Action → glTF animation
│ channels: position (VEC3), rotation (VEC4 quaternion), scale (VEC3)
│ cubic bezier → sampled at 30 fps → LINEAR glTF interpolation
│
└── Write JSON header + binary buffer
.gltf → JSON file + separate .bin
.glb → single binary envelope (JSON chunk + BIN chunk)
Animation Export Notes
- Position, rotation, and scale channels are exported as glTF
animations[]. - Individual per-component MC3 channels (e.g.,
position.yonly) are merged into VEC3/VEC4 at export time; non-animated components fall back to the object's base transform value. - Cubic Bézier channels are densely sampled at 30 fps and exported as
LINEARglTF interpolation (glTF has no native cubic Bézier). - The
visible,deform.*, andmaterial.*properties have no glTF equivalent and are silently skipped during export.
Test Suite
mc3togltf/test/gltf_test.py contains 39 Python assertions. Registered as a CTest test (top-level build includes mc3togltf):
# Run via CTest (from the main cmake-build-debug)
ctest --test-dir cmake-build-debug -V -R mc3togltf
# Run directly
python3 mc3togltf/test/gltf_test.py \
cmake-build-debug/mc3togltf/mc3togltf \
test/animation_test.mc3.xml \
test/house.mc3.xml
Known Limitations
- CSG boolean geometry is not evaluated during export (Manifold not linked). By default, any CSG node causes an error. Pass
--allow-approximate-csgto export child primitives as separate meshes instead (geometrically incorrect). - UV mapping overrides from
<uv_mapping>are not yet applied during mesh tessellation. visible,deform.*, andmaterial.*animation channels are silently skipped — no glTF equivalent.