How to Integrate Custom Models Using Assimp in Equilibrium Engine
Call assimp_scene_load() from equilibrium/utils/assimp_utils.h with your model path and ECS world pointer to import GLTF, OBJ, or FBX files as renderable entities with automatic material generation.
The Equilibrium Engine provides a built-in Assimp import pipeline that converts standard 3D formats into engine-native Mesh components. By leveraging the utilities in equilibrium/utils/assimp_utils.h, you can load custom assets with automatic material and texture handling according to the clibequilibrium/equilibriumengine source code. This guide walks through the exact integration steps, file paths, and function signatures required to bring your own 3D assets into the engine.
Understanding the Assimp Import Pipeline
The import process centers on assimp_scene_load() defined in equilibrium/utils/assimp_utils.h. This function orchestrates the conversion from Assimp's scene graph to the engine's ECS entity hierarchy through five distinct phases:
- Property store creation: Initializes an Assimp property store and configures import flags to enforce triangle-only geometry and 16-bit index limits (lines 30-41).
- Scene import: Calls
aiImportFileExWithPropertiesand validates the returned pointer (lines 24-28). - Material processing: Iterates over
aiMaterialobjects and converts them to engineMaterialstructs viamaterial_load()(lines 61-112). - Mesh conversion: Transforms vertex data into packed
PosNormalTangentTexcoordVertexbuffers and creates BGFX resources throughgroup_load()(lines 13-98). - Entity instantiation: Creates ECS entities for each mesh, attaching
Meshcomponents and optionalMaterialcomponents when base-color textures are detected (lines 58-67).
Vertex Processing in group_load
The group_load() function packs interleaved vertex attributes (position, normal, tangent, UV) into the PosNormalTangentTexcoordVertex structure. It allocates BGFX vertex buffers using bgfx_create_vertex_buffer and constructs 16-bit index buffers via bgfx_create_index_buffer to match the engine's rendering constraints.
Material Processing in material_load
The material_load() function extracts GLTF PBR parameters including base-color, metallic/roughness, normal, occlusion, and emissive properties. It resolves texture paths relative to the model file's directory and loads them using load_texture() from equilibrium/utils/bgfx_utils.h.
Loading Your First Custom Model
To integrate a custom model, place your asset files in the repository and invoke the loader from a system.
First, place your model and associated textures in a directory such as assets/models/MyCharacter/character.gltf.
Next, modify the bootstrap system or create a custom loader. The reference implementation in launcher/sandbox/bootstrap_system.c (line 13) demonstrates the invocation pattern:
// launcher/sandbox/bootstrap_system.c
#include "utils/assimp_utils.h"
static void Bootstrap(ecs_iter_t *it) {
/* Load a custom GLTF model */
if (!assimp_scene_load("assets/models/MyCharacter/character.gltf", it->world)) {
ecs_err("Failed to load character model");
}
/* Additional scene setup (lights, camera) continues here */
}
The assimp_scene_load() function returns a boolean indicating success. Upon completion, the engine contains new ECS entities representing your model's hierarchy, each equipped with renderable components.
Customizing the Import Behavior
The default configuration enforces specific constraints optimized for the engine's rendering pipeline. You can modify these behaviors by editing equilibrium/utils/assimp_utils.h.
Modifying Import Flags
The loader configures Assimp's property store with aiSetImportPropertyInteger to enforce triangle-only geometry and 16-bit index limits. To change these constraints—for example, to enable explicit triangulation or UV flipping—adjust the flags variable passed to aiImportFileExWithProperties around lines 11-22:
// In assimp_scene_load() - modify the flags parameter
unsigned int flags = aiProcess_Triangulate |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace;
Extending Vertex Attributes
To support additional vertex data such as vertex colors or multiple UV sets, extend the PosNormalTangentTexcoordVertex struct and modify group_load() to copy the new data. You must also update the BGFX vertex layout using bgfx_vertex_layout_add() to describe the new attribute offsets and types.
Custom Texture Search Paths
By default, material_load() constructs texture paths by concatenating the model's directory (dir) with texture filenames. If your pipeline stores textures in a separate location, modify the path construction logic in material_load() (lines 88-110) to prepend your asset root or implement a custom resolution scheme.
Key Source Files and Functions
| File | Purpose | Key Functions |
|---|---|---|
equilibrium/utils/assimp_utils.h |
Core import implementation | assimp_scene_load(), material_load(), group_load() |
launcher/sandbox/bootstrap_system.c |
Example integration point | Bootstrap() system demonstrating loader invocation |
cmake/assimp-config.cmake |
Build configuration | Assimp include directories and library linking |
equilibrium/utils/bgfx_utils.h |
Texture loading utilities | load_texture() for BGFX texture handle creation |
Summary
- Use
assimp_scene_load()fromequilibrium/utils/assimp_utils.hto import GLTF, OBJ, FBX, and other Assimp-supported formats. - The loader automatically creates ECS entities with Mesh and Material components backed by BGFX GPU buffers using 16-bit indices.
- Modify
assimp_scene_load()to change import flags for triangulation, UV flipping, or coordinate system conversion. - Customize
group_load()andPosNormalTangentTexcoordVertexto support additional vertex attributes beyond the default position/normal/tangent/UV layout. - The CMake configuration in
cmake/assimp-config.cmakehandles all third-party linking requirements; no additional build setup is required.
Frequently Asked Questions
Does Equilibrium Engine support FBX and OBJ files, or only GLTF?
Yes. Because the integration uses the Assimp library, it supports any format Assimp can parse, including FBX, OBJ, Collada, and glTF. Simply provide the correct file extension in the path argument to assimp_scene_load(); no code changes are required to support different formats.
How are textures loaded when importing a model?
The material_load() function extracts texture filenames from the aiMaterial and resolves them relative to the model file's directory using the dir variable. It then calls load_texture() to create BGFX texture handles. If textures reside in a different directory structure, modify the path concatenation logic in material_load() around lines 88-110 of assimp_utils.h.
What entity hierarchy is created for imported models?
For each mesh in the Assimp scene, assimp_scene_load() creates a distinct ECS entity with a Mesh component containing the geometry groups. If the mesh references a material with textures, a Material component is also attached. The function preserves the scene's transform hierarchy, creating parent-child relationships between entities as defined in the source file.
Why does the loader enforce 16-bit indices and triangle-only geometry?
The engine uses 16-bit index buffers for memory efficiency and compatibility with mobile GPU architectures. The aiSetImportPropertyInteger calls in assimp_scene_load() configure Assimp to split meshes exceeding 65535 vertices and to reject non-triangle primitives. These constraints ensure the resulting geometry can be rendered directly by the engine's BGFX-based pipeline without runtime conversion.
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 →