Coordinate issue with Threejs + mapbox. It should be an easy task, but I can't

I am struggling with the position of multiple boxgeometry instances with instancedMesh on a mapbox/maplibre map.

Goal: Adding several geometry instances each with specific xyz or lat-long coordinates (I have both coordinates for each instance). The mapbox customlayer shall have coordinates at 0,0,0, to manage each instance position through the .setPosition(x,y,z) of the instancedMesh matrix4().

Problem: the latlong coordinates of each 3d geometries are not valid for feeding the Three’s matrix4 transformation through setPosition(), as mapbox and threejs talk different units, so there must be a conversion formula to get latlong coordinates into the matrix4() setPosition() inside a for loop.

Note that I am dealing with several boxgeometry instances. No gltf 3D models involved.

Appreciate any heads-up on this.

From stackoverflow:

const model = mapboxgl.MercatorCoordinate.fromLngLat([-120, 40], modelAltitude);

point.position.set(model.x, model.y, 0);

this.scene.add(point);
2 Likes

Hi @manthrax
I am afraid that seems only for adding single entities to the map, not instances.

Based on each instance’s coordinates, I look for a solution to place multiple instances of instancedMesh on the map. Here’s an example (see matrix.setPosition( … )):

 maplayer.content = {
                id: maplayer.name,
                type: 'custom',
                renderingMode: '3d',
                onAdd (map, gl) {
                    this.camera = new THREE.Camera();
                    this.scene = new THREE.Scene();
                    // create two three.js lights to illuminate the model 
                    const directionalLight = new THREE.DirectionalLight(0xffffff);
                    directionalLight.position.set(0, -70, 100).normalize();
                    this.scene.add(directionalLight); 
                    // Define instance geometry.
                    const geometry = new THREE.BoxGeometry( 50, 50, 50)
                    // Define instance material.
                    const material = new THREE.MeshBasicMaterial();
                    // Wrap the geometry, the material and the number of instances into a mesh.
                    const mesh = new THREE.InstancedMesh( geometry, material, data.length );
                    // Create a matrix4 to manage instance transformations.    
                    const matrix = new THREE.Matrix4();
                    // Keep the colour for each instance as a separate array for later manipulation.
                    const array_rgb = [];
                    // Iterate each data entry.
                    for ( let x = 0; x < data.length; x ++ ) {
                        matrix.setPosition(
                            X-WHICH-COORDS-HERE? MERCATOR? METERS? DEGREES? RELATIVE TO ITS PARENT AT x0y0z0,
                            Y-WHICH-COORDS-HERE? MERCATOR? METERS? DEGREES? RELATIVE TO ITS PARENT AT x0y0z0,
                            Z-JUST ALTITUDE IN METERS,
                        ) 
                        mesh.setMatrixAt( x, matrix );
                        mesh.setColorAt( x, array_rgb[x] );
                    }
                    // Add the mesh to the map scene.
                    this.scene.add( mesh );          
                    // Not sure what this means.
                    this.map = map;
                    // use the MapLibre GL JS map canvas for three.js
                    this.renderer = new THREE.WebGLRenderer({
                        canvas: map.getCanvas(),
                        context: gl,
                        antialias: true
                    });
                    // Not sure what this means.
                    this.renderer.autoClear = false;
                    // Raycaster methods.
                    this.raycaster = new THREE.Raycaster();
                    this.raycaster.near = -1;
                    this.raycaster.far = 1e6;
                },
                render (gl, matrix) {
                    ....
                }
        };