Skip to content

Latest commit

 

History

History
executable file
·
2043 lines (1540 loc) · 94.6 KB

Threebox.md

File metadata and controls

executable file
·
2043 lines (1540 loc) · 94.6 KB

Threebox Documentation


Background

Threebox works by adding a Three.js scene to Mapbox GL, creating a new Mapbox GL custom layer that implements CustomLayerInterface. The custom layer API takes a fair amount of finessing to be useful, and Threebox tackles several hurdles to getting Three.js and Mapbox GL to work together.



Examples

Threebox contains +20 examples to showcase most of its features. Check them out to have a glance of what is possible.
To run them, create a config.js file with your Mapbox-gl-js access token, in the same folder and in the format of the template.



Threebox

Using Threebox

You can use threebox in three different ways.

NPM install

Add threebox to your project via npm package NPM version :

npm install threebox-plugin

Then you will need to import Threebox object in your code. Depending your javascript framework this might be different.

import { Threebox } from 'threebox-plugin/dist/threebox'; 

Use the bundle locally

Download the bundle from dist/threebox.js or dist/threebox.min.js and include it in a <script> tag on your page.
If you want to use styles predefined, add the link to the cascade style sheet, just ensure the src and href attributes are pointing to relative or absolute url path.

<script src="../dist/threebox.js" type="text/javascript"></script>
<link href="./css/threebox.css" rel="stylesheet" />

Public CDNs

Threebox can be also used from different public CDNs:

jsdelivr

This CDN has the particularity that always requires the version of the package to download individual files.

<script src="https://cdn.jsdelivr.net/gh/jscastro76/[email protected]/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://cdn.jsdelivr.net/gh/jscastro76/[email protected]/dist/threebox.css" rel="stylesheet" />

unpkg

Despite this CDN admits version, if omitted, it will download always the last one published.

<script src="https://unpkg.com/threebox-plugin/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://unpkg.com/threebox-plugin/dist/threebox.css" rel="stylesheet" />

For an specific version (i.e. v2.2.1) use the followin:

<script src="https://unpkg.com/[email protected]/dist/threebox.min.js" type="text/javascript"></script>
<link href="https://unpkg.com/[email protected]/dist/threebox.css" rel="stylesheet" />


Threebox instance

The instance of Threebox will be used normally across the full page, so it's recommended to be created at window scope to be used as a global variable.
Creating a global instance might be producing memory leaks when you navigate to other pages without disposing properly the resources. You can use tb.dispose method to fully dispose the instance of Threebox but also all mapbox and three.js resources together.

constructor

var tb = new Threebox(map, glContext [, options])

Sets up a Threebox scene using an Mapbox map and a WebGLRenderingContext, both of them can be obtained from Mapbox GL map instance.
options param is optional and can contain the following values:

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
realSunlight no false boolean It sets lights that simulate Sun position for the map center coords map.getCenter and user local datetime new Date(). This sunlight can be updated through tb.setSunlight method. It calls internally to suncalc module.
realSunlightHelper no false boolean It sets if a light helper will be shown when realSunlight is true.
passiveRendering no true boolean Color of line. Unlike other Threebox objects, this color will render on screen precisely as specified, regardless of scene lighting
enableSelectingFeatures no false boolean Enables the Mouseover and Selection of fill-extrusion features. This will fire the event SelectedFeatureChange
enableSelectingObjects no false boolean Enables the Mouseover and Selection of 3D objects. This will fire the event SelectedChange. This value will set the options.bbx value of the objects created.
enableDraggingObjects no false boolean Enables to the option to Drag a 3D object. This will fire the event ObjectDragged where draggedAction = 'translate' or draggedAction = 'altitude'
enableRotatingObjects no false boolean Enables to the option to Drag a 3D object. This will fire the event ObjectDragged where draggedAction = 'rotate'
enableTooltips no false boolean Enables the default tooltips on fill-extrusion features and 3D Objects
enableHelpTooltips no false boolean Enables the default help tooltips when an object is being moved, rotated or measured.
multiLayer no false boolean Enables the option for multi layer pages where a default layer will be created internally that will manage the tb.update calls
orthographic no false boolean Enables the option to set a THREE.OrthographicCamera instead of a THREE.PerspectiveCamera which is the default in Mapbox
fov no ThreeboxConstants.FOV_DEGREES number Enables to set the FOV of the default THREE.PerspectiveCamera. This value has no effect if orthographic: true
sky no false boolean It sets a built-in atmospheric layer initially set with the time and the map center position. This layer is automatically updated if realSunlight is also true, but it can be updated separately through tb.updateSunSky(tb.getSunSky()) method call.
terrain no false boolean It sets a built-in terrain layer initially set with the time and the map center position. This layer is automatically updated if realSunlight is also true, but it can be updated separately through tb.updateSunSky(tb.getSunSky()) method call.

To render Threebox scene, first is needed to create a CustomLayerInterface, and then add the 3D objects to render at onAdd function.
Second, you need to call recursively to tb.update(); method from CustomLayerInterface render function.
Threebox then automatically synchronizes the camera movement and events between Three.js and Mapbox GL JS.

WebGLRenderingContext instance can be obtained in different ways. The most usual one is to get the context from the instance of the member onAdd(map, gl).
This method is quick and easy, but it implies that it's created only in every call to the method addLayer(layer[, beforeId])

map.addLayer({
	id: 'custom_layer',
	type: 'custom',
	renderingMode: '3d',
	onAdd: function (map, gl) {

		window.tb = new Threebox(
			map,
			gl, //get the context from Mapbox
			{ defaultLights: true }
		);
		var geometry = new THREE.BoxGeometry(30, 60, 120);
		let cube = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: 0x660000 }));
		cube = tb.Object3D({ obj: cube, units: 'meters' });
		cube.setCoords([-3.460539968876, 40.4849214450]);
		tb.add(cube);
	},
	render: function (gl, matrix) {
		tb.update(); //update Threebox scene
	}
}

The second way is to get the context from the canvas of the Mapbox GL map map.getCanvas().getContext('webgl').
In this way the creation of the Threebox can be instantiated separately from the addLayer method that is more useful for multiple layers and objects. In this way the instace will exist even if there are no custom layers created, so you have to take care to properly dispose the resources.

