Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to use THREE.LOD? #8912

Closed
AmeliaWang93 opened this issue Oct 26, 2019 · 4 comments
Closed

Is it possible to use THREE.LOD? #8912

AmeliaWang93 opened this issue Oct 26, 2019 · 4 comments

Comments

@AmeliaWang93
Copy link

I try to use THREE.LOD, but it doesn't change after zooming.

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'/>
    <title>Add a 3D model</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no'/>
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.1/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.1/mapbox-gl.css' rel='stylesheet'/>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
        }
    </style>
</head>
<body>

<script src='https://unpkg.com/[email protected]/build/three.min.js'></script>

<div id='map'></div>
<script>
    mapboxgl.accessToken = '<your token>';
    var map = window.map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/light-v10',
        zoom: 18,
        center: [148.9819, -35.3981],
        pitch: 60,
        antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
    });

    // parameters to ensure the model is georeferenced correctly on the map
    var modelOrigin = [148.98190, -35.39847];
    var modelAltitude = 0;
    var modelRotate = [Math.PI / 2, 0, 0];

    var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(modelOrigin, modelAltitude);

    // transformation parameters to position, rotate and scale the 3D model onto the map
    var modelTransform = {
        translateX: modelAsMercatorCoordinate.x,
        translateY: modelAsMercatorCoordinate.y,
        translateZ: modelAsMercatorCoordinate.z,
        rotateX: modelRotate[0],
        rotateY: modelRotate[1],
        rotateZ: modelRotate[2],
        /* Since our 3D model is in real world meters, a scale transform needs to be
         * applied since the CustomLayerInterface expects units in MercatorCoordinates.
         */
        scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
    };

    var THREE = window.THREE;

    // configuration of the custom layer for a 3D model per the CustomLayerInterface
    var customLayer = {
        id: '3d-model',
        type: 'custom',
        renderingMode: '3d',
        onAdd: function (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);

			// add THREE.LOD
            var geometry = [
                [new THREE.IcosahedronBufferGeometry(50, 4), 5],
                [new THREE.IcosahedronBufferGeometry(50, 3), 10],
                [new THREE.IcosahedronBufferGeometry(50, 2), 20],
                [new THREE.IcosahedronBufferGeometry(50, 1), 30],
                [new THREE.IcosahedronBufferGeometry(50, 0), 40]
            ];

            let material = new THREE.MeshLambertMaterial({color: 0xffffff, wireframe: true});

            let i, j, mesh, lod;

            lod = new THREE.LOD();

            for (i = 0; i < geometry.length; i++) {

                mesh = new THREE.Mesh(geometry[i][0], material);
                mesh.scale.set(1.5, 1.5, 1.5);
                mesh.updateMatrix();
                mesh.matrixAutoUpdate = false;
                lod.addLevel(mesh, geometry[i][1]);
            }

            lod.updateMatrix();
            lod.matrixAutoUpdate = false;
            this.scene.add(lod);

            this.map = map;

            // use the Mapbox GL JS map canvas for three.js
            this.renderer = new THREE.WebGLRenderer({
                canvas: map.getCanvas(),
                context: gl,
                antialias: true
            });

            this.renderer.autoClear = false;
        },
        render: function (gl, matrix) {
            var rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX);
            var rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY);
            var rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ);

            var m = new THREE.Matrix4().fromArray(matrix);
            var l = new THREE.Matrix4().makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ)
                .scale(new THREE.Vector3(modelTransform.scale, -modelTransform.scale, modelTransform.scale))
                .multiply(rotationX)
                .multiply(rotationY)
                .multiply(rotationZ);

            this.camera.projectionMatrix = m.multiply(l);
            this.renderer.state.reset();
            this.renderer.render(this.scene, this.camera);
            this.map.triggerRepaint();
        }
    };

    map.on('style.load', function () {
        map.addLayer(customLayer, 'waterway-label');
    });
</script>

</body>
</html>
@joedjc
Copy link

joedjc commented Oct 26, 2019

@AmeliaWang93 I was trying to use this too, using the threebox library (see peterqliu/threebox#72). I found that the distance from the object to the camera wasn't being calculated/returned as it usually would in three js. Possibly the camera is being dealt with differently when using mapbox

@vakila
Copy link

vakila commented Oct 29, 2019

Hi @AmeliaWang93 @joedjc thanks for using Mapbox! No, we don't currently support LOD in our camera, but this is on our roadmap as part of our long-term work on 3D maps. So I'm going to close this out for now, but stay tuned! ❤️

@vakila vakila closed this as completed Oct 29, 2019
@AmeliaWang93
Copy link
Author

Thanks a lot. @vakila @joedjc

@tranhogdiep
Copy link

Hello guys, have any updates for these functions. Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants