I am trying to visualise a three.js scene in Mapbox, using an approach based on this tutorial: https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/
I have a prepared scene named "threescene", which I added to the scene of the custom layer. It contains geometries of buildings. The coordinates are in WGS84, and it seems like they would be transformed properly in the tutorial code.
However, the layer simply does not show up. I don't know if I should do something else with the coordinates, or if there is another problem. I have already attempted to normalise the coordinates within the scene.
My code is as follows:
mapboxgl.accessToken = 'pk.eyJ1IjoiamxpZW1wdCIsImEiOiJjanpzZHNhOGwxZ3RjM2JuenBpcjN4eTh3In0.dnO_1v0NDfRMZBhv-hVvjQ';
var map = window.map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 18,
center: [6.8309373573, 53.0475174735], // min of bbox
pitch: 60,
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
});
// parameters to ensure the model is georeferenced correctly on the map
var modelOrigin = [6.8309373573, 53.0475174735]; // min of bbox
var modelAltitude = 0;
var modelRotate = [Math.PI / 2, 0, 0];
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude);
// transformation parameters to position, rotate and scale the 3D model onto the map
var modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};
var THREE = window.THREE;
// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
id: '3d-model',
type: 'custom',
renderingMode: '3d',
onAdd: function(map, gl) {
this.camera = new THREE.Camera();
this.scene = new THREE.Scene();
this.scene.add(threescene); // here I include my scene
// create two three.js lights to illuminate the model
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(0, -70, 100).normalize();
this.scene.add(directionalLight);
var directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(0, 70, 100).normalize();
this.scene.add(directionalLight2);
this.map = map;
// use the Mapbox GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
},
render: function(gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX);
var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY);
var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4().makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ)
.scale(new THREE.Vector3(modelTransform.scale, -modelTransform.scale, modelTransform.scale))
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix.elements = matrix;
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
};
map.on('style.load', function() {
map.addLayer(customLayer, 'waterway-label');
});