window.tb = new Threebox(
	map,
	map.getCanvas().getContext('webgl'), //get the context from the map canvas
	{ defaultLights: true }
);
map.addLayer({
	id: 'custom_layer',
	type: 'custom',
	renderingMode: '3d',
	onAdd: function (map, gl) {
		var geometry = new THREE.BoxGeometry(30, 60, 120);
		let cube = new THREE.Mesh(geometry, new THREE.MeshPhongMaterial({ color: 0x660000 }));
		cube = tb.Object3D({ obj: cube, units: 'meters' });
		cube.setCoords([-3.460539968876, 40.4849214450]);
		tb.add(cube);
	},
	render: function (gl, matrix) {
		tb.update(); //update Threebox scene
	}
}


Loading a 3D model

One of the most powerful capabilities of Threebox is the option to load 3D models from external files in different formats (OBJ/MTL, GLTF/GLB, FBX, DAE are supported). Once the model is loaded and added to Threebox, the object is powered by default with some methods, interactions, events and animations.

Once the object is loaded and added to Threebox instance, it can be selectable, draggable and rotable (over the z axis) with the mouse if Threebox instance properties enableSelectingObjects, enableDraggingObjects and enableRotatingObjects are set to true.

  • To drag an object you have to select the object and then press SHIFT key and move the mouse to change its Lnglat position, and CTRL key to change its altitude.
  • To rotate and object you have to select the object and then press ALT key and move the mouse. The object will always rotate over its defined center.

Any 3D object (including 3D extrusions created through fill-extrusion mapbox layers) will have a tooltip if the Threebox instance property tb.enableTooltips is set to true.

Here below is the simplest sample to load a 3D model:

<!doctype html>
<head>
	<title>Simplest sample of 3D Model loading</title>
	<script src="../dist/threebox.js" type="text/javascript"></script>
	<script src="https://api.mapbox.com/mapbox-gl-js/v.1.11.1/mapbox-gl.js"></script>
	<link href="https://api.mapbox.com/mapbox-gl-js/v.1.11.1/mapbox-gl.css" rel="stylesheet" />
	<style>
		body, html {
			width: 100%;
			height: 100%;
			margin: 0;
			background: black;
		}
		#map {
			width: 100%;
			height: 100%;
		}
	</style>
</head>
<body>
	<div id='map' class='map'></div>
	<script>
		mapboxgl.accessToken = 'Paste here your mapbox access token key';

		var origin = [-122.47920912, 37.716351775];
		var destination, line;
		var soldier;

		var map = new mapboxgl.Map({
			container: 'map',
			style: 'mapbox://styles/mapbox/outdoors-v11',
			center: origin,
			zoom: 18,
			pitch: 60,
			bearing: 0
		});

		map.on('style.load', function () {
			map.addLayer({
				id: 'custom_layer',
				type: 'custom',
				renderingMode: '3d',
				onAdd: function (map, mbxContext) {

					window.tb = new Threebox(
						map,
						mbxContext,
						{ defaultLights: true }
					);

					var options = {
						obj: '/3D/soldier/soldier.glb',
						type: 'gltf',
						scale: 1,
						units: 'meters',
						rotation: { x: 90, y: 0, z: 0 } //default rotation
					}

					tb.loadObj(options, function (model) {
						soldier = model.setCoords(origin);
						tb.add(soldier);
					})

				},
				render: function (gl, matrix) {
					tb.update();
				}
			});
		})
	</script>
</body>


Threebox Methods

Here is the full list of all the methods exposed by Threebox. In all the samples below, the instance of Threebox will be always referred as tb.

add

tb.add(obj [, layerId, sourceId])

method to add an object to Threebox scene. It will add it to tb.world.children array.


clear

async tb.clear([layerId, dispose])

This method removes any children from tb.world. If it receives a layerId this only affects to the objects in that layer.
If it receives true as a param, it will also call internally obj.dispose to dispose all the resources reserved by those objects.


createSkyLayer

tb.createSkyLayer()

This internal method creates a new sky atmospheric layer, it's interally used by the property tb.sky.


createTerrainLayer

tb.createTerrainLayer()

This internal method creates a new terrain layer, it's interally used by the property tb.terrain.


defaultLights

tb.defaultLights()

This method creates the default illumination of the Threebox scene.
By default, it creates a THREE.AmbientLight and assigned to tb.lights.ambientLight two THREE.DirectionalLight. These lights can be overriden manually adding custom lights to the Threebox scene.


dispose

tb.dispose() : Promise (async)

If Threebox is being used as a part of a web application, it's recommended to dispose explicitely the instance of Threebox whenever its instance is not going to be used anymore or before navigating to another page that does not include Threebox, otherwise it's likely that you will face memory leaks issues not only due to Threebox, but also due to the internal use of Mapbox GL and Three.js instances needed to manage the objects.

To dispose completely all the resources and memory Threebox can acumulate, including the internal resources from Three.js and Mapbox GL, it's needed to invoke the dispose method.

This method will go through the scene created to dispose every object, geometry, material and texture in Three.js, then it will dispose all the resources from Mapbox GL, including the WebGLRenderingContext and itselft the Threebox instance.

After calling to this method, Threebox and Mapbox GL map instances will be fully disposed so it's only recommended before navigating to other pages.


findParent3DObject

tb.findParent3DObject(mesh) : Object3D

This method finds the parent Object3D in the Threebox scene by a mesh. This method is used in combination with tb.queryRenderedFeatures that returns an Array of objects, most of them Meshes where the THREE.Raycaster has interesected.


getFeatureCenter

tb.getFeatureCenter(feature, model, level): lnglat

Calculate the center of a feature geometry coordinates, including the altitude (in meters) for a given GeoJson feature that can include or not a 3D model loaded and for a given level. This method calls internally to tb.getObjectHeightOnFloor and can be used for both a Poligon feature for a Fill Extrusion or a Point feature for a 3D model.


getObjectHeightOnFloor

tb.getObjectHeightOnFloor(feature, obj, level) : number

Calculate the altitude (in meters) for a given GeoJson feature that can include or not a 3D model loaded and for a given level. This method can be used for both a Poligon feature for a Fill Extrusion or a Point feature for a 3D model.


getSunPosition

tb.getSunPosition(date, coords)

This method gets Sun light position (azimuth, altitude) based on suncalc.js. module which calculates the sun position for a given date, time, lng, lat combination.


getSunSky

tb.getSunSky(date, sunPos)

This method gets Sun sky layer position [azimuth, altitude] based on suncalc.js. module which calculates the sun position for a given date, time, lng, lat combination. If date is provided, it will use that, otherwise it will use new Date(). If sunPos is provided, it will use that, otherwise it will calculate it based on map.getCenter() calling tb.getSunPosition method.


getSunTimes

tb.getSunTimes(date, coords)

This method gets Sun times based on suncalc.js. module which calculates the times for the different light phases (sunrise, sunset, etc..) from a given datetime, lng, lat and alt. This is used to change the map style based on day/night hour. Returns an object with the following properties (each is a Date object):

Property Description
sunrise sunrise (top edge of the sun appears on the horizon)
sunriseEnd sunrise ends (bottom edge of the sun touches the horizon)
goldenHourEnd morning golden hour (soft light, best time for photography) ends
solarNoon solar noon (sun is in the highest position)
goldenHour evening golden hour starts
sunsetStart sunset starts (bottom edge of the sun touches the horizon)
sunset sunset (sun disappears below the horizon, evening civil twilight starts)
dusk dusk (evening nautical twilight starts)
nauticalDusk nautical dusk (evening astronomical twilight starts)
night night starts (dark enough for astronomical observations)
nadir nadir (darkest moment of the night, sun is in the lowest position)
nightEnd night ends (morning astronomical twilight starts)
nauticalDawn nautical dawn (morning nautical twilight starts)
dawn dawn (morning nautical twilight ends, morning civil twilight starts)

loadObj

async tb.loadObj(options, callback(obj));

This async method loads a 3D model in different formats from its respective files. It automatically caches the first object for each resource url so the next instances are returned from obj.duplicate. 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, THREE.FBXLoader, THREE.GLTFLoader or THREE.ColladaLoader respectively to fetch the assets to each 3D format. THREE.FBXLoader also dependes on Zlib to open compressed files which this format is based on.

