vasturiano / globe.gl

UI component for Globe Data Visualization using ThreeJS/WebGL
https://vasturiano.github.io/globe.gl/example/world-population/
MIT License
1.97k stars 293 forks source link

Document how to use external models like GLTF #121

Open letmaik opened 1 year ago

letmaik commented 1 year ago

globe.gl seems to remove old objects whenever objectsData() is called, which probably makes sense. But it isn't clear that one has to call .clone() on a loaded scene object to make it all work. I spent quite a bit of time trying to figure this out. Here's an example of something that should probably go into the docs:

    const gltfLoader = new THREE.GLTFLoader();
    gltfLoader.load('model.glb', gltf => {
      const scene = gltf.scene;
      scene.scale.setScalar(0.001)
      world.objectThreeObject(() => scene.clone());
    })
vasturiano commented 1 year ago

@letmaik thanks for reaching out.

If you input the object like so: world.objectThreeObject(scene) you shouldn't need to clone it. The framework will do it for you if pass a single object. But if you pass an accessor function like you've done above, the framework will assume that every object returned is unique because it can't know otherwise.

letmaik commented 1 year ago

I see, though in general passing a function is needed as soon as you start having multiple types of objects. The docstring also doesn't talk about the object case yet:

Object accessor function or attribute for defining a custom 3d object to render as part of the objects map layer. Should return an instance of ThreeJS Object3d.

At the moment there's only a single example using objectThreeObject: https://github.com/vasturiano/globe.gl/blob/221ae7cf9d519b6284d0d615ff689062120bf09c/example/satellites/index.html#L46-L48

Here, the following would be equivalent:

    const satGeometry = new THREE.OctahedronGeometry(SAT_SIZE * world.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
    const satMaterial = new THREE.MeshLambertMaterial({ color: 'palegreen', transparent: true, opacity: 0.7 });
    const sat = new THREE.Mesh(satGeometry, satMaterial);
    world.objectThreeObject(sat);
    const satGeometry = new THREE.OctahedronGeometry(SAT_SIZE * world.getGlobeRadius() / EARTH_RADIUS_KM / 2, 0);
    const satMaterial = new THREE.MeshLambertMaterial({ color: 'palegreen', transparent: true, opacity: 0.7 });
    const sat = new THREE.Mesh(satGeometry, satMaterial);
    world.objectThreeObject(() => sat.clone());

I think understanding the three cases would help folks.