3D Model

The example shows you how to render a 3D model to the map.

Demo

Plain HTML

You can find the live Demo on CodeSandbox here.

1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
<meta name="viewport" content="initial-scale=1.0" />
5
<meta charset="UTF-8" />
6
<title>Basic Map</title>
7
<link
8
href="https://maps-gl.nextbillion.io/maps/v2/api/css"
9
rel="stylesheet"
10
/>
11
<style>
12
* {
13
margin: 0;
14
padding: 0;
15
}
16
#map {
17
width: 100vw;
18
height: 100vh;
19
}
20
</style>
21
</head>
22
<body>
23
<div id="map"></div>
24
<script src="https://unpkg.com/[email protected]/build/three.min.js"></script>
25
<script src="https://unpkg.com/[email protected]/examples/js/loaders/GLTFLoader.js"></script>
26
<script src="https://maps-gl.nextbillion.io/maps/v2/api/js"></script>
27
<script>
28
// You need to replace the apiKey with yours
29
nextbillion.setApiKey("your-api-key");
30
var nbmap = new nextbillion.maps.Map({
31
container: document.getElementById("map"),
32
style: "https://api.nextbillion.io/maps/streets/style.json",
33
zoom: 20,
34
pitch: 52,
35
center: { lat: 34.08572, lng: -118.324569 }
36
});
37
38
// parameters to ensure the model is georeferenced correctly on the map
39
var modelOrigin = [-118.324424, 34.08572];
40
var modelAltitude = 0;
41
var modelRotate = [Math.PI / 2, 0, 0];
42
43
var modelAsMercatorCoordinate = nextbillion.maps.MercatorCoordinate.fromLngLat(
44
modelOrigin,
45
modelAltitude
46
);
47
48
// transformation parameters to position, rotate and scale the 3D model onto the map
49
var modelTransform = {
50
translateX: modelAsMercatorCoordinate.x,
51
translateY: modelAsMercatorCoordinate.y,
52
translateZ: modelAsMercatorCoordinate.z,
53
rotateX: modelRotate[0],
54
rotateY: modelRotate[1],
55
rotateZ: modelRotate[2],
56
/* Since our 3D model is in real world meters, a scale transform needs to be
57
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
58
*/
59
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
60
};
61
62
var THREE = window.THREE;
63
64
// configuration of the custom layer for a 3D model per the CustomLayerInterface
65
var customLayer = {
66
id: "3d-model",
67
type: "custom",
68
renderingMode: "3d",
69
onAdd: function (map, gl) {
70
this.camera = new THREE.Camera();
71
this.scene = new THREE.Scene();
72
73
// create two three.js lights to illuminate the model
74
var directionalLight = new THREE.DirectionalLight(0xffffff);
75
directionalLight.position.set(0, -70, 100).normalize();
76
this.scene.add(directionalLight);
77
78
var directionalLight2 = new THREE.DirectionalLight(0xffffff);
79
directionalLight2.position.set(0, 70, 100).normalize();
80
this.scene.add(directionalLight2);
81
82
// use the three.js GLTF loader to add the 3D model to the three.js scene
83
var loader = new THREE.GLTFLoader();
84
loader.load(
85
"https://static.nextbillion.io/docs-next/3d-model-demo.gltf",
86
function (gltf) {
87
this.scene.add(gltf.scene);
88
}.bind(this)
89
);
90
this.map = map;
91
92
// use the MapLibre GL JS map canvas for three.js
93
this.renderer = new THREE.WebGLRenderer({
94
canvas: map.getCanvas(),
95
context: gl,
96
antialias: true
97
});
98
99
this.renderer.autoClear = false;
100
},
101
render: function (gl, matrix) {
102
var rotationX = new THREE.Matrix4().makeRotationAxis(
103
new THREE.Vector3(1, 0, 0),
104
modelTransform.rotateX
105
);
106
var rotationY = new THREE.Matrix4().makeRotationAxis(
107
new THREE.Vector3(0, 1, 0),
108
modelTransform.rotateY
109
);
110
var rotationZ = new THREE.Matrix4().makeRotationAxis(
111
new THREE.Vector3(0, 0, 1),
112
modelTransform.rotateZ
113
);
114
115
var m = new THREE.Matrix4().fromArray(matrix);
116
var l = new THREE.Matrix4()
117
.makeTranslation(
118
modelTransform.translateX,
119
modelTransform.translateY,
120
modelTransform.translateZ
121
)
122
.scale(
123
new THREE.Vector3(
124
modelTransform.scale,
125
-modelTransform.scale,
126
modelTransform.scale
127
)
128
)
129
.multiply(rotationX)
130
.multiply(rotationY)
131
.multiply(rotationZ);
132
133
this.camera.projectionMatrix = m.multiply(l);
134
this.renderer.state.reset();
135
this.renderer.render(this.scene, this.camera);
136
this.map.triggerRepaint();
137
}
138
};
139
140
nbmap.on("style.load", function () {
141
nbmap.map.addLayer(customLayer);
142
});
143
</script>
144
</body>
145
</html>
146

© 2024 NextBillion.ai all rights reserved.