[jscastro] IMPORTANT: There are breaking changes in this release regarding the attributes below comparing to @peterqliu original Threebox.

option required default type description
type yes "mtl" string ("mtl", "gltf", "fbx", "dae") BREAKING CHANGE: Type is now required
obj yes NA string BREAKING CHANGE: URL path to asset's .obj, .glb, .gltf, .fbx, .dae file.
mtl no NA string URL path to assets .mtl files needed for OBJ models respectively
bin no NA string URL path to assets .bin files needed for GLTF models respectively
units no scene string ("scene" or "meters") "meters" is recommended for precision. 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 number or {x, y, z} 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. rotate attribute must be provided in number or per axis ((i.e. for an object rotated 90 degrees over the x axis rotation: {x: 90, y: 0, z: 0}
scale no 1 number or {x, y, z} 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. scale attribute must be provided in number or per axis ((i.e. for an object transformed to 3 times higher than it's default size scale: {x: 1, y: 1, z: 3}
anchor no bottom-left string () This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top, bottom, left, right, center, top-left, top-right, bottom-left, bottom-right. Default value is bottom-left. auto value will do nothing, so the model will use the anchor defined in the model, whatever it is.
adjustment no 1 {x, y, z} 3D models are often not centered in their axes so the object positions and rotates wrongly. adjustment param must be provided in units per axis (i.e. adjustment: {x: 0.5, y: 0.5, z: 0}), so the model will correct the center position of the object
normalize no true bool This param allows to normalize specular values from some 3D models
feature no 1 GeoJson feature GeoJson feature instance. properties object of the GeoJson standard feature could be used to store relavant data to load and paint many different objects such as camera position, zoom, pitch or bearing, apart from the attributes already usually used by Mapbox GL examples such as height, base_height, color
tooltip no false bool This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips
bbox no false bool This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects
raycasted no true bool This param allows to hide an object from raycast individually
clone no true bool This param allows to load an object without cloning it by default, but it will reduce performance because the new object will consume extra memory as no textures will be cloned. Some objects could require full new instances when animations and textures don't work well with cloning, then clone: false will solve the problem. By default clone param is true.
defaultAnimation no 0 number This allows to assign by param a default animation. Igneored if the object does not contain animations
callback yes NA function A function to run after the object loads. The first argument will be the successfully loaded object, and this is normally used to finish the configuration of the model and add it to Threebox scene through tb.add() method.
map.addLayer({
	id: 'custom_layer',
	type: 'custom',
	renderingMode: '3d',
	onAdd: function (map, gl) {

		window.tb = new Threebox(
			map,
			gl,
			{ 
				defaultLights: true 
              enableSelectingFeatures: true, //omit or change this to false to disable fill-extrusion features selection
              enableSelectingObjects: true, //omit or change this to false to disable 3D objects selection
              enableDraggingObjects: true, //omit or change this to false to disable 3D objects drag & move once selected
              enableRotatingObjects: true, //omit or change this to false to disable 3D objects rotation once selected
              enableTooltips: true, //omit or change this to false to disable default tooltips on fill-extrusion and 3D models
			}
		);

		var options = {
			obj: '/3D/soldier/soldier.glb', //the model url, relative path to the page 
			type: 'gltf', //type enum, glb format is
			scale: 20, //20x the original size
			units: 'meters', //everything will be converted to meters in setCoords method				
			rotation: { x: 90, y: 0, z: 0 }, //default rotation
			adjustment: { x: 0, y: 0, z: 0 }, // model center is displaced
			feature: geoJsonFeature // a valid GeoJson feature
		}

		tb.loadObj(options, function (model) {
			//this wil position the soldier at the GeoJson feature coordinates 
			soldier = model.setCoords(feature.geometry.coordinates);
			tb.add(soldier);
		})

	},
	render: function (gl, matrix) {
		tb.update();
	}
});

After the callback is initiated, the object returned will have the following events already available to listen that enable the UI to behave and react to those. You can add these addEventListener lines below to tb.loadObj:

	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('SelectedChange', onSelectedChange, false);
		soldier.addEventListener('Wireframed', onWireframed, false);
		soldier.addEventListener('IsPlayingChanged', onIsPlayingChanged, false);
		soldier.addEventListener('ObjectDragged', onDraggedObject, false);
		soldier.addEventListener('ObjectMouseOver', onObjectMouseOver, false);
		soldier.addEventListener('ObjectMouseOut', onObjectMouseOut, false);

		tb.add(soldier);
	})

In this way you'll be able to manage in you UI through a function once these events are fired. See below an example for onSelectedChange to use the method map.flyTo(options[, eventData]) from Mapbox GL:

// method to activate/deactivate a UI button.
// this example uses jQuery 
// this example requires a GeoJson feature included in the options of the tb.loadObj(options) 
function onSelectedChange(e) {
	let selected = e.detail.selected; //we get if the object is selected after the event
	$('#deleteButton')[0].disabled = !selected; //we find the delete button with jquery

	//if selected
	if (selected) {
		selectedObject = e.detail; //
		//we fly smoothly to the object selected
		map.flyTo({
			center: selectedObject.userData.feature.properties.camera,
			zoom: selectedObject.userData.feature.properties.zoom,
			pitch: selectedObject.userData.feature.properties.pitch,
			bearing: selectedObject.userData.feature.properties.bearing
		});
	}
	tb.update();
	map.repaint = true;
}

3D Formats and MIME types

Most of the popular 3D formats extensions (.glb, .gltf, .fbx, .dae, ...) are not standard MIME types, so you will need to configure your web server engine to accept this extensions, otherwise you'll receive different HTTP errors downloading them.
If you are using IIS server from an ASP.Net application, add the xml lines below in the </system.webServer> node of your web.config file:

<system.webServer>
	  ...
	  <staticContent>
		  <remove fileExtension=".mtl" />
		  <mimeMap fileExtension=".mtl" mimeType="model/mtl" />
		  <remove fileExtension=".obj" />
		  <mimeMap fileExtension=".obj" mimeType="model/obj" />
		  <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>

If you are using ASP.net core server, add the C# lines below in the Configure method of the Startup class:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    // Set up custom content types - associating file extension to MIME type
    var provider = new FileExtensionContentTypeProvider();
    // Add new mappings
    provider.Mappings[".mtl"] = "model/mtl";
    provider.Mappings[".obj"] = "model/obj";
    provider.Mappings[".glb"] = "model/gltf-binary";
    provider.Mappings[".gltf"] = "model/gltf+json";
    provider.Mappings[".fbx"] = "application/octet-stream";
    provider.Mappings[".dae"] = "application/vnd.oipf.dae.svg+xml";

    app.UseStaticFiles(new StaticFileOptions 
    {
        ContentTypeProvider = provider
    });

    ...
}

If you are using an nginx server, add the following lines to the nginx.conf file in the http object:

http {
	include /etc/nginx/mime.types;
	types {
		model/mtl mtl;
		model/obj obj;
		model/gltf+json gltf;
		model/gltf-binary glb;
		application/octet-stream fbx;
		application/vnd.oipf.dae.svg+xml dae;
	}
	...
}

If you are using an Apache server, add the following lines to the mime.types file:

model/mtl mtl
model/obj obj
model/gltf+json gltf
model/gltf-binary glb
application/octet-stream fbx
application/vnd.oipf.dae.svg+xml dae

memory

tb.memory() : Object

This will return the member memory from THREE.WebGLRenderer.info


programs

tb.programs() : int

This will return the lenght of the programs member from THREE.WebGLRenderer.info


projectToWorld

tb.projectToWorld(lnglat) : THREE.Vector3

Calculate the corresponding THREE.Vector3 for a given lnglat. It's inverse method is tb.unprojectFromWorld.


queryRenderedFeatures

tb.queryRenderedFeatures(point) : Array

This methods calculate objects intersecting the picking ray using THREE.Raycaster and returns an Array of the Threebox objects in the scene ordered by distance from closer to farther away.

Takes an input of {x: number, y: number} as an object with values representing screen coordinates (as returned by Mapbox GL mouse events as e.point).


realSunlight

tb.realSunlight([helper = true])

This method creates the an illumination that simulates Sun light for the Threebox scene. It creates a THREE.HemisphereLight and one THREE.DirectionalLight that is positioned based on suncalc.js. module which calculates the sun position for a given date, time, lng, lat combination. It calls internally to tb.setSunlight with map.getCenter and new Date() as values. These lights can be overriden manually adding custom lights to the Threebox scene. If helper is true, then a helper is shown.

remove

tb.remove(obj)

Method to remove an object from Threebox scene and the tb.world.children array.


removeByName

tb.removeByName(name)

Method to remove an object from Threebox scene and the tb.world.children array, Searches through an object and its children, starting with the object itself, and removes the first with a matching name..


removeLayer

tb.removeLayer(layerId)

Method to remove a layer from Mapbox, including all 3D objects from Threebox scene and the tb.world.children array.


setLayerHeigthProperty

tb.setLayerHeigthProperty(layerId, level) 

Method to set the height of all the objects in a level. This method only works if the objects have a GeoJson feature, and a level attribute among its properties.


setLayerZoomRange

tb.setLayerZoomRange(layerId, minZoomLayer, maxZoomLayer)

Custom Layers don't work on minzoom and maxzoom attributes, as every layer is rendering the full scene, and if the layer is including labels they don't hide either on minzoom.
This method sets the zoom range for any custom layer and manages the 3D objects and CSS2D labels toggle action in sync with layer visibility set through tb.setLayoutProperty.


setLayerZoomVisibility

tb.setLayerZoomVisibility(layerId)

This method sets or resets the layer visibility based on the current zoom. It's used by different methods to set the visibility of the layers.


setLayoutProperty

tb.setLayoutProperty(layerId, name, value)

This method replicates the behaviour of map.setLayoutProperty when custom layers are affected but it can used for any layer type.


setObjectsScale

tb.setObjectsScale()

This method scales all the objects from tb.world.children that are fixedZoom.


setStyle

tb.setStyle(styleId[, options])

This method replicates the behaviour of map.setStyle to remove the 3D objects from tb.world. It's a direct passthrough to map.setStyle but it also calls internally tb.clear(true) to remove the children from tb.world and also to dispose all the resources reserved by those objects.


setSunlight

tb.setSunlight(newDate = new Date(), coords)

This method updates Sun light position based on suncalc.js. module which calculates the sun position for a given date, time, lng, lat combination. It calls internally to tb.setSunlight with map.getCenter and new Date() as values.


toggleLayer

tb.toggleLayer(layerId, visible) 

This method to toggles any layer visibility but it's specifically designed for custom layers. If you want to avoid differentiating between Mapbox layers (including custom layers) this method replaces the call to map.setLayoutProperty(layerId, 'visibility', visible)


update

tb.update()

With tb.loadObj(options, callback(obj)) this is probably the most important method in Threebox as it's responsible of invoking the THREE.WebGLRenderer.render(scene, camera) method.


updateLightHelper

tb.updateLightHelper()

This method updates the poition of tb.lights.dirLightHelper, it's needed if we want to see the helper properly render when the light moves.


updateSunGround

tb.updateSunGround(sunPos)

If tb.realSunlight is true, this method updates the light over the satellite style (if applied) according to the sun altitude.


updateSunSky

tb.updateSunSky(sunPos)

If tb.sky is true, this method updates the sky atmospheric layer with the received sun position.


unprojectFromWorld

tb.unprojectFromWorld(Vector3): lnglat

Calculate the corresponding lnglat for a given THREE.Vector3. It's inverse method is tb.projectToWorld.


versions

tb.version() : string

This will return the version of Threebox



Threebox properties

In all the samples below, the instance of the Threebox will be always referred as tb.


altitudeStep

tb.altitudeStep : Number

This get/set property receives and returns the size in meters of the step to use when an object is dragged vertically. By default this is set to 0.1 = 10cm.


defaultCursor

tb.defaultCursor : string

This get/set property receives and returns the value of the default cursor for the map canvas container this.getCanvasContainer().style.cursor, initally set to 'default'.


enableDraggingObjects

tb.enableDraggingObjects : Boolean

This get/set property receives and returns the value to enable the option to drag 3D Objects vertical or horizontally created with Threebox. This property requires tb.enableSelectingFeature is set to true.
When this property is true, and an object is selected, holding the [Shift] key + mouse click the object will be moved on its x-y axes (horizontally).
Holding the [Ctrl] key + mouse click the object will be moved on its z axis (vertically). This dragging actions fire ObjectDragged event when the object is dropped, that can be listened as follows:

obj.addEventListener('ObjectDragged', onDraggedObject, false)

This property doesn't affect to Mapbox fill-extrusion layers.


enableRotatingObjects

tb.enableRotatingObjects : Boolean

This get/set property receives and returns the value to enable the option to drag 3D Objects vertical or horizontally created with Threebox. This property requires tb.enableSelectingFeature is set to true.
When this property is true, and an object is selected, holding the [Alt] key + mouse click the object will be rotate pivoting over its anchor on z axis.
Holding the [Ctrl] key + mouse click the object will be moved on its z axis (vertically). This dragging actions fire ObjectDragged event when the object is dropped, that can be listened as follows:

obj.addEventListener('ObjectDragged', onDraggedObject, false)

This property doesn't affect to Mapbox fill-extrusion layers.


enableSelectingFeatures

tb.enableSelectingFeatures : Boolean

This get/set property receives and returns the value to enable the option to select features from fill-extrusion layers. This property doesn't affect to 3D objects.

This selection/unselection actions fire SelectedFeatureChange event when the object selected or unselected (explicitly or implicitly because of other feature is selected instead), and can be listened as follows:

obj.addEventListener('SelectedFeatureChange', onSelectedFeatureChange, false)

enableSelectingObjects

tb.enableSelectingObjects : Boolean

This get/set property receives and returns the value to enable the option to select 3D Objects created with Threebox.
This selection/unselection actions fire SelectedChange event when the object selected or unselected (explicitly or implicitly because of other object is selected instead), and can be listened as follows:

obj.addEventListener('SelectedChange', onSelectedChange, false)

This property doesn't affect to Mapbox fill-extrusion layers.


enableTooltips

tb.enableTooltips : Boolean

This get/set property receives and returns the value to enable the option to have tooltips (custom or by default) on objects. This property requires tb.enableSelectingFeature is set to true.
When this property is true, and an object is overed or selected, its tooltip will be shown.


fov

tb.fov : Number (degrees)

By default is ThreeboxConstants.FOV_DEGREES.
This get/set property sets and returns the value of the Field of View (FOV) used in the Camera. This value is only valid when tb.orthographic is false which implicitly means the camera being used is a THREE.PerspectiveCamera. When tb.orthographic is true, this value has no effect because the FOV for orthographic view is always 0.

IMPORTANT
This property accepts values between 0 and 60 (that's the maximum range of FOV by Mapbox), but below 2.5 degrees will generate serious issues with polygons in fill-extrusions and 3D meshes, and above 45 degrees will also produce clipping and performance issues that can freeze your map. Mapbox minimum value for the FOV cannot be 0, so if it receives a 0 value, it will be converted to 0.01 by Mapbox map.transform.fov property to it's minimum value.


gridStep

tb.gridStep : Number(integer)

This get/set property receives and returns the size in precision decimals of the step to use when an object is dragged horizontally reducing the number of decimals managed by Mapbox in its coords. By default the precision of this step is set to 6 decimals = 11.1 cm, setting this property to 7 the grid will be reduced to 1.1 cm.
Mapbox minimum value for the FOV is 0.01, so if it receives a 0 value, it will be converted to 0.01 by Mapbox map.transform.fov property to it's minimum value.


lights

tb.lights : Object

This get\set property receives and returns the full set of lights applied to the scene. tb.lights.ambientLight is initialized with an instance THREE.AmbientLight by tb.defaultLights() method, but can be overriden manually. tb.lights.dirLight could be initialized with an instance THREE.DirectionalLight by tb.defaultLights() or tb.setSunlight. It's not recommended to override this light is using realSunlight property. tb.lights.dirLightBack is initialized with an instance THREE.DirectionalLight by tb.defaultLights() method, but can be overriden manually. tb.lights.dirLightHelper is initialized with an instance THREE.DirectionalLightHelper by tb.setSunlight. I'll be visible only if realSunlightHelper is tru in Threebox constructor. tb.lights.hemiLight is initialized with an instance THREE.HemisphereLight by tb.setSunlight. tb.lights.pointLight is not initialized by default.


multiLayer

tb.multiLayer : Boolean

By default is false.
This get/set property receives and returns the value to enable the option to have multiple 3D layers, where a default layer will be created internally that will manage the tb.update calls Despite this value can be changed in runtime, the value won't take effect unless there's a style change through tb.setStyle. So if you know your page could have multiple 3D layers, it's recommended to initialize it to true in Threeboc constructor with the init param multiLayer: true.


orthographic

tb.orthographic : Boolean 

By default is false.
This get/set property sets and returns the value of the Camera to be used. When tb.orthographic is true, the camera being used will be an instance of THREE.OrthographicCamera.
If tb.orthographic is false, the camera being used will be an instance of THREE.PerspectiveCamera.

IMPORTANT
Pure orthographic view is not supported by Mapbox, as the minimum value for FOV is 0.01, so iftb.orthographic is true will generate serious issues with polygons and depth calculations with fill-extrusions. Don't set this property to true is you are creating fill-extrusion layers. If need to have at the same time fill-extrusions and 3D Objects at the same time but want to keep an orthographic-like camera, the recommendation is to use tb.orthographic = false and tb.fov = 2.5.


rotationStep

tb.rotationStep : Number

This get/set property receives and returns the size in degrees of the step to use when an object is dragged and rotated. By default this is set to 5.


sky

tb.sky: Boolean

By default is false. This property is set by the init param sky: true in threebox constructor. This get/set property sets and returns the option to have a built-in atmospheric layer initially set with the time and the map center position.
This layer is automatically updated if realSunlight is also true, but it can be updated separately through tb.updateSunSky(tb.getSunSky()) method call. If this property is set to false after the atmospheric sky layer is created, it will remove the layer.


terrain

tb.terrain: Boolean

By default is false. This property is set by the init param terrain: true in threebox constructor. This get/set property sets and returns the option to have a built-in terrain layer. This layer is automatically updated if realSunlight is also true, adjusting it's light but it can be updated separately through tb.updateSunGround(tb.getSunPosition()) method call. If this property is set to false after the terrain layer is created, it will remove the layer.


Objects

Threebox offers convenience functions to construct meshes of various Three.js meshes, as well as 3D models. 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

Dynamic objects

Extrusion

tb.extrusion(options);

Add a extruded shape to the map. Internally, calls THREE.ExtrudeBufferGeometry, and also to Object3D(options) to convert it in a dynamic object.

option required default type description
coordinates no [[[]]] or Vector2 array nested array Nested array following the standard of a geoJson feature.geometry.coordinates with type polygon, or a THREE.Vector2 array.
geometryOptions no {} Object Object that contains the options following ExtrudeGeometry
height no 100 Number Length of the extruded shape.
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.
scale no 1 number or {x, y, z} 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. scale attribute must be provided in number or per axis ((i.e. for an object transformed to 3 times higher than it's default size scale: {x: 1, y: 1, z: 3}
rotation no 0 number or {x, y, z} 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. rotate attribute must be provided in number or per axis ((i.e. for an object rotated 90 degrees over the x axis rotation: {x: 90, y: 0, z: 0}
materials no THREE.MeshPhongMaterial({ color: 0x660000, side: THREE.DoubleSide }) threeMaterial or threeMaterials array THREE material to use. Can be invoked with a text string, or a predefined material object via THREE itself.
anchor no bottom-left string This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top, bottom, left, right, center, top-left, top-right, bottom-left, bottom-right. Default value is bottom-left
adjustment no 1 {x, y, z} For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglaton 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level.
tooltip no false bool This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips
bbox no false bool This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects
raycasted no true bool This param allows to hide an object from raycast individually

Label

tb.label(options);

Creates a new HTML Label object that can be positioned through obj.setCoords(coords) and then added to Threebox scene through tb.add(obj). Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that will be associated to the obj.label property.

option required default type description
htmlElement yes null htmlElement HTMLElement that will be rendered as a CSS2DObject
cssClass no " label3D" string CssClass that will be aggregated to manage the styles of the label object.
alwaysVisible no false number Number of width and height segments. The higher the number, the smoother the sphere.
topMargin no -0.5 int If topMargin is defined in number, it will be added to it's vertical position in units, where 1 is the object height. By default a label will be positioned in the vertical middle of the object (topMargin: -0.5)
feature no null GeoJson feature GeoJson feature to assign to the tooltip. It'll be used for dynamic positioning

Object3D

tb.Object3D(options)

Add any geometry as THREE.Object3D or THREE.Mesh instantiated elsewhere in Three.js, to empower it with Threebox methods below. Unnecessary for 3d models instantiated with tb.loadObj above.

option required default type description
obj yes null THREE.Mesh Object to be enriched with this method adding new attributes.
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.
anchor no bottom-left string This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top, bottom, left, right, center, top-left, top-right, bottom-left, bottom-right. Default value is bottom-left
adjustment no 1 {x, y, z} For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglaton 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level.
tooltip no false bool This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips
bbox no false bool This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects
raycasted no true bool This param allows to hide an object from raycast individually

This method enriches the Object in the same way is done at 3D Models through tb.loadObj.


Sphere

tb.sphere(options);

Add a sphere to the map. Internally, calls THREE.Mesh with a THREE.SphereGeometry, and also to Object3D(options) to convert it in a dynamic object.

option required default type description
radius no 50 number Radius of sphere.
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.
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.
anchor no bottom-left string This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top, bottom, left, right, center, top-left, top-right, bottom-left, bottom-right. Default value is bottom-left
adjustment no 1 {x, y, z} For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglaton 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level.
tooltip no false bool This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips
bbox no false bool This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects
raycasted no true bool This param allows to hide an object from raycast individually

Tooltip

tb.tooltip(options);

Creates a new browser-like Tooltip object that can be positioned through obj.setCoords(coords) and then added to Threebox scene through tb.add(obj). Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that will be associated to the obj.tooltip property.

option required default type description
text yes "" string String that will be used to rendered as a CSS2DObject
cssClass no "toolTip text-xs" string CssClass that will be aggregated to manage the styles of the label object.
mapboxStyle no false int If mapboxStyle is true, it applies the same styles the Mapbox GL popups.
topMargin no 0 int If topMargin is defined in number, it will be added to it's vertical position in units, where 1 is the object height. By default a label will be positioned on top of the object (topMargin: 0)
feature no null GeoJson feature GeoJson feature to assign to the tooltip. It'll be used for dynamic positioning

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, and also to Object3D(options) to convert it in a dynamic object.

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
anchor no bottom-left string This param will position the pivotal center of the 3D models to the coords it's positioned. This could have the following values top, bottom, left, right, center, top-left, top-right, bottom-left, bottom-right. Default value is bottom-left
adjustment no 1 {x, y, z} For geometries the center is by default {0,0,0} position, this is the point to be used for location and for rotation. For perfect positioning and heigth from floor calculations this could be redefined in normalized units, adjustment param must be provided in units per axis (i.e. adjustment: {x: -0.5, y: -0.5, z: 0} , so the model will correct the center position of the object minus half of the x axis length and minus half of the y axis length ). If you position a cube created throuhg this method with by default center in a concrete lnglaton 0 height, half of the cube will be below the ground map level and the object will position at it's {x,y} center, so you can define adjustment: { x: -0.5, y: -0.5, z: 0.5 } to change the center to the bottom-left corner and that corner will be exactly in the lnglat position at the ground level.
tooltip no false bool This param allows to have or not a tooltip, by default is set with the value of tb.enableTooltips
bbox no false bool This param allows to have or not a bounding box, by default is set with the value of tb.enableSelectingObjects
raycasted no true bool This param allows to hide an object from raycast individually


Object methods

In all the samples below, the instance of the Threebox object will be always referred as obj


addCSS2D

obj.addCSS2D(element, objName [, center = obj.anchor, height = 0])

This is a generic method that uses the DOM HTMLElement received to paint it on screen in a relative position to the object that contains it. objName is needed to name the object and potentially to remove a previous one. center defines the position where the label will rendered, by default the object anchor obj.anchor. height defines this object position, where 0 is the object bottom and 1 is the object top, by default the bottom-center (0) of the object.

Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that is returned.


addHelp

obj.addHelp(helpText [,objName = helpName, mapboxStyle = false, center = obj.anchor, height = 0])

This method creates a browser-like help tooltip instance that is accessible through obj.help. This help tooltip is only visible when an object is being dragged for a translation, rotation or altitude change. If mapboxStyle is true, it applies the same styles the Mapbox GL popups. center defines the position where the label will rendered, by default the object anchor obj.anchor. height defines this object position, where 0 is the object bottom and 1 is the object top, by default the bottom-center (0) of the object.

Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that will be associated to the obj.help property. Internally this method calls objects.prototype.drawTooltip to create the needed HTML to wrap up the HTMLElement received by param. Internally this method calls obj.addCSS2D.


addLabel

obj.addLabel(HTMLElement [, visible, center = obj.anchor, height = 0.5])

It uses the DOM HTMLElement received to paint it on screen in a relative position to the object that contains it. If visible is true, the label will be always visible, otherwise by default its value is false and it's regular behavior is only to be shown on MouseOver. center defines the position where the label will rendered, by default the object anchor obj.anchor. height defines this object position, where 0 is the object bottom and 1 is the object top, by default the middle-center (0.5) of the object.

Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that will be associated to the obj.label property. Internally this method calls obj.drawLabelHTML to create the needed HTML to wrap up the HTMLElement received by param.


addTooltip

obj.addTooltip(tooltipText [, mapboxStyle = false, center = obj.anchor, custom = true, height = 1])

This method creates a browser-like tooltip for the object using the tooltipText. If mapboxStyle is true, it applies the same styles the Mapbox GL popups. center defines the position where the label will rendered, by default the object anchor obj.anchor. custom is always true for explicitly added tooltips by the user, unless the tooltip is automatically generated by Threebox. height defines this object position, where 0 is the object bottom and 1 is the object top, by default the top-center (1) of the object.

Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that will be associated to the obj.tooptip property. Internally this method calls obj.addHelp.


copyAnchor

obj.copyAnchor(anchor)

Copies the anchor properties, internally used in obj.duplicate.


drawBoundingBox

obj.drawBoundingBox

This method creates two bounding boxes using THREE.Box3Helper The first bounding box will be assigned to obj.boundingBox property and the second will be assigned to obj.boundingBoxShadow.


drawLabelHTML

obj.drawLabelHTML(HTMLElement [, visible = false, center = obj.anchor])

It uses the DOM HTMLElement received to paint it on screen in a relative position to the object that contains it. If visible is true, the label will be always visible, otherwise by default its value is false and it's regular behavior is only to be shown on MouseOver. center defines the object center of position and rotation that in 3D objects is defined through options.adjustment param. As the label is calculated based on the center of the object, this value will change the position of the object. Its position is always relative to the object that contains it and rerendered whenever that label is visible. Internally this method uses a CSS2DObject rendered by THREE.CSS2DRenderer to create an instance of THREE.CSS2DObject that will be associated to the obj.label property.


duplicate

obj.duplicate()

Returns a clone of the object. Improves around a 95% the performance when handling many identical objects, by reusing materials and geometries.


removeCSS2D

obj.removeCSS2D(objName)

Removes the instance of CSS2DObject by objName and dispose its resources.


removeHelp

obj.removeHelp()

Removes the instance of CSS2DObject stored in obj.help. Internally it calls obj.removeCSS2D method.


removeLabel

obj.removeLabel()

Removes the instance of CSS2DObject stored in obj.label. Internally it calls obj.removeCSS2D method.


removeTooltip

obj.removeTooltip()

Removes the instance of CSS2DObject stored in obj.tooltip. Internally it calls obj.removeCSS2D method.


set

obj.set(options)

Broad method to update object's position, rotation, and scale in only one call. Internally it calls to obj._setObject(options) method. This method can also be used to animate an object if options.duration has a value. Check out the Threebox Types section below for details.

options object on animations (duration > 0)

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
duration no 1000 number Duration of the animation, in milliseconds to complete the values specified in the other properties scale, rotation and coords. If 0 or undefined it will apply the values to the object directly with no animation.

options object without animations (duration == 0)

option required default type description
position 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
worldCoordinates no NA Vector3 Duration of the animation, in milliseconds to complete the values specified in the other properties scale, rotation and coords. If 0 or undefined it will apply the values to the object directly with no animation.
quaternion no NA [Vector3, radians] Rotation(s) to set to the axes received by the Vector3 and in by the angle in radians
translate no NA lnglat Increment to the coords position to translate the object.
worldTranslate no NA Vector3 Increment to the object world position to translate the object.

setAnchor

obj.setAnchor(anchor)

Sets the positional and pivotal anchor automatically from string param. Calculates dynamically the positional and pivotal anchor. anchor is a string value that could have the following values: top, bottom, left, right, center, top-left, top-right, bottom-left, bottom-right. Default value is bottom-left for precison on positioning


setBoundingBoxShadowFloor

obj.setBoundingBoxShadowFloor()

This method is called from obj.setCoords every time an object receives new coords to position obj.boundingBoxShadow at the height of the floor. So in this way if an object changes it's height the shadow box always projects over the floor and it's easier to visualize, position and rotate dragging it.


setCoords

obj.setCoords(lnglat)

Positions the object at the defined lnglat coordinates, and resizes it appropriately if it was instantiated with units: "meters". Can be called before adding object to the map.


setFixedZoom

obj.setFixedZoom(scale)

Sets the scale used to convert the object based on fixedZoom value. The received param scale should be always equal to map.transform.scale. This method is called from obj.setScale and other loading methods, so it's not needed to be called separately from the UI.


setObjectScale

obj.setObjectScale(scale)

Sets the scale used to convert the object considering object current obj.unitsPerMeter and depending the object is in units scene or meters.
The received param scale should be always equal to map.transform.scale.
This method calls internally obj.setScale(scale), obj.setBoundingBoxShadowFloor(), obj.setReceiveShadowFloor() sequentially.


setRotation

obj.setRotation(xyz)

Rotates the object over its defined center in the 3 axes, the value must be provided in degrees and could be a number (it will apply the rotation to the 3 axes) or as an {x, y, z} object. This rotation is applied on top of the rotation provided through loadObj(options).


setRotationAxis

obj.setRotationAxis(xyz)

Rotates the object over one of its bottom corners on z axis, the value must be provided in degrees and could be a number (it will apply the rotation to the 3 axes) or as an {x, y, z} object. This rotation is applied on top of the rotation provided through loadObj(options).


setScale

obj.setScale(scale)

Sets the scale used to convert the object considering object current obj.unitsPerMeter and depending the object is in units scene or meters.
The received param scale should be always equal to map.transform.scale, if it's null, obj.userData.mapScale will be use instead.
This method calls internally obj.setFixedZoom.


setTranslate

obj.setTranslate(lnglat)

Movesthe object from it's current position adding the lnglat coordinates recibed. Don't confuse this method with obj.setCoords This method must be called after adding object to the map.


Object properties

In all the samples below, the instance of the Threebox object will be always referred as obj.


boundingBox

obj.boundingBox : THREE.Box3Helper

This get/set property receives and returns a THREE.Box3Helper which contains the object in it's initial size. boundingBox represents is visible once the object is on MouseOver (yellow) or Selected (green).

By Threebox design .boundingBox is hidden for THREE.Raycaster even when it's visible for the camera.

TODO: In next versions of Threebox, this object material will be configurable. In this versión still predefined in Objects.prototype


boundingBoxShadow

obj.boundingBoxShadow : THREE.Box3Helper

This get/set property receives and returns a THREE.Box3Helper which contains the object in it's initial size but 0 height and projected to the floor of the map independently of its heigh position, so it acts as a shadow of the shape. boundingBoxShadow represents is visible once the object is on MouseOver or Selected in black color.

By Threebox design .boundingBoxShadow is hidden for THREE.Raycaster even when it's visible for the camera.

TODO: In next versions of Threebox, this object material will be configurable. In this versión still predefined in Objects.prototype


castShadow

obj.castShadow : boolean

This get/set property receives and returns the value of the option of objects to cast a shadow. It creates a plane with a THREE.PlaneBufferGeometry and a THREE.ShadowMaterial() centered on the object to project the shadow with the size of the longest dimension (x, y, z) size of the object and make it 10 times bigger to be able to hold the full shadow.


color

obj.color : integer hex 

This get/set property receives and returns the value of the color from a hexadecimal value. This method calls color.setHex


help

obj.help : CSS2DObject

This get property returns a CSS2DObjectTHREE.CSS2DObject value that represents the help tooltip of a THREE.Object3D created by obj.addHelp method, where the value of a rotation, translation or altitude change is shown while dragging. Despite this is accessible, this is an internal object only visible on drag&drop actions over an object.


hidden

obj.hidden : boolean

This get/set property receives and returns the value of the hidden status of an object. This property overrides the value of obj.visibility.


fixedZoom

obj.fixedZoom : Number

This get/set property receives and returns the value for the zoom below the one the object will have a fixed scale at any zoom level. Over the value, the object will rescale as always. This property is very useful for models that need to be visible on very low zoom levels (i.e. an airplane describing a world route), but they also need to be visible when zoom is higher.
It's important to know that fixedZoom will use the model in scene units, not in meters.


label

obj.label : CSS2DObject

This get property returns a CSS2DObjectTHREE.CSS2DObject value that represents the label of a THREE.Object3D created by obj.addLabel method. The label could be used as an element to show on mouse over or to be always visible. It's normally used to show attributes or status of a threebox object and can contain any HTMLElement.


modelHeight

obj.modelHeight : Number

This get property returns the height of the object in meters.


raycasted

obj.raycasted : boolean

This get/set property receives and returns a boolean value to hide a THREE.Object3D from THREE.Raycaster if false. By default all the objects are visible for raycaster. This value can be initialized by default through tb.loadObj or tb.Object3D.


receiveShadow

obj.receiveShadow : boolean

This get/set property receives and returns the value of the option of objects to receive a shadow.


tooltip

obj.tooltip : CSS2DObject

This get property returns a CSS2DObjectTHREE.CSS2DObject value that represents the tooltip of a THREE.Object3D created by obj.addTooltip method. The tooltip by default shows the uuid value of a threebox object and it's only visible if tb.enableTooltips is true.


unitsPerMeter

obj.unitsPerMeter : Number

This get property returns the conversion value of units per meter at the object current latitude.


visibility

obj.visibility : boolean

This get/set property receives and returns a boolean value to override the property visible of a THREE.Object3D, adding also the same visibility value for obj.label and obj.tooltip This property is overriden by obj.hidden, so if obj.hidden is false, obj.visibility is ignored. By Threebox design .boundingBoxShadow is hidden for THREE.Raycaster even when it's visible for the camera.


wireframe

obj.wireframe : boolean

This get/set property receives and returns a boolean value to convert an THREE.Object3D in wireframes or texture it.

By Threebox design whenever an object is converted to wireframes, it's also hidden for THREE.Raycaster even when it's visible for the camera.



Object events

In all the samples below, the instance of the Threebox object will be always referred as obj


IsPlayingChanged

obj.addEventListener('IsPlayingChanged', onIsPlayingChanged, false)

This event is fired once an object changes its animation playing status, it means it will be fired both when an object animation starts and stops to play. The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail.

map.addLayer({
	...
	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('IsPlayingChanged', onIsPlayingChanged, false);

		tb.add(soldier);
	})

	...
});
...
function onIsPlayingChanged(eventArgs) {
	if (e.detail.isPlaying) {
		//do something in the UI such as changing a button state
	}
	else {
		//do something in the UI such as changing a button state
	}
}

ObjectChanged

obj.addEventListener('ObjectChanged', onObjectChanged, false)

This event is fired when an object is changed by any method, including animations.
The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail, and the action made to the object that cound be one or more of the following:

  • position: defined as lnglat + alt coords (i.e. [-122.43471544901193, 37.73719686062993, 0]), undefined if the change doesn't affect position.
  • rotation: defined as radians in Vector3 format (i.e. {x: 0, y: 0, z: -3.026900303641103}), undefined if the change doesn't affect rotation.
  • scale: defined as a Vector3 (i.e. {x: 1, y: 1, z: 1}), , undefined if the change doesn't affect scale.
map.addLayer({
	...
	tb.loadObj(options, function (model) {
		model.setCoords(origin);
		model.addEventListener('ObjectChanged', onObjectChanged, false);
		tb.add(model);
	})

	...
});
...
function onObjectChanged(e) {
	let object = e.detail.object; // the object that has changed
	let action = e.detail.action; // the action that defines the change
	//do something in the UI such as changing a button state or updating the new position and rotation
}

ObjectDragged

obj.addEventListener('ObjectDragged', onDraggedObject, false)

This event is fired when an object changes is dragged and dropped in a different position, and only once when map.once('mouseup' and map.once('mouseout'. The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail, and the action made during the dragging that cound be "rotate" if the object has been rotated on its center axis or "translate"/"altitude" if the object has been moved to other position .

map.addLayer({
	...
	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('ObjectDragged', onDraggedObject, false);

		tb.add(soldier);
	})

	...
});
...
function onDraggedObject(e) {
	let draggedObject = e.detail.draggedObject; // the object dragged
	let draggedAction = e.detail.draggedAction; // the action during dragging

	//do something in the UI such as changing a button state or updating the new position and rotation
}

ObjectMouseOver

obj.addEventListener('ObjectMouseOver', onObjectMouseOver, false)

This event is fired when an object is overed by the mouse pointer.
The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail.

map.addLayer({
	...
	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('ObjectMouseOver', onObjectMouseOver, false);

		tb.add(soldier);
	})

	...
});
...
function onObjectMouseOver(e) {
	//do something in the UI such as adding help or showing this object attributes
}

ObjectMouseOut

obj.addEventListener('ObjectMouseOut', onObjectMouseOut, false)

This event is fired when the mouse pointer leaves an object that has been overed.
The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail.

map.addLayer({
	...
	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('ObjectMouseOut', onObjectMouseOut, false);

		tb.add(soldier);
	})

	...
});
...
function onObjectMouseOut(e) {
	//do something in the UI such as removing help
}

