The loader module provides classes for loading 3D models, textures, and other assets.
import io.materia.loader.*
Abstract base class for all loaders.
| 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 |
// 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
Loads glTF 2.0 and GLB files (industry standard format).
class GLTFLoader(manager: LoadingManager = DefaultLoadingManager)
// Load glTF/GLB file
fun load(
url: String,
onLoad: (GLTF) -> Unit,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
// Load with coroutines
suspend fun loadAsync(url: String): GLTF
// Parse from ArrayBuffer
fun parse(
data: ArrayBuffer,
path: String,
onLoad: (GLTF) -> Unit,
onError: ((Exception) -> Unit)? = null
)
// Register extension
fun register(callback: (GLTFParser) -> GLTFLoaderPlugin): GLTFLoader
// Unregister extension
fun unregister(callback: (GLTFParser) -> GLTFLoaderPlugin): GLTFLoader
// Set Draco decoder path
fun setDRACOLoader(dracoLoader: DRACOLoader): GLTFLoader
// Set KTX2 loader
fun setKTX2Loader(ktx2Loader: KTX2Loader): GLTFLoader
// Set mesh optimizer decoder
fun setMeshoptDecoder(decoder: MeshoptDecoder): GLTFLoader
data class GLTF(
val scene: Group, // Root scene
val scenes: List<Group>, // All scenes
val animations: List<AnimationClip>, // Animations
val cameras: List<Camera>, // Cameras
val asset: GLTFAsset, // Asset metadata
val parser: GLTFParser, // Parser instance
val userData: Map<String, Any> // Custom data
)
data class GLTFAsset(
val version: String,
val generator: String?,
val copyright: String?,
val minVersion: String?
)
val loader = GLTFLoader()
// Basic loading
loader.load("models/robot.glb") { gltf ->
scene.add(gltf.scene)
// Play animations
if (gltf.animations.isNotEmpty()) {
val mixer = AnimationMixer(gltf.scene)
val action = mixer.clipAction(gltf.animations[0])
action.play()
}
}
// With Draco compression
val dracoLoader = DRACOLoader()
dracoLoader.setDecoderPath("libs/draco/")
loader.setDRACOLoader(dracoLoader)
loader.load("models/compressed.glb") { gltf ->
scene.add(gltf.scene)
}
// With progress
loader.load(
url = "models/large.glb",
onLoad = { gltf -> scene.add(gltf.scene) },
onProgress = { event ->
val percent = (event.loaded / event.total) * 100
println("Loading: $percent%")
},
onError = { error ->
println("Error: ${error.message}")
}
)
Loads Wavefront OBJ files.
class OBJLoader(manager: LoadingManager = DefaultLoadingManager)
// 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
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)
}
}
Loads FBX files (ASCII format, static geometry only).
class FBXLoader(manager: LoadingManager = DefaultLoadingManager)
fun load(
url: String,
onLoad: (Group) -> Unit,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
fun parse(buffer: ArrayBuffer, path: String): Group
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()
}
}
Loads COLLADA (.dae) files.
class ColladaLoader(manager: LoadingManager = DefaultLoadingManager)
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
)
Loads PLY (Polygon File Format) files.
class PLYLoader(manager: LoadingManager = DefaultLoadingManager)
fun load(
url: String,
onLoad: (BufferGeometry) -> Unit,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
fun parse(data: ArrayBuffer): BufferGeometry
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)
}
Loads STL (Stereolithography) files.
class STLLoader(manager: LoadingManager = DefaultLoadingManager)
fun load(
url: String,
onLoad: (BufferGeometry) -> Unit,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
fun parse(data: ArrayBuffer): BufferGeometry
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)
}
Loads Draco-compressed geometry.
class DRACOLoader(manager: LoadingManager = DefaultLoadingManager)
// 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()
val dracoLoader = DRACOLoader()
dracoLoader.setDecoderPath("libs/draco/")
dracoLoader.setWorkerLimit(4)
dracoLoader.preload()
// Use with GLTFLoader
val gltfLoader = GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)
Loads image textures.
class TextureLoader(manager: LoadingManager = DefaultLoadingManager)
fun load(
url: String,
onLoad: ((Texture) -> Unit)? = null,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
): Texture
suspend fun loadAsync(url: String): Texture
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") }
Loads cube map textures (skyboxes, environment maps).
class CubeTextureLoader(manager: LoadingManager = DefaultLoadingManager)
fun load(
urls: Array<String>, // [px, nx, py, ny, pz, nz]
onLoad: ((CubeTexture) -> Unit)? = null,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
): CubeTexture
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
}
Low-level image loader that returns raw pixel data.
class ImageLoader(
resolver: AssetResolver = AssetResolver.default(),
manager: LoadingManager? = null
)
// 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)
data class ImageData(
val width: Int,
val height: Int,
val data: ByteArray // RGBA pixel data
)
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
Loads HDR cube textures for environment mapping.
class HDRCubeTextureLoader(
resolver: AssetResolver = AssetResolver.default(),
manager: LoadingManager? = null
)
// 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
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")
Loads KTX2 compressed textures.
class KTX2Loader(manager: LoadingManager = DefaultLoadingManager)
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()
val ktx2Loader = KTX2Loader()
ktx2Loader.setTranscoderPath("libs/basis/")
ktx2Loader.detectSupport(renderer)
ktx2Loader.load("textures/compressed.ktx2") { texture ->
material.map = texture
}
Loads OpenEXR HDR images.
class EXRLoader(manager: LoadingManager = DefaultLoadingManager)
fun setDataType(type: TextureDataType): EXRLoader
fun load(
url: String,
onLoad: ((DataTexture) -> Unit),
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
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
}
Loads Radiance HDR (.hdr) images.
class RGBELoader(manager: LoadingManager = DefaultLoadingManager)
fun setDataType(type: TextureDataType): RGBELoader
fun load(
url: String,
onLoad: ((DataTexture) -> Unit),
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
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()
}
Loads JSON font files for TextGeometry.
class FontLoader(manager: LoadingManager = DefaultLoadingManager)
fun load(
url: String,
onLoad: (Font) -> Unit,
onProgress: ((ProgressEvent) -> Unit)? = null,
onError: ((Exception) -> Unit)? = null
)
fun parse(json: JsonObject): Font
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)
}
Manages loading progress across multiple loaders.
class LoadingManager(
onLoad: (() -> Unit)? = null,
onProgress: ((url: String, loaded: Int, total: Int) -> Unit)? = null,
onError: ((url: String) -> Unit)? = null
)
| 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 |
// 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)
// 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
Low-level file loading.
class FileLoader(manager: LoadingManager = DefaultLoadingManager)
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