Loader API ReferenceThe loader module provides classes for loading 3D models, textures, and other assets.

Loader API Reference

The loader module provides classes for loading 3D models, textures, and other assets.

Overview

import io.materia.loader.*

Loader (Base Class)

Abstract base class for all loaders.

Properties

Property Type Description
manager LoadingManager Loading manager
crossOrigin String CORS setting
withCredentials Boolean Include credentials
path String Base path for assets
resourcePath String Resource path
requestHeader Map<String, String> HTTP headers

Methods

// Set base path
fun setPath(path: String): Loader

// Set resource path
fun setResourcePath(path: String): Loader

// Set cross-origin
fun setCrossOrigin(crossOrigin: String): Loader

// Set request headers
fun setRequestHeader(headers: Map<String, String>): Loader

GLTFLoader

Loads glTF 2.0 JSON files and GLB 2.0 binary containers into Materia scene objects.

Constructor

class GLTFLoader(
    resolver: AssetResolver = AssetResolver.default(),
    json: Json = Json { ignoreUnknownKeys = true; isLenient = true },
    cache: GLTFAssetCache? = GLTFAssetCache.shared,
    cacheScope: String? = resolver.cacheKeyScope
)

By default, loaders using the platform default AssetResolver share GLTFAssetCache.shared. Repeated loads for the same normalized URL reuse completed and in-flight source assets, then return an independent instance to the caller. Custom resolvers are isolated by default unless a shared cacheScope is supplied.

Methods

suspend fun load(
    url: String,
    progress: ((LoadingProgress) -> Unit)? = null
): GLTFAsset

suspend fun load(
    url: String,
    onLoad: (GLTFAsset) -> Unit,
    onProgress: ((LoadingProgress) -> Unit)? = null,
    onError: ((Throwable) -> Unit)? = null
)

GLTFAsset

data class GLTFAsset(
    val scene: Scene,
    val scenes: List<Scene>,
    val nodes: List<Object3D>,
    val materials: List<Material>,
    val animations: List<AnimationClip>
) {
    fun instantiate(): GLTFAsset
}

instantiate() creates a new scene graph with independent object transforms and parent/child relationships. Geometry, materials, textures, and animations are shared intentionally so renderers can reuse CPU and GPU resources for repeated model instances.

GLTFAssetCache

class GLTFAssetCache {
    suspend fun getOrLoad(scope: String, url: String, load: suspend () -> GLTFAsset): GLTFAsset
    suspend fun remove(scope: String, url: String)
    suspend fun clear()

    companion object {
        val shared: GLTFAssetCache
    }
}

Use a custom cache for bounded lifetimes such as level loads, tests, or editor previews:

val cache = GLTFAssetCache()
val loader = GLTFLoader(cache = cache, cacheScope = "warehouse-level")

val crateA = loader.load("models/crate.glb")
val crateB = loader.load("models/crate.glb")

scene.add(crateA.scene)
scene.add(crateB.scene)

// Safe: object transforms are not shared between instances.
crateA.scene.position.x = -2f
crateB.scene.position.x = 2f

// Optional cleanup when the scope is no longer useful.
cache.clear()

Progress

data class LoadingProgress(
    val loaded: Long,
    val total: Long
) {
    val percentage: Float
}

Progress currently reports dependent buffer byte loading. Cached source hits may not replay the original progress sequence because no new network/decode work is performed.

Format Notes

  • .gltf JSON documents are supported with embedded data URIs and external buffers.
  • .glb binary containers are supported for glTF 2.0 JSON plus embedded binary buffer chunks.
  • Repeated same-URL .gltf and .glb loads share source asset work when cache scope and URL match.

OBJLoader

Loads Wavefront OBJ files.

Constructor

class OBJLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

