# ArmorPaint Import/Export Pipeline for GLTF and FBX Files: Technical Architecture Guide

> Explore the ArmorPaint import export pipeline for GLTF and FBX files. Learn how ArmorPaint uses cgltf and ufbx to process 3D assets in its modular plugin system for seamless integration.

- Repository: [Armory 3D/armorpaint](https://github.com/armory3d/armorpaint)
- Tags: architecture
- Published: 2026-09-11

---

**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`](https://github.com/armory3d/armorpaint/blob/main/paint/plugins/io_gltf/cgltf.c) with definitions in [`paint/plugins/io_gltf/cgltf.h`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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:

```c
// 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;

```

```c
// 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:

```c
// 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.c`](https://github.com/armory3d/armorpaint/blob/main/paint/plugins/plugins.c) via extension-to-function mapping.
- **Export Flexibility**: The export system supports texture baking, vertex merging, and configurable padding through [`box_export.c`](https://github.com/armory3d/armorpaint/blob/main/box_export.c).
- **Programmatic Access**: Developers can import files directly via `io_gltf_parse` and `io_fbx_parse` without 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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/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`](https://github.com/armory3d/armorpaint/blob/main/paint/sources/ui/box_import_mesh.c) for imports and [`paint/sources/ui/box_export.c`](https://github.com/armory3d/armorpaint/blob/main/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.