Threebox works by adding a Three.js scene to Mapbox GL, via a custom layer. The custom layer API takes a fair amount of finessing to be useful, and Threebox tackles several hurdles to getting THREE and Mapbox to work together.
var tb = new Threebox(map, mapboxGLContext[, options])
Sets up a threebox scene inside a Mapbox GL custom layer's onAdd function, which provides both inputs for this method. Automatically synchronizes the camera movement and events between Three.js and Mapbox GL JS.
option | required | default | type | purpose |
---|---|---|---|---|
defaultLights |
no | false | boolean | Whether to add some default lighting to the scene. If no lighting added, most objects in the scene will render as black |
passiveRendering |
no | true | boolean | Color of line. Unlike other Threebox objects, this color will render on screen precisely as specified, regardless of scene lighting |
tb.update()
Rerender the threebox scene. Fired in the custom layer's render
function.
Threebox offers convenience functions to construct meshes of various Three.js meshes, as well asl . Under the hood, they invoke a subclass of THREE.Object3D.
Objects in Threebox fall under two broad varieties. Static objects don't move or change once they're placed, and used usually to display background or geographical features. They may have complex internal geometry, which are expressed primarily in lnglat coordinates.
In contrast, dynamic objects can move around the map, positioned by a single lnglat point. Their internal geometries are produced mainly in local scene units, whether through external obj files, or these convenience methods below.
##Static objects
###Line
tb.line(options)
Adds a line to the map, in full 3D space. Color renders independently of scene lighting. Internally, calls a custom line shader.
option | required | default | type | purpose |
---|---|---|---|---|
geometry |
yes | NA | lineGeometry | Array of lnglat coordinates to draw the line |
color |
no | black | color | Color of line. Unlike other Threebox objects, this color will render on screen precisely as specified, regardless of scene lighting |
width |
no | 1 | number | Line width. Unlike other Threebox objects, this width is in units of display pixels, rather than meters or scene units. |
opacity |
no | 1 | Number | Line opacity |
###Tube
tb.tube(options)
Extrude a tube along a specific lineGeometry, with an equilateral polygon as cross section. Internally uses a custom tube geometry generator.
option | required | default | type | description |
---|---|---|---|---|
geometry |
yes | NA | lineGeometry | Line coordinates forming the tube backbone |
radius |
no | 20 | number | Radius of the tube cross section, or half of tube width. |
sides |
no | 8 | number | Number of facets along the tube. The higher, the more closely the tube will approximate a smooth cylinder. |
material |
no | MeshLambertMaterial | threeMaterial | THREE material to use. Can be invoked with a text string, or a predefined material object via THREE itself. |
color |
no | black | color | Tube color. Ignored if material is a predefined THREE.Material object. |
opacity |
no | 1 | Number | Tube opacity |
##Dynamic objects
###Sphere
tb.sphere(options)
Add a sphere to the map. Internally, calls THREE.Mesh
with a THREE.SphereGeometry
.
option | required | default | type | description |
---|---|---|---|---|
radius |
no | 50 | number | Radius of sphere. |
units |
no | scene | string ("scene" or "meters") | Units with which to interpret radius . If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
sides | no | 8 | number | Number of width and height segments. The higher the number, the smoother the sphere. |
color | no | black | color | Color of sphere. |
material |
no | MeshLambertMaterial | threeMaterial | THREE material to use. Can be invoked with a text string, or a predefined material object via THREE itself. |
###External OBJ object
threebox.loadObj(options, callback(obj))
Loads an object via an external .obj and .mtl file. Note that unlike all the other object classes, this is asynchronous, and returns the object as an argument of the callback function. Internally, uses THREE.OBJLoader
to fetch the .obj assets.
option | required | default | type | description |
---|---|---|---|---|
obj |
yes | NA | string | URL path to asset's .obj file |
mtl |
yes | NA | string | URL path to asset's .mtl file |
units |
no | scene | string ("scene" or "meters") | Units with which to interpret the object's vertices. If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
rotation |
no | 0 | rotationTransform | Rotation of the object along the three axes, to align it to desired orientation before future rotations. Note that future rotations apply atop this transformation, and do not overwrite it. |
scale |
no | 1 | scaleTransform | Scale of the object along the three axes, to size it appropriately before future transformations. Note that future scaling applies atop this transformation, rather than overwriting it. |
callback |
yes | NA | function | A function to run after the object loads. The first argument will be the successfully loaded object. |
###Object3D
threebox.Object3D(obj)
Add a THREE.Object3D
instantiated elsewhere in THREE, to empower it with Threebox methods below. Unnecessary for objects instantiated with any methods above.
option | required | default | type | description |
---|---|---|---|---|
units |
no | scene | string ("scene" or "meters") | Units with which to interpret the object's vertices. If meters, Threebox will also rescale the object with changes in latitude, to appear to scale with objects and geography nearby. |
###Shared methods between dynamic objects
obj.setCoords(lnglat)
Positions the object at the desired coordinate, and resizes it appropriately if it was instantiated with units: "meters"
. Can be called before adding object to the map.
obj.set(options)
Broad method to update object's position, rotation, and scale. Check out the Threebox Types section below for details
Options
option | required | default | type | description |
---|---|---|---|---|
coords |
no | NA | lnglat |
Position to which to move the object |
rotation |
no | NA | rotationTransform |
Rotation(s) to set the object, in units of degrees |
scale |
no | NA | scaleTransform |
Scale(s) to set the object, where 1 is the default scale |
obj.followPath(options(, callback) )
Translate object along a specified path. Optional callback function to execute when animation finishes
option | required | default | type | description |
---|---|---|---|---|
path |
yes | NA | lineGeometry | Path for the object to follow |
duration |
no | 1000 | number | Duration to travel the path, in milliseconds |
trackHeading |
no | true | boolean | Rotate the object so that it stays aligned with the direction of travel, throughout the animation |
####obj.stop()
Stops all of object's current animations.
####obj.duplicate()
Returns a clone of the object. Greatly improves performance when handling many identical objects, by reusing materials and geometries.
##Utilities
tb.projectToWorld(lnglat)
Calculate the corresponding Vector3
for a given lnglat.
tb.unprojectFromWorld(Vector3)
Calculate the corresponding lnglat for a given Vector3
.
tb.queryRenderedFeatures({x: number, y: number})
Takes an input of xy
as an object with values representing screen coordinates (as returned by mapboxgl mouse events as e.point
). Returns an array of threebox objects at that screen position.
pointGeometry [longitude, latitude(, meters altitude)]
An array of 2-3 numbers representing longitude, latitude, and optionally altitude (in meters). When altitude is omitted, it is assumed to be 0. When populating this from a GeoJSON Point, this array can be accessed at point.geometry.coordinates
.
While altitude is not standardized in the GeoJSON specification, Threebox will accept it as such to position objects along the z-axis.
####lineGeometry
[pointGeometry, pointGeometry ... pointGeometry]
An array of at least two lnglat's, forming a line. When populating this from a GeoJSON Linestring, this array can be accessed at linestring.geometry.coordinates
.
####rotationTransform
number
or {x: number, y: number, z: number}
Angle(s) in degrees to rotate object. Can be expressed as either an object or number.
The object form takes three optional parameters along the three major axes: x is parallel to the equator, y parallel to longitudinal lines, and z perpendicular to the ground plane.
The number form rotates along the z axis, and equivalent to {z: number}
.
####scaleTransform
number
or {x: number, y: number, z: number}
Amount to scale the object, where 1 is the default size. Can be expressed as either an object or number.
The three axes are identical to those of rotationTransform
. However, expressing as number form scales all three axes by that amount.
####threeMaterial
string
or instance of THREE.Material()
Denotes the material used for an object. This can usually be customized further with color
and opacity
parameters in the same
Can be expressed as a string to the corresponding material type (e.g. "MeshPhysicalMaterial"
for THREE.MeshPhysicalMaterial()
), or a prebuilt THREE material directly.
##Using vanilla Three.js in Threebox
Threebox implements many small affordances to make mapping run in Three.js quickly and precisely on a global scale. Whenever possible, use threebox methods to add, change, manage, and remove elements of the scene. Otherwise, here are some best practices:
- Use
threebox.Object3D
to add custom objects to the scene - If you must interact directly with the THREE scene, add all objects to
threebox.world
. tb.projectToWorld
to convert lnglat to the correspondingVector3()
#Performance considerations
- Use
obj.clone()
when adding many identical objects.