Overview
Threebox supports loading external 3D models in multiple formats through the tb.loadObj() method. Once loaded, models become interactive objects with built-in methods for positioning, animation, selection, and dragging.
GLTF/GLB Industry-standard format with animation and PBR material support
FBX Autodesk format popular in game development and animation
OBJ/MTL Classic 3D format with separate material files
Collada (DAE) Open format supporting complex scenes and animations
Basic Usage
const options = {
obj: '/models/soldier.glb' ,
type: 'gltf' ,
scale: 1 ,
units: 'meters' ,
rotation: { x: 90 , y: 0 , z: 0 }
};
tb . loadObj ( options , function ( model ) {
model . setCoords ([ - 122.4194 , 37.7749 ]);
tb . add ( model );
});
GLTF/GLB Models
GLTF (separate files)
GLB (single file)
const options = {
type: 'gltf' ,
obj: '/models/robot.gltf' ,
bin: '/models/robot.bin' , // Optional binary data
units: 'meters' ,
scale: 5 ,
rotation: { x: 90 , y: 0 , z: 0 },
defaultAnimation: 0 // Play first animation by default
};
GLTF models can include animations. Use defaultAnimation to specify which animation plays by default, or control animations programmatically after loading.
FBX Models
const options = {
type: 'fbx' ,
obj: '/models/character.fbx' ,
units: 'meters' ,
scale: 0.01 , // FBX models often need scaling
normalize: true , // Recommended for FBX
rotation: { x: 90 , y: 0 , z: 0 }
};
tb . loadObj ( options , function ( model ) {
model . setCoords ( origin );
model . castShadow = true ;
tb . add ( model );
});
OBJ/MTL Models
const options = {
type: 'mtl' ,
obj: '/models/building.obj' ,
mtl: '/models/building.mtl' , // Material file
units: 'meters' ,
scale: 1 ,
rotation: { x: 0 , y: 0 , z: 0 }
};
Collada (DAE) Models
const options = {
type: 'dae' ,
obj: '/models/scene.dae' ,
units: 'meters' ,
scale: 1 ,
rotation: { x: 90 , y: 0 , z: 0 }
};
Configuration Options
Required Parameters
Parameter Type Description type'mtl' | 'gltf' | 'glb' | 'fbx' | 'dae'Model format type objstringURL path to the model file callbackfunctionCallback function receiving the loaded model
Optional Parameters
Parameter Type Default Description mtlstringnullURL to material file (OBJ format only) binstringnullURL to binary file (GLTF format only) units'scene' | 'meters''scene'Coordinate system for model vertices scalenumber | {x, y, z}1Model scale (uniform or per-axis) rotationnumber | {x, y, z}0Initial rotation in degrees anchorstring'bottom-left'Pivot point for positioning and rotation adjustment{x, y, z}{x:0, y:0, z:0}Fine-tune center position normalizebooleantrueNormalize specular values (recommended for FBX/GLTF) bboxbooleantrueEnable bounding box display tooltipbooleantrueEnable tooltip on hover raycastedbooleantrueInclude in raycasting for selection clonebooleantrueClone textures for new instances defaultAnimationnumber0Default animation index withCredentialsbooleanfalseSend credentials with HTTP requests
Positioning and Anchoring
Anchor Points
The anchor parameter determines the model’s pivot point:
const options = {
obj: '/models/building.glb' ,
type: 'gltf' ,
anchor: 'center' , // 'top', 'bottom', 'left', 'right', 'top-left', etc.
units: 'meters'
};
Use anchor: 'bottom-left' (default) for most ground-level objects, and anchor: 'center' for objects that float or need centered rotation.
Adjustment for Off-Center Models
Many 3D models have misaligned centers. Use adjustment to correct this:
const options = {
obj: '/models/car.glb' ,
type: 'gltf' ,
anchor: 'bottom-left' ,
adjustment: { x: 0.5 , y: 0.5 , z: 0 } // Shift center by these ratios
};
Advanced Configuration
Using GeoJSON Features
Store model metadata in GeoJSON feature properties:
const feature = {
type: 'Feature' ,
geometry: {
type: 'Point' ,
coordinates: [ - 122.4194 , 37.7749 , 100 ]
},
properties: {
height: 50 ,
name: 'Building A' ,
camera: [ - 122.4194 , 37.7749 ],
zoom: 18 ,
pitch: 60 ,
bearing: 45
}
};
const options = {
type: 'gltf' ,
obj: '/models/building.glb' ,
feature: feature ,
units: 'meters'
};
tb . loadObj ( options , function ( model ) {
model . setCoords ( feature . geometry . coordinates );
tb . add ( model );
});
Controlling Scale
Uniform Scale
Per-Axis Scale
const options = {
obj: '/models/tree.glb' ,
type: 'gltf' ,
scale: 10 // 10x original size
};
Rotation
const options = {
obj: '/models/soldier.glb' ,
type: 'gltf' ,
rotation: { x: 90 , y: 0 , z: 0 } // Rotate 90° on X-axis
};
Model Caching
Threebox automatically caches the first instance of each model URL. Subsequent loads return duplicates from cache:
// First load - fetched from server and cached
tb . loadObj ( options , function ( model1 ) {
model1 . setCoords ([ - 122.4194 , 37.7749 ]);
tb . add ( model1 );
});
// Second load - duplicated from cache (faster)
tb . loadObj ( options , function ( model2 ) {
model2 . setCoords ([ - 122.4200 , 37.7750 ]);
tb . add ( model2 );
});
Set clone: false to create a new instance without cloning textures. This uses more memory but may be needed for models with complex animations.
Server Configuration
3D model file extensions require MIME type configuration on your web server.
< system.webServer >
< staticContent >
< remove fileExtension = ".glb" />
< mimeMap fileExtension = ".glb" mimeType = "model/gltf-binary" />
< remove fileExtension = ".gltf" />
< mimeMap fileExtension = ".gltf" mimeType = "model/gltf+json" />
< remove fileExtension = ".fbx" />
< mimeMap fileExtension = ".fbx" mimeType = "application/octet-stream" />
< remove fileExtension = ".dae" />
< mimeMap fileExtension = ".dae" mimeType = "application/vnd.oipf.dae.svg+xml" />
</ staticContent >
</ system.webServer >
http {
include /etc/nginx/mime.types;
types {
model/gltf+json gltf;
model/gltf-binary glb;
application/octet-stream fbx;
application/vnd.oipf.dae.svg+xml dae;
}
}
model/gltf+json gltf
model/gltf-binary glb
application/octet-stream fbx
application/vnd.oipf.dae.svg+xml dae
Complete Example
map . on ( 'style.load' , function () {
map . addLayer ({
id: 'custom_layer' ,
type: 'custom' ,
renderingMode: '3d' ,
onAdd : function ( map , gl ) {
window . tb = new Threebox (
map ,
gl ,
{
defaultLights: true ,
enableSelectingObjects: true ,
enableDraggingObjects: true ,
enableRotatingObjects: true ,
enableTooltips: true
}
);
const options = {
obj: '/models/soldier.glb' ,
type: 'gltf' ,
scale: 20 ,
units: 'meters' ,
rotation: { x: 90 , y: 0 , z: 0 },
anchor: 'bottom-left' ,
adjustment: { x: 0 , y: 0 , z: 0 }
};
tb . loadObj ( options , function ( model ) {
const soldier = model . setCoords ([ - 122.4194 , 37.7749 , 0 ]);
// Add event listeners
soldier . addEventListener ( 'SelectedChange' , onSelectedChange , false );
soldier . addEventListener ( 'ObjectDragged' , onDraggedObject , false );
tb . add ( soldier );
});
},
render : function ( gl , matrix ) {
tb . update ();
}
});
});
function onSelectedChange ( e ) {
console . log ( 'Model selected:' , e . detail . selected );
}
function onDraggedObject ( e ) {
console . log ( 'Model dragged to:' , e . detail . coordinates );
}
Next Steps
Primitives Create spheres, lines, and tubes
Materials & Lighting Configure materials and scene lighting