How the Modly Export Endpoint Converts Between GLB, STL, and OBJ Formats
Modly's export endpoint uses a dedicated mesh-exporter processor that parses GLB input via @gltf-transform, extracts raw vertex geometry, and serializes it into binary STL or ASCII OBJ formats using deterministic, format-specific writers.
The lightningpixel/modly repository handles 3D model interoperability through a workflow-based export pipeline. When you configure an export node in Modly, the system invokes a specialized processor that accepts GLB files—the internal standard—and transforms them into production-ready formats through a multi-stage conversion process.
Architecture of the Mesh-Exporter Processor
The conversion logic resides in src/areas/workflows/nodes/mesh-exporter/processor.ts, which implements Modly’s process extension interface. This design isolates format conversion from the core application, allowing the exporter to operate as a discrete node within visual workflows.
Parameter Handling and Format Mapping
When the processor executes, it receives a configuration object containing export_format (accepting glb, stl, obj, or ply) and an optional output_path. The extension maps these values to file extensions using a static EXT_MAP lookup table defined around lines 77–82, then creates a dedicated output directory if one is not provided.
GLB Loading and Geometry Extraction
The processor loads the source GLB using @gltf-transform’s NodeIO class, which fully resolves the GLTF document structure into accessible meshes and primitives. For non-GLB targets, the code extracts raw geometry via the extractPrimitives helper:
const prims = extractPrimitives(doc);
This helper iterates over every mesh and primitive in the document, gathering POSITION attributes along with optional NORMAL and TEXCOORD_0 arrays to build PrimGeometry objects. This normalization step ensures consistent data structures regardless of the input GLB’s internal complexity.
Format-Specific Serialization Logic
Once geometry is extracted, the processor branches into format-specific writers that handle byte-level serialization for binary formats and structured text generation for ASCII formats.
GLB Pass-Through Export
When the target format is GLB, the processor delegates entirely to the library’s native capabilities. The document is written directly using io.write without geometry manipulation, preserving the original structure and extensions.
Binary STL Generation
For STL output, the processor constructs a binary buffer sized precisely to the mesh topology. The implementation calculates total triangles and allocates a buffer of 84 + totalTri * 50 bytes. The serialization process follows the STL binary specification:
- Writes an 80-byte header (reserved, typically empty)
- Appends a 4-byte unsigned integer indicating the triangle count
- For each triangle:
- Computes a normal vector using
faceNormalif the primitive lacks explicit normals - Writes three 32-bit floating-point values for the normal
- Writes nine 32-bit floating-point values for the three vertex coordinates
- Appends a 2-byte attribute count (usually zero)
- Computes a normal vector using
The completed buffer is persisted using fs.writeFileSync.
ASCII OBJ Generation
For OBJ export, the processor emits a human-readable text file with structured vertex and face definitions. The writer tracks index offsets across multiple meshes using vOff, vnOff, and vtOff counters to ensure correct face indexing:
- Vertex data: Emits
vlines for positions,vnfor normals (if available), andvtfor UV coordinates (if present) - Face definitions: Generates
flines that reference vertices by index, properly offset to account for preceding mesh data - File encoding: Concatenates all lines and writes UTF-8 output to the destination path
This approach preserves mesh separation while creating a valid, parseable OBJ file compatible with most 3D software.
Workflow Integration and Usage
The mesh-exporter operates as a first-class citizen in Modly’s workflow engine, reporting progress via context.progress() and logging actions through context.log(). Upon completion, the processor returns the absolute path of the generated file, enabling downstream nodes to reference the asset immediately.
You can invoke the processor programmatically:
import processor from './src/areas/workflows/nodes/mesh-exporter/processor';
await processor(
{ filePath: '/tmp/model.glb' },
{ export_format: 'stl', output_path: '/tmp/exports' },
{
workspaceDir: '/my/workspace',
tempDir: '/my/temp',
log: console.log,
progress: (pct, label) => console.log(`${pct}% – ${label}`)
}
);
When configured through the UI, add a Mesh Exporter node to your workflow, set the Export Format parameter to your desired format, and connect an input mesh. The node automatically generates timestamped files (e.g., export-1700123456789.stl) in the workspace’s Exports folder.
Summary
- Modly’s export endpoint is implemented as a process extension in
processor.tsthat converts internal GLB files to STL, OBJ, or other supported formats. - GLB parsing relies on @gltf-transform’s
NodeIOto resolve document structures before extracting raw primitive data viaextractPrimitives. - STL output uses a custom binary writer that allocates
84 + (triangleCount * 50)bytes, writes an 80-byte header, and serializes triangles with computed face normals. - OBJ output generates ASCII text with indexed face definitions, tracking vertex offsets across multiple meshes to maintain valid references.
- Integration supports both programmatic invocation and visual workflow configuration, returning absolute file paths for downstream processing.
Frequently Asked Questions
Does the Modly export endpoint support both binary and ASCII STL formats?
According to the source code in processor.ts, Modly currently implements binary STL only. The writer explicitly allocates binary buffers and writes the 80-byte header and 4-byte triangle count required by the binary specification. ASCII STL output is not implemented in the current version.
How does Modly handle missing normal vectors when exporting to STL?
If the source GLB lacks normal data for a primitive, the processor calculates surface normals dynamically using the faceNormal function during serialization. Each triangle in the binary STL output requires a normal vector, so the system computes this geometrically from the vertex positions if not explicitly provided in the source mesh.
Can the export endpoint convert multiple meshes into a single OBJ file?
Yes. The extractPrimitives helper aggregates geometry from all meshes in the GLB document, and the OBJ writer manages global index offsets (vOff, vnOff, vtOff) to ensure that face definitions reference the correct vertices across concatenated mesh data. The resulting OBJ file contains all geometry while maintaining proper index references.
What dependencies power the GLB parsing in Modly’s export pipeline?
The conversion relies on @gltf-transform/core and @gltf-transform/extensions, as declared in the project’s dependencies. The processor specifically uses the NodeIO class from this library to read GLB files and access their internal mesh structures, primitives, and vertex attributes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →