ArmorPaint Import/Export Pipeline for GLTF and FBX Files: Technical Architecture Guide
ArmorPaint processes 3D assets through a modular plugin system that uses cgltf for GLTF/GLB files and ufbx for FBX files, converting all mesh data into a unified internal format before export.
The ArmorPaint import/export pipeline enables seamless interchange of 3D models through format-specific plugins that normalize external data into the engine’s native representation. According to the armory3d/armorpaint source code, the implementation separates parsing logic from UI interaction, allowing developers to import GLTF and FBX files either programmatically or through the visual interface.
How ArmorPaint Imports GLTF and GLB Files
The cgltf Parser Implementation
ArmorPaint handles GLTF and GLB imports through the io_gltf plugin, which wraps the cgltf library—a single-file C99 parser. The core parsing logic resides in paint/plugins/io_gltf/cgltf.c with definitions in paint/plugins/io_gltf/cgltf.h. This implementation processes both JSON-based .gltf descriptors and binary .glb containers, extracting geometry, materials, and scene hierarchies.
Converting GLTF Data to Internal Format
After parsing, the io_gltf_parse_mesh function transforms raw vertex data into ArmorPaint’s internal 16-bit format. This conversion pipeline performs critical coordinate system adjustments, specifically axis-swaps between Y-up and Z-up orientations, applies uniform mesh scaling, and recomputes normal vectors when the source file lacks them. The resulting data populates the raw_mesh_t structure used throughout the rendering engine.
FBX Import Pipeline in ArmorPaint
The ufbx Library Integration
For FBX interchange, ArmorPaint employs the io_fbx plugin backed by the ufbx library—a fast, header-only FBX parser. The library interface is defined in paint/plugins/io_fbx/ufbx/ufbx.h, which declares structures for meshes, nodes, and transforms. Unlike heavier SDK dependencies, ufbx provides lightweight access to FBX geometry without external Autodesk requirements.
Mesh Extraction and Normalization
The io_fbx_parse_mesh function in paint/plugins/io_fbx/io_fbx.c traverses the FBX node hierarchy to extract geometry data. Despite FBX’s complex transform inheritance and custom property systems, the importer flattens this into the same raw_mesh_t structure used by the GLTF pipeline. This normalization ensures that both formats ultimately produce identical internal mesh representations regardless of their original encoding differences.
Plugin Registration and UI Integration
Registering Importers in plugins.c
Both import modules register automatically in paint/plugins/plugins.c. The build system includes format-specific sources using project.add_cfiles("io_gltf/**") and project.add_cfiles("io_fbx/**"), then maps file extensions (.gltf, .glb, .fbx) to their respective loader functions. This registration mechanism allows the engine to dispatch files to the correct parser without hardcoding format logic into the core executable.
File Extension Dispatch in box_import_mesh.c
The user-facing import dialog lives in paint/sources/ui/box_import_mesh.c. When a user selects a file, the code checks the extension and routes the path to io_gltf_parse or io_fbx_parse accordingly. This abstraction layer separates the UI from parsing implementation, enabling support for additional formats through plugin additions rather than core engine modifications.
Exporting Meshes and Textures
The box_export.c Pipeline
Export functionality centers on paint/sources/ui/box_export.c, which handles the ArmorPaint export pipeline for textures and meshes. The system takes the internal raw_mesh_t representation and writes it to disk, applying optional processing steps including padding expansion, vertex merging for optimization, and material baking. The box_export_tab_export_textures_run function triggers the actual write operation, utilizing settings stored in the global context such as output path and mesh optimization flags.
Working with the Pipeline Programmatically
You can bypass the UI and import files directly using the plugin APIs:
// Import GLTF/GLB programmatically
size_t size;
char *buf = sys_file_read_bytes("model.glb", &size);
void *gltf_data = io_gltf_parse(buf, size);
raw_mesh_t *mesh = (raw_mesh_t *)gltf_data;
// Import FBX programmatically
size_t size;
char *buf = sys_file_read_bytes("character.fbx", &size);
void *fbx_data = io_fbx_parse(buf, size);
raw_mesh_t *mesh = (raw_mesh_t *)fbx_data;
For export operations, trigger the pipeline directly:
// Export with current settings
box_export_tab_export_textures_run(NULL);
// Writes mesh using context settings (padding, vertex merge, material bake)
Summary
- Modular Architecture: The pipeline separates parsing (cgltf/ufbx), conversion (to
raw_mesh_t), and UI layers (box_import_mesh.c/box_export.c). - Unified Internal Format: Both GLTF and FBX importers normalize data into a 16-bit internal mesh structure with Y-up/Z-up axis correction.
- Plugin Registration: Import functions register in
paint/plugins/plugins.cvia extension-to-function mapping. - Export Flexibility: The export system supports texture baking, vertex merging, and configurable padding through
box_export.c. - Programmatic Access: Developers can import files directly via
io_gltf_parseandio_fbx_parsewithout UI interaction.
Frequently Asked Questions
What libraries does ArmorPaint use for parsing GLTF and FBX files?
ArmorPaint uses cgltf for GLTF and GLB parsing—a single-file C99 library located in paint/plugins/io_gltf/cgltf.c. For FBX files, it integrates ufbx, a header-only C library found in paint/plugins/io_fbx/ufbx/ufbx.h. Both libraries were chosen for their minimal dependencies and permissive licensing, allowing direct embedding into the ArmorPaint codebase without external SDK requirements.
How does ArmorPaint handle coordinate system differences between 3D formats?
The import pipeline automatically performs axis-swaps during the conversion to internal format. In io_gltf_parse_mesh, the code transforms Y-up coordinates (common in GLTF) to Z-up (ArmorPaint’s internal convention) or vice versa as needed. This normalization ensures that meshes from different source applications maintain correct orientation regardless of whether they originated as GLTF or FBX files.
Where is the import/export logic registered in the ArmorPaint codebase?
Format support registers in paint/plugins/plugins.c, where file extensions map to specific parser functions at build time. The UI integration resides in paint/sources/ui/box_import_mesh.c for imports and paint/sources/ui/box_export.c for exports. This separation allows the core engine to remain agnostic about specific 3D formats while the plugin layer handles format-specific parsing.
Can I import GLTF and FBX files programmatically without using the ArmorPaint UI?
Yes, both formats expose C APIs for programmatic import. Call io_gltf_parse() for GLTF/GLB files or io_fbx_parse() for FBX files, passing a memory buffer containing the file data. Both functions return a pointer to a raw_mesh_t structure ready for rendering. For export, invoke box_export_tab_export_textures_run() to trigger the export pipeline with settings stored in the global context.
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 →