Additional Format Loaders
This page documents the various 3D asset format loaders available in Three.js beyond GLTF. These loaders enable importing models, scenes, and point clouds from legacy and specialized formats. For GLTF import/export (the recommended modern format), see GLTF Import & Export.
The additional format loaders are located in examples/jsm/loaders/ and support a wide range of formats from animation-capable scene formats (FBX, Collada) to simple mesh formats (OBJ, STL) to point cloud data (PCD, PLY, VTK).
Format Categories and Capabilities
Three.js supports loaders across several format categories, each with different capabilities:
| Format | Loader Class | Geometry | Materials | Textures | Animations | Lights/Cameras | Notes |
|---|---|---|---|---|---|---|---|
| FBX | FBXLoader | ✓ | ✓ | ✓ | ✓ | ✓ | Full scene format, industry standard |
| Collada (.dae) | ColladaLoader | ✓ | ✓ | ✓ | ✓ | ✓ | XML-based, Khronos standard |
| VRML (.wrl) | VRMLLoader | ✓ | ✓ | ✓ | ✗ | ✓ | Web3D legacy format |
| OBJ | OBJLoader | ✓ | Via MTL | Via MTL | ✗ | ✗ | Simple mesh format |
| STL | STLLoader | ✓ | ✗ | ✗ | ✗ | ✗ | CAD/3D printing |
| PLY | PLYLoader | ✓ | Vertex colors | ✗ | ✗ | ✗ | Point cloud/mesh |
| 3MF | ThreeMFLoader | ✓ | ✓ | ✓ | ✗ | ✗ | 3D printing standard |
| AMF | AMFLoader | ✓ | ✓ | ✗ | ✗ | ✗ | 3D printing (XML) |
| PCD | PCDLoader | Points | Vertex colors | ✗ | ✗ | ✗ | Point Cloud Data |
| VTK | VTKLoader | ✓ | Vertex colors | ✗ | ✗ | ✗ | Scientific visualization |
| NRRD | NRRDLoader | Volume data | ✗ | ✗ | ✗ | ✗ | Medical imaging voxels |
| XYZ | XYZLoader | Points | ✓ | ✗ | ✗ | ✗ | Simple point cloud |
| KMZ | KMZLoader | ✓ | ✓ | ✓ | ✓ | ✓ | Compressed Collada |
FBXLoader Architecture
FBXLoader is the most comprehensive additional format loader, supporting full scene hierarchies with animations, materials, textures, lights, cameras, and skeletal animations. It handles both ASCII and binary FBX formats version 7.0+.
FBX Parsing Pipeline
FBX Parsing Pipeline: load() → parse() → FBXTreeParser
The loader uses FileLoader to load the raw data as an ArrayBuffer, then determines format with isFbxFormatBinary() and isFbxFormatASCII() helper functions. The parsers construct a global fbxTree object containing all FBX nodes, which FBXTreeParser then processes sequentially through its parsing methods. The final output is stored in a global sceneGraph variable of type Group.
FBX Object Types and Three.js Mapping
The FBX format contains multiple object types in fbxTree.Objects.Model that FBXTreeParser.parseModels() converts to Three.js objects based on the node.attrType field:
FBX node.attrType → Three.js Object Mapping
FBX Material System
FBX materials in fbxTree.Objects.Material have a ShadingModel property that determines the Three.js material type. The parseMaterial() method extracts material parameters and the parseParameters() method processes texture connections:
FBX Material Parsing: materialNode.ShadingModel → MeshLambertMaterial/MeshPhongMaterial
FBX Deformers and Skeletal Animation
FBX deformers in fbxTree.Objects.Deformer are processed by parseDeformers() which returns a structure with skeletons and morphTargets dictionaries. The deformerNode.attrType determines the deformer type:
FBX Deformer Processing: parseDeformers() → bindSkeleton()
FBX Animation System
FBX animations are parsed by AnimationParser.parse() which constructs AnimationClip objects from the animation data in fbxTree.Objects.AnimationCurveNode and related nodes. The parser uses parseAnimStack(), parseAnimationLayers(), and parseAnimationCurveNodes() to build the animation hierarchy:
FBX Animation Pipeline: AnimationParser.parse() → AnimationClip
OBJLoader and MTLLoader
The OBJ format is a simple ASCII mesh format that stores vertex positions, normals, UV coordinates, and face definitions. Materials are defined in a separate MTL file.
OBJ Parsing State Machine
OBJLoader.parse() uses a ParserState object to accumulate vertex data and build objects. The parser reads line-by-line, dispatching to state methods based on the line prefix:
OBJ Line-by-Line Parser: ParserState methods
MTLLoader Material Creation
MTLLoader.parse() reads MTL line-by-line, building a materialsInfo dictionary. It returns a MaterialCreator instance that lazily creates materials when create(materialName) is called:
MTL Parsing: MaterialCreator.create() → MeshPhongMaterial
ColladaLoader Architecture
Collada (.dae) is an XML-based format that supports full scene graphs with animations, kinematics, and physics. ColladaLoader is one of the most complex loaders.
Collada Parsing Pipeline
ColladaLoader.parse() uses DOMParser to parse the XML, then calls helper functions like parseLibrary() and buildLibrary() for each library section. The result includes a scene (Group), animations array, and kinematics object:
Collada XML Processing: parseLibrary() → buildLibrary() → Result
Collada Library System
Collada organizes content into libraries that are parsed independently and then cross-referenced:
| Library | XML Element | Parser Function | Three.js Output |
|---|---|---|---|
| Geometries | <library_geometries> | parseGeometry() | BufferGeometry |
| Materials | <library_materials> | parseMaterial() | MeshLambertMaterial / MeshPhongMaterial |
| Effects | <library_effects> | parseEffect() | Material parameters |
| Images | <library_images> | parseImage() | Texture |
| Animations | <library_animations> | parseAnimation() | AnimationClip |
| Cameras | <library_cameras> | parseCamera() | PerspectiveCamera / OrthographicCamera |
| Lights | <library_lights> | parseLight() | DirectionalLight / PointLight / SpotLight |
| Visual Scenes | <library_visual_scenes> | parseVisualScene() | Group hierarchy |
Point Cloud Loaders
Three.js provides several loaders for point cloud data formats, each returning a Points object with a BufferGeometry containing position and optional color/normal attributes.
Point Cloud Format Comparison
Point cloud loaders all return a Points object containing a BufferGeometry with vertex positions and optional color/normal attributes:
Point Cloud Loaders: parse() → Points
PCD Header and Data Parsing
PCDLoader.parse() first calls parseHeader() to extract PCD metadata, then uses PCDheader.data to determine which parsing path to take. The _getDataView() helper reads typed data from the binary buffer:
PCD Data Extraction: parseHeader() → parse ASCII/binary/compressed
3D Printing Format Loaders
Several loaders target 3D printing workflows, with different levels of material support.
3D Printing Format Loaders
Three loaders target 3D printing workflows with varying complexity:
3D Printing Format Capabilities
| Format | Loader | Geometry | Materials | Textures | Output |
|---|---|---|---|---|---|
| STL | STLLoader | Triangle mesh | ✗ | ✗ | BufferGeometry (no material) |
| 3MF | 3MFLoader | Triangle mesh | ✓ (PBR) | ✓ | Group with MeshStandardMaterial |
| AMF | AMFLoader | Triangle mesh | ✓ (basic) | ✗ | Group with MeshPhongMaterial |
STL Format: STLLoader.parse() detects ASCII vs binary with isBinary(), then calls parseASCII() or parseBinary(). Binary STL may contain "Magics" color data in the attribute byte count field.
3MF Format: 3MFLoader.parse() uses JSZip to extract 3D/3dmodel.model XML file, parses resources (basematerials, texture2d, objects), and builds meshes with material arrays. Supports pbmetallicdisplayproperties for PBR metallic/roughness.
AMF Format: AMFLoader.parse() handles both plain XML and ZIP-compressed AMF files. Parses <object> → <mesh> → <vertices> and <volume> → <triangle> structure with optional <material> definitions.
3MF Material and Texture System
3MFLoader parses XML resources and builds materials with buildBasematerialsMeshStandardSet() or buildMaterialsMeshPhong(). The buildTexture() method loads textures from the ZIP archive:
3MF Resource Processing: XML resources → Material arrays
VRMLLoader Scene Graph
VRMLLoader parses VRML 2.0 files, which use a hierarchical scene graph with nodes and fields:
VRML Node Types
VRMLLoader.parse() uses the Chevrotain parser library to tokenize and parse VRML 2.0 syntax into an AST (Abstract Syntax Tree). The parseTree() function walks the AST and calls buildNode() for each node based on node.name:
VRML Parsing: Chevrotain → AST → buildNode() → Scene
VTKLoader for Scientific Visualization
VTKLoader supports the VTK (Visualization Toolkit) format for scientific and medical data visualization. It handles both ASCII and binary POLYDATA:
VTK POLYDATA Structure
VTKLoader.parse() calls parseASCII() or parseBinary() based on the file content. The parser uses state machine variables (inPointsSection, inPolygonsSection, etc.) to track which section is being read:
VTK Section-Based Parsing: parseASCII/parseBinary() → BufferGeometry
NRRDLoader for Medical Imaging
NRRDLoader loads NRRD (Nearly Raw Raster Data) format files commonly used for medical imaging and scientific volume visualization. Unlike mesh loaders, it returns a Volume object containing 3D voxel data rather than surface geometry.
NRRD Format Structure
NRRD files consist of a text header followed by raw binary volume data. The header specifies dimensions, data type, encoding, and spatial transformations:
NRRD Header Fields
| Field | Description | Example |
|---|---|---|
| type | Data type (uint8, int16, float, etc.) | type: unsigned char |
| dimension | Number of dimensions | dimension: 3 |
| sizes | Size along each dimension | sizes: 256 256 128 |
| encoding | Data encoding (raw, gzip, bzip2) | encoding: gzip |
| endian | Byte order (little, big) | endian: little |
| space directions | Spatial transformation vectors | space directions: (1,0,0) (0,1,0) (0,0,1) |
NRRD Parsing Pipeline
NRRDLoader.parse() splits the file into header and data sections, parses the header with field-specific functions in _fieldFunctions, then decodes the data based on the encoding type:
NRRD Parsing: parseHeader() → decompression → Volume object
Volume Object and Coordinate Systems
The Volume class stores 3D voxel data and provides methods for accessing values and extracting 2D slices. It maintains two coordinate systems:
IJK Coordinate System: Integer indices into the volume data array (0 to xLength-1, etc.)
RAS Coordinate System: Real-world spatial coordinates (Right-Anterior-Superior) defined by the space directions header
The volume.matrix property transforms from IJK to RAS coordinates, and volume.extractSlice(axis, index) returns a VolumeSlice object for rendering:
// Volume structure
class Volume {
xLength: number; // Width in IJK
yLength: number; // Height in IJK
zLength: number; // Depth in IJK
data: TypedArray; // Voxel values
spacing: Vector3; // Physical spacing
matrix: Matrix4; // IJK to RAS transform
getData(i, j, k): number;
extractSlice(axis, index): VolumeSlice;
}VolumeSlice Rendering
VolumeSlice represents a 2D cross-section of the volume as a Mesh with a dynamically-generated texture. The updateGeometry() method positions the slice plane in RAS space, and repaint() extracts voxel data to a canvas texture:
VolumeSlice Architecture: Canvas texture → PlaneGeometry mesh
NRRD Usage Example
import { NRRDLoader } from 'three/addons/loaders/NRRDLoader.js';
const loader = new NRRDLoader();
const volume = await loader.loadAsync('brain.nrrd');
// Create slice through the volume
const sliceZ = volume.extractSlice('z', Math.floor(volume.zLength / 2));
scene.add(sliceZ.mesh);
// Access voxel data
const value = volume.getData(128, 128, 64); // IJK coordinates
console.log(`Voxel value at (128,128,64): ${value}`);
// Volume properties
console.log(`Volume dimensions: ${volume.xLength} x ${volume.yLength} x ${volume.zLength}`);
console.log(`RAS dimensions: ${volume.RASDimensions.join(' x ')}`);Common Loader Patterns
All Three.js loaders follow common architectural patterns inherited from the Loader base class:
Loader Base Class Integration
All loaders extend the Loader base class which provides common functionality like setPath(), setResourcePath(), setCrossOrigin(), and setRequestHeader(). The typical pattern is:
Common Loader Pattern: load() → FileLoader → parse()
Coordinate System Conversion
Many formats use different coordinate systems (Z-up vs Y-up). Loaders handle this through transformation:
| Format | Native Coordinate System | Conversion Strategy |
|---|---|---|
| FBX | Y-up (native) | No conversion needed |
| Collada | Z-up or Y-up (specified in <up_axis>) | Apply 90° X-rotation if Z-up |
| OBJ | Y-up | No conversion needed |
| VRML | Y-up | No conversion needed |
| STL | Z-up (convention) | Manual rotation recommended: object.rotation.set(-Math.PI/2, 0, 0) |
| 3MF | Z-up (3D printing standard) | Manual rotation recommended |
Material Default Handling
When materials are missing or unsupported, loaders use default materials:
// FBXLoader default material
const material = new MeshPhongMaterial({
name: Loader.DEFAULT_MATERIAL_NAME,
color: 0xcccccc
});
// OBJLoader default material
const material = new MeshPhongMaterial();
// STLLoader - geometry only, no default material
// Application must provide materialUsage Examples
Loading FBX with Animations
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
const loader = new FBXLoader();
const fbx = await loader.loadAsync('model.fbx');
scene.add(fbx);
// Access animations
if (fbx.animations && fbx.animations.length > 0) {
const mixer = new THREE.AnimationMixer(fbx);
const action = mixer.clipAction(fbx.animations[0]);
action.play();
}Loading OBJ with MTL Materials
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
import { MTLLoader } from 'three/addons/loaders/MTLLoader.js';
// Load materials first
const mtlLoader = new MTLLoader();
const materials = await mtlLoader.loadAsync('model.mtl');
materials.preload();
// Load OBJ with materials
const objLoader = new OBJLoader();
objLoader.setMaterials(materials);
const object = await objLoader.loadAsync('model.obj');
scene.add(object);Loading Point Cloud Data
import { PCDLoader } from 'three/addons/loaders/PCDLoader.js';
const loader = new PCDLoader();
const points = await loader.loadAsync('pointcloud.pcd');
// Points object contains geometry with position and color
points.geometry.center();
points.geometry.rotateX(Math.PI); // Z-up to Y-up
scene.add(points);Loader Capabilities and Limitations
Format-Specific Limitations
FBXLoader:
- Requires FBX version >= 7.0 (6400+ for binary)
- Morph normals not supported examples/jsm/loaders/FBXLoader.js58-61
- Only Lambert and Phong materials supported examples/jsm/loaders/FBXLoader.js536-548
- Orthographic cameras converted to Object3D placeholder examples/jsm/loaders/FBXLoader.js1137-1140
ColladaLoader:
- Only subset of full Collada spec supported examples/jsm/loaders/ColladaLoader.js44-48
- Only matrix animation transform type implemented examples/jsm/loaders/ColladaLoader.js516-527
- Vertex data not converted when coordinate system changes examples/jsm/loaders/ColladaLoader.js48-51
VRMLLoader:
- No animation support
- Many node types not implemented (Inline, LOD, Switch, Script, etc.) examples/jsm/loaders/VRMLLoader.js745-782
STLLoader:
- No material support (geometry only)
- Binary format may have endianness issues examples/jsm/loaders/STLLoader.js16-19
- "Magics" color format only for binary examples/jsm/loaders/STLLoader.js17-18
VTKLoader:
- Only POLYDATA dataset format supported examples/jsm/loaders/VTKLoader.js12-16
- Other formats (structured points, structured grid, etc.) not supported
NRRDLoader:
- Bzip2 compression not supported examples/jsm/loaders/NRRDLoader.js230-234
- Returns
Volumeobject, not standardBufferGeometryexamples/jsm/loaders/NRRDLoader.js95 - Requires
VolumeSlicefor rendering examples/jsm/misc/VolumeSlice.js18-27
Performance Considerations
- Binary formats (binary FBX, binary STL, binary PLY) load faster than ASCII
- Compressed formats (3MF, KMZ, compressed PCD) require decompression overhead via fflate
- Large point clouds (PCD, PLY, XYZ) can create very large geometries - consider LOD or culling
- Complex scenes (FBX, Collada) with many objects should use scene graph traversal optimization