SelectedChange

obj.addEventListener('SelectedChange', onSelectedChange, false)

This event is fired once an object changes its selection status, it means it will be fired both when an object is selected or unselected. The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail.

map.addLayer({
	...
	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('SelectedChange', onSelectedChange, false);

		tb.add(soldier);
	})

	...
});
...
function onSelectedChange(e) {
	let selectedObject = e.detail; //we get the object selected/unselected
	let selectedValue = selectedObject.selected; //we get if the object is selected after the event
}

SelectedFeature

map.on('SelectedFeature', onSelectedFeature)

This event is fired by Threebox usign the same pattern of mapbox the feature-state select and hover TODO once an object changes its selection status, it means it will be fired both when an object is selected or unselected. The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail.

map.addLayer({
	'id': 'room-extrusion',
	'type': 'fill-extrusion',
	'source': 'floorplan',
	'paint': {
	// See the Mapbox Style Specification for details on data expressions.
	// https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions
 
	// Get the fill-extrusion-color from the source 'color' property.
	'fill-extrusion-color':
		[
			'case',
			['boolean', ['feature-state', 'select'], false],
			'#ffff00',
			['boolean', ['feature-state', 'hover'], false],
			'#0000ff',
			['get', 'color']
		],
 
	// Get fill-extrusion-height from the source 'height' property.
	'fill-extrusion-height': ['get', 'height'],
 
	// Get fill-extrusion-base from the source 'base_height' property.
	'fill-extrusion-base': ['get', 'base_height'],
 
	// Make extrusions slightly opaque for see through indoor walls.
	'fill-extrusion-opacity': 0.5
}
});
//selected extrusion feature event
map.on('SelectedFeature', onSelectedFeature);
...
function onSelectedFeature(e) {
	let selectedObject = e.detail; //we get the object selected/unselected
	let selectedValue = selectedObject.selected; //we get if the object is selected after the event
}