// Load OBJ file
fun load(
    url: String,
    onLoad: (Group) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

// Set materials
fun setMaterials(materials: MTLLoader.MaterialCreator): OBJLoader

// Parse OBJ string
fun parse(text: String): Group

Example

val mtlLoader = MTLLoader()
val objLoader = OBJLoader()

// Load with materials
mtlLoader.load("models/model.mtl") { materials ->
    materials.preload()
    objLoader.setMaterials(materials)
    
    objLoader.load("models/model.obj") { obj ->
        scene.add(obj)
    }
}

FBXLoader

Loads FBX files (ASCII format, static geometry only).

Constructor

class FBXLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: (Group) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

fun parse(buffer: ArrayBuffer, path: String): Group

Example

val loader = FBXLoader()

loader.load("models/character.fbx") { fbx ->
    fbx.scale.setScalar(0.01f)  // FBX often uses cm
    scene.add(fbx)
    
    // Animations
    if (fbx.animations.isNotEmpty()) {
        val mixer = AnimationMixer(fbx)
        mixer.clipAction(fbx.animations[0]).play()
    }
}

ColladaLoader

Loads COLLADA (.dae) files.

Constructor

class ColladaLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: (Collada) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

data class Collada(
    val scene: Group,
    val animations: List<AnimationClip>,
    val kinematics: Any?,
    val library: ColladaLibrary
)

PLYLoader

Loads PLY (Polygon File Format) files.

Constructor

class PLYLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: (BufferGeometry) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

fun parse(data: ArrayBuffer): BufferGeometry

Example

val loader = PLYLoader()

loader.load("models/scan.ply") { geometry ->
    geometry.computeVertexNormals()
    
    val material = MeshStandardMaterial().apply {
        vertexColors = true
    }
    val mesh = Mesh(geometry, material)
    scene.add(mesh)
}

STLLoader

Loads STL (Stereolithography) files.

Constructor

class STLLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: (BufferGeometry) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

fun parse(data: ArrayBuffer): BufferGeometry

Example

val loader = STLLoader()

loader.load("models/part.stl") { geometry ->
    val material = MeshPhongMaterial().apply {
        color = Color(0x888888)
        specular = Color(0x111111)
        shininess = 200f
    }
    val mesh = Mesh(geometry, material)
    mesh.rotation.x = -PI / 2  // STL often Z-up
    scene.add(mesh)
}

DRACOLoader

Loads Draco-compressed geometry.

Constructor

class DRACOLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

// Set decoder path
fun setDecoderPath(path: String): DRACOLoader

// Set decoder config
fun setDecoderConfig(config: DracoDecoderConfig): DRACOLoader

// Enable/disable worker
fun setWorkerLimit(limit: Int): DRACOLoader

// Preload decoder
fun preload(): DRACOLoader

// Load compressed file
fun load(
    url: String,
    onLoad: (BufferGeometry) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

// Dispose workers
fun dispose()

Example

val dracoLoader = DRACOLoader()
dracoLoader.setDecoderPath("libs/draco/")
dracoLoader.setWorkerLimit(4)
dracoLoader.preload()

// Use with GLTFLoader
val gltfLoader = GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)

TextureLoader

Loads image textures.

Constructor

class TextureLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: ((Texture) -> Unit)? = null,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
): Texture

suspend fun loadAsync(url: String): Texture

Example

val loader = TextureLoader()

// Sync (texture updates when loaded)
val texture = loader.load("textures/wood.jpg")
material.map = texture

// With callback
loader.load("textures/wood.jpg") { texture ->
    texture.wrapS = TextureWrapping.REPEAT
    texture.wrapT = TextureWrapping.REPEAT
    texture.repeat.set(4f, 4f)
    material.map = texture
    material.needsUpdate = true
}

// Load multiple
val textures = listOf(
    "albedo.jpg",
    "normal.jpg",
    "roughness.jpg"
).map { loader.load("textures/pbr/$it") }

CubeTextureLoader

Loads cube map textures (skyboxes, environment maps).

Constructor

class CubeTextureLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    urls: Array<String>,  // [px, nx, py, ny, pz, nz]
    onLoad: ((CubeTexture) -> Unit)? = null,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
): CubeTexture

Example

val loader = CubeTextureLoader()

// Load skybox
val cubeTexture = loader.load(arrayOf(
    "textures/sky/px.jpg",
    "textures/sky/nx.jpg",
    "textures/sky/py.jpg",
    "textures/sky/ny.jpg",
    "textures/sky/pz.jpg",
    "textures/sky/nz.jpg"
)) { texture ->
    scene.background = texture
    scene.environment = texture  // For reflections
}

ImageLoader

Low-level image loader that returns raw pixel data.

Constructor

class ImageLoader(
    resolver: AssetResolver = AssetResolver.default(),
    manager: LoadingManager? = null
)

Methods

// Load image data
suspend fun load(path: String): ImageData
suspend fun load(path: String, onProgress: ((LoadingProgress) -> Unit)?): ImageData

// Cache management
fun clearCache()
fun uncache(path: String)

ImageData Class

data class ImageData(
    val width: Int,
    val height: Int,
    val data: ByteArray  // RGBA pixel data
)

Example

val loader = ImageLoader()
val image = loader.load("textures/sprite.png")
println("Loaded ${image.width}x${image.height} image")

// Use for custom processing
val pixels = image.data

HDRCubeTextureLoader

Loads HDR cube textures for environment mapping.

Constructor

class HDRCubeTextureLoader(
    resolver: AssetResolver = AssetResolver.default(),
    manager: LoadingManager? = null
)

Methods

// Load from 6 face images
suspend fun load(
    paths: Array<String>,  // [+X, -X, +Y, -Y, +Z, -Z]
    onProgress: ((Int, Int) -> Unit)? = null
): CubeTexture

// Load from equirectangular HDR
suspend fun loadEquirectangular(
    path: String,
    faceSize: Int = 512
): CubeTexture

Example

val loader = HDRCubeTextureLoader()

// Load from 6 HDR faces
val envMap = loader.load(arrayOf(
    "px.hdr", "nx.hdr",
    "py.hdr", "ny.hdr",
    "pz.hdr", "nz.hdr"
))
scene.environment = envMap

