I used adding gltf 3D Model on map using mapbox gl with three.js from the link
but adding single 3D gltf model in single separate layer and adding them to map is working fine,but is there any way to add mulitple 3D gltf model in a single layer on the map.
Map code:
this.modelOrigin = [148.9819, -35.3981];
this.modelOrigin2 = [148.9819, -35.4981];
this.iconImage = "https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf";
//map info here
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v9', //stylesheet location
center: [148.9819, -35.3981], // starting position[35.890, -75.664]
zoom: 17.5, // starting zoom
hash: true,
minZoom: 0,
maxZoom: 22,
preserveDrawingBuffer: true,
pitch: 60
});
var self = this;
map.on('style.load', function () {
//adding separate 3d model on map
map.addLayer(new AddMapCustomLayer(self.modelOrigin, self.iconImage));
map.addLayer(new AddMapCustomLayer(self.modelOrigin2, self.iconImage));
});
code for the custom Layer:
class AddMapCustomLayer {
id;
type="custom";
renderingMode="3d";
//
modelOrigin;
modelAltitude = 0;
modelRotate = [Math.PI / 2, 0, 0];
modelScale = 5.41843220338983e-8;
modelTransform;
camera;
scene;
map;
renderer;
iconImage;
constructor(modelOrigin, iconImage) {
this.id = '3d-model' + this.uuidv4();
this.type = 'custom';
this.renderingMode = '3d';
this.modelOrigin = modelOrigin;
this.iconImage = iconImage;
// transformation parameters to position, rotate and scale the 3D model onto the map
this.modelTransformation(this.modelOrigin,this.iconImage)
}
modelTransformation(modelOrigin,modelAltitude){
this.modelTransform = {
translateX: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).x,
translateY: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).y,
translateZ: mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude).z,
rotateX: this.modelRotate[0],
rotateY: this.modelRotate[1],
rotateZ: this.modelRotate[2],
scale: this.modelScale
};
}
uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
onAdd(map, gl) {
this.camera = new THREE.Camera();
this.scene = new THREE.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);
// use the three.js GLTF loader to add the 3D model to the three.js scene
var loader = new THREE.GLTFLoader();
loader.load(this.iconImage, (function (gltf) {
this.scene.add(gltf.scene);
}).bind(this));
this.map = map;
// use the Mapbox GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl
});
this.renderer.autoClear = false;
}
render(gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), this.modelTransform.rotateX);
var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), this.modelTransform.rotateY);
var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), this.modelTransform.rotateZ);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4().makeTranslation(this.modelTransform.translateX, this.modelTransform.translateY, this.modelTransform.translateZ)
.scale(new THREE.Vector3(this.modelTransform.scale, -this.modelTransform.scale, this.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();
}
So Please give suggestion, how i can achive adding same model dyanmically at different different location on the map by single layer.
this question is quite old, but I would recommend you to check out the latest version of threebox as it enables you to add as many models and 3D layers as you want but also to do things like these below with only a few lines of code
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();
}
});
})
- 3D models built-in and custom animations
- Full raycast support MouseOver/Mouseout, Selected, Drag&Drop, Drag&Rotate, Wireframe
- CSS2D Tooltips and Labels that consider altitude
**- Three.js and Mapbox cameras sync with depth adjustment **
- Include geolocated models of monuments
If the models are close to one-another, have you tried loading two glTF models and adding them to the same THREE.Scene() ?
ie. this.scene.add(gltf1.scene); this.scene.add(gltf2.scene);
you would still need to calculate the offset / rotation of gltf2, relative to gltf1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With