jscastro76 / threebox

A Three.js plugin for Mapbox GL JS, with support for animations and advanced 3D rendering.
Other
549 stars 145 forks source link

Labels visibility according to distance to camera #409

Closed NataliaDSmirnova closed 11 months ago

NataliaDSmirnova commented 11 months ago

Threebox version: 2.2.7

Question

Hello! Thank you for the plugin, it's great 😊

I'm interested in a way of visualizing labels according to their distances to the camera. I tried to transform objects' world positions into camera space аnd measure distance there, but after zooming and panning of map distance differs while objects have the same visual size.

Maybe I missed some space transitions. Could you advice how the distance can be calculated?

jscastro76 commented 11 months ago

For that you will need CSS3D objects. The current labels are implemented based on CSS2D objects. That feature is out of scope but maybe you can fork it to implement it just replacing CSS2D objects by CSS3D objects

NataliaDSmirnova commented 11 months ago

For that you will need CSS3D objects. The current labels are implemented based on CSS2D objects. That feature is out of scope but maybe you can fork it to implement it just replacing CSS2D objects by CSS3D objects

Thank you for the answer 😊 I added the type of labels using the current threebox-plugin version. For someone who may be interested, the main idea is below :

  1. Add a function to calculate the actual distance to the camera in the local space of object3D
    const tempVector3 = new THREE.Vector3();
    const distanceFromCamera = (object3D, tb) => {
    tempVector3.setFromMatrixPosition(tb.camera.matrixWorld);
    const targetInLocalSpace = object3D.worldToLocal(tempVector3);
    const distance = targetInLocalSpace.length();
    return distance;
    };
  2. Call the update label function for the object3D before every tb.update() (be sure every object3D before the call has actual worldMatrix.
    const updateLabel = (object3D, label, tb) => {
    const distance = distanceFromCamera(object3D, tb);
    if (distance < LABEL_CAMERA_DISTANCE) {
        if (!object3D.scaleGroup.getObjectByName('label')) {
                      object3D.addLabel(...);
        }
    } else {
        object3D.removeLabel();
    }
    };
jscastro76 commented 11 months ago

That's great to hear you found a way to implement it without CSS3D just manipulating the current ones. If you can create an example with it and send me a PR, I'll be glad to add it to the plugin and adding you as official collaborator @NataliaDSmirnova

NataliaDSmirnova commented 11 months ago

That's great to hear you found a way to implement it without CSS3D just manipulating the current ones. If you can create an example with it and send me a PR, I'll be glad to add it to the plugin and adding you as official collaborator @NataliaDSmirnova

Sure, it'll take some time, but I'm going to do that.