// Or from equirectangular panorama
val envMap2 = loader.loadEquirectangular("studio.hdr")

KTX2Loader

Loads KTX2 compressed textures.

Constructor

class KTX2Loader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun setTranscoderPath(path: String): KTX2Loader
fun setWorkerLimit(limit: Int): KTX2Loader
fun detectSupport(renderer: Renderer): KTX2Loader

fun load(
    url: String,
    onLoad: ((CompressedTexture) -> Unit),
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

fun dispose()

Example

val ktx2Loader = KTX2Loader()
ktx2Loader.setTranscoderPath("libs/basis/")
ktx2Loader.detectSupport(renderer)

ktx2Loader.load("textures/compressed.ktx2") { texture ->
    material.map = texture
}

EXRLoader

Loads OpenEXR HDR images.

Constructor

class EXRLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun setDataType(type: TextureDataType): EXRLoader

fun load(
    url: String,
    onLoad: ((DataTexture) -> Unit),
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

Example

val loader = EXRLoader()
loader.setDataType(TextureDataType.HALF_FLOAT)

loader.load("textures/environment.exr") { texture ->
    texture.mapping = TextureMapping.EQUIRECTANGULAR_REFLECTION
    scene.environment = texture
    scene.background = texture
}

RGBELoader

Loads Radiance HDR (.hdr) images.

Constructor

class RGBELoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun setDataType(type: TextureDataType): RGBELoader

fun load(
    url: String,
    onLoad: ((DataTexture) -> Unit),
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

Example

val loader = RGBELoader()

loader.load("textures/environment.hdr") { texture ->
    texture.mapping = TextureMapping.EQUIRECTANGULAR_REFLECTION
    scene.environment = texture
    
    // Convert to cube map for better performance
    val pmremGenerator = PMREMGenerator(renderer)
    val envMap = pmremGenerator.fromEquirectangular(texture).texture
    scene.environment = envMap
    texture.dispose()
    pmremGenerator.dispose()
}

FontLoader

Loads JSON font files for TextGeometry.

Constructor

class FontLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: (Font) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

fun parse(json: JsonObject): Font

Example

val loader = FontLoader()

loader.load("fonts/helvetiker_regular.typeface.json") { font ->
    val geometry = TextGeometry("Hello", TextGeometryOptions(
        font = font,
        size = 1f,
        height = 0.2f
    ))
    
    val mesh = Mesh(geometry, material)
    scene.add(mesh)
}

LoadingManager

Manages loading progress across multiple loaders.

Constructor

class LoadingManager(
    onLoad: (() -> Unit)? = null,
    onProgress: ((url: String, loaded: Int, total: Int) -> Unit)? = null,
    onError: ((url: String) -> Unit)? = null
)

Properties

Property Type Description
onStart ((url: String, loaded: Int, total: Int) -> Unit)? Start callback
onLoad (() -> Unit)? All loaded callback
onProgress ((url: String, loaded: Int, total: Int) -> Unit)? Progress callback
onError ((url: String) -> Unit)? Error callback

Methods

// Get/set URL modifier
fun setURLModifier(callback: ((url: String) -> String)?): LoadingManager

// Add/remove handlers
fun addHandler(regex: Regex, loader: Loader): LoadingManager
fun removeHandler(regex: Regex): LoadingManager

// Get handler for URL
fun getHandler(file: String): Loader?

// Resolve URL
fun resolveURL(url: String): String

// Item tracking
fun itemStart(url: String)
fun itemEnd(url: String)
fun itemError(url: String)

Example

// Create manager with callbacks
val manager = LoadingManager(
    onLoad = {
        println("All assets loaded!")
        hideLoadingScreen()
    },
    onProgress = { url, loaded, total ->
        val progress = loaded.toFloat() / total * 100
        updateLoadingBar(progress)
    },
    onError = { url ->
        println("Error loading: $url")
    }
)

// Use with loaders
val gltfLoader = GLTFLoader(manager)
val textureLoader = TextureLoader(manager)

// Load assets
gltfLoader.load("models/scene.glb") { /* ... */ }
textureLoader.load("textures/diffuse.jpg") { /* ... */ }
textureLoader.load("textures/normal.jpg") { /* ... */ }
// onLoad fires when all three complete

FileLoader

Low-level file loading.

Constructor

class FileLoader(manager: LoadingManager = DefaultLoadingManager)

Methods

fun load(
    url: String,
    onLoad: (String) -> Unit,
    onProgress: ((ProgressEvent) -> Unit)? = null,
    onError: ((Exception) -> Unit)? = null
)

fun setResponseType(type: String): FileLoader  // "text", "arraybuffer", "blob", "json"
fun setMimeType(mimeType: String): FileLoader

See Also

Architected in Kotlin. Rendered with Materia. Powered by Aether.
© 2026 Yousef.