Working with threejs and Mapbox GL

Hi,
wanted to ask what is the best way to combine Mapbox GL with threejs. I’m developing in threejs some CAD tools, basically dragging and resizing with the mouse some polyhedrons. As possible approaches, I wonder myself if it would be better to just import Mapbox in a kind of texture type into my threejs scene and stay working with pure threejs; or another alternatives I can think of would be through a costume layer in Mapbox?

Additionally, in the case of a costume layer in Mapbox, the event listeners for mouse moving and clicking developed in threejs, how can they be implemented with the mapbox, should I re-write them in Mapbox as “map.on(‘mousemove’, e => { }” and (in this particular example) internally call the function already programmed in threejs for when the mousemoves?

Any advise would be highly appreciated, thanks!

FMU mapbox is going to handle the map texture processing in the best way it can as its designed to do, it already has logic to decipher when and where map chunks should be loaded which will save you a headache sorting out in three, I’d personally suggest embedding your three js on a costume layer in mapbox.

Yes you can use this type of pattern…

let mousePos
const screenPos = new THREE.Vector2();
let wid = map.getCanvas().width
let hig = map.getCanvas().height

map.on('mousemove', e => {
   mousePos = e.point;
   screenPos.set((mousePos.x / wid) * 2 - 1, -(mousePos.y / hig) * 2 + 1);
   cube.position.set(screenPos.x, screenPos.y, 0);
   CallAnotherThreeJsMouseFunction() 
});

Great, thanks for the reply! some further questions…

How can the threejs control add-on’s be implemented. Would like turn off the Mapbox camera controls, and use the OribitControls and the TransformControls from threejs.

On my first try, while implementing the TransformControls, I get an error message “.getInverse() can’t invert matrix, determinant is 0”. I configure the TransformControls like this:

async onAdd(map, gl) { 
      some lines for camera, object, scene configuration
      ...
      controls = new TransformControls(camera, renderer.domElement);
      controls.size = 500;
      controls.attach(object);
      scene.add(controls);
}

Further, would the use of React or Vue.js be convenient for the handling of events between Mapbox gl and threejs?

I’m guessing the error comes from the following line?

controls.attach(object);

It may be worth you setting up a live example on codepen or codesandbox, the error could be a number of things, what is the object you’re attaching, how was it built, has your attached object been scaled to 0 before the attach?

As for using Vue and react with both of the libraries im not entirely sure, it may be a question for mapbox / Vue / r3f community, someone here may have used these libs together with a framework before…

Yes its exactly at that line controls.attach(object) Here the codepen https://codepen.io/eAmur/pen/mdGNLPw

the following line seems to be incorrect…

this.ball.translate = new THREE.Vector3(30,30,30);

this should probably be…

this.ball.position.set(30,30,30);

here’s an updated pen that adds the transform controls…

the problem here is that mapbox needs to heavily modify the projectionMatrix of the camera which TransformControls rely on internally for calculating both the scale of the gizmo as well as raycast the _gizmo.picker to detect when the control is intersected in screen space…

you can see this SO answer on how the raycaster could be calculated but i’m not sure how you’d internally set the raycaster within TransformControls from this mapbox gl js - Raycast in Three.js with only a projection matrix - Stack Overflow

1 Like