Wireframed

obj.addEventListener('Wireframed', onWireframed, false)

This event is fired once an object is changes its wireframe status, it means it will be fired both when an object is wireframed or textured again. The event can be listened at any time once the tb.loadObj callback method is being executed. An instance of the object that changes is returned in eventArgs.detail.

map.addLayer({
	...
	tb.loadObj(options, function (model) {

		soldier = model.setCoords(origin);

		soldier.addEventListener('Wireframed', onWireframed, false);

		tb.add(soldier);
	})

	...
});
...
function onWireframed(e) {
	if (e.detail.wireframe) {
		//do something in the UI such as changing a button state
	}
	else {
		//do something in the UI such as changing a button state
	}
}


Object animations

playDefault

obj.playDefault(options)

Plays the default embedded animation of a loaded 3D model.

options object

option required default type description
duration no 1000 number Duration of the animation, in milliseconds
speed no 1 number This value changes the obj.mixer.timeScale of the animation being played where 1 is the default duration of the animation, < 1 will mathe the animation slower and > 1 will make the animation faster

playAnimation

obj.playAnimation(options)

Plays one of the embedded animations of a loaded 3D model. The animation index must be set in the attribute options.animation

options object

option required default type description
animation yes NA number Index of the animation in the 3D model. If you need to check whats the index of the animation you can get the full array using obj.animations.
duration no 1000 number Duration of the animation, in milliseconds
speed no 1 number This value changes the obj.mixer.timeScale of the animation being played where 1 is the default duration of the animation, < 1 will mathe the animation slower and > 1 will make the animation faster

followPath

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

stop

obj.stop()

Stops all of object's current animations.



Threebox types

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.



Performance considerations

  • Use obj.duplicate() when adding many identical objects. If your object contains other objects not in the obj.children collection, then those objects need to be cloned too.
  • This is a by default behavior when tb.loadObj is called.