mapbox結(jié)合threeJS載入3d模型,并實(shí)現(xiàn)點(diǎn)擊事件

參考文檔鏈接1:https://github.com/mapbox/mapbox-gl-js/issues/10595

https://codepen.io/astojilj/pen/jOyQNLW?editors=0010

參考文檔鏈接2:http://www.mapbox.cn/mapbox-gl-js/example/add-3d-model/

加載地圖后調(diào)用該函數(shù)

    setBuild () {
      const that = this
      const mouse = new THREE.Vector4(-1000, -1000, 1, 1);
      // parameters to ensure the model is georeferenced correctly on the map
      var modelOrigin = [116.404269, 39.914714];
      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()
      };
      // 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.PerspectiveCamera();
          this.scene = new THREE.Scene();
          // var geometry = new THREE.BoxGeometry( 1000, 1000, 1000 )
          // var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } )
          // this.cube = new THREE.Mesh( geometry, material )
          // this.scene.add( this.cube )
          // 創(chuàng)建兩個(gè)3.js燈光來照亮模型
          var directionalLight = new THREE.DirectionalLight(0xffffff);
          directionalLight.position.set(1000, -1000, 1000).normalize();
          this.scene.add(directionalLight); 
          var directionalLight2 = new THREE.DirectionalLight(0xffffff);
          directionalLight2.position.set(1000, 1000, 1000).normalize();
          this.scene.add(directionalLight2);    
          // 使用three.js FBX加載程序?qū)⑷S模型添加到three.js場景中
          var loader = new FBXLoader();
          loader.load('./3d/demo.FBX',function (loadedMesh) {
              this.scene.add(loadedMesh);
            }.bind(this)
          );
          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;
          this.raycaster = new THREE.Raycaster();
          this.renderer.domElement.addEventListener('click', (event) => {
            event.preventDefault();
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
            // 通過攝像機(jī)和鼠標(biāo)位置更新射線
            // this.raycaster.setFromCamera(mouse, this.camera);
            // 計(jì)算物體和射線的焦點(diǎn)
            const intersects = this.raycaster.intersectObjects(this.scene.children, true);
            if (intersects.length > 0) {
              that.$emit('openBuild')
            }
          })
        },
        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.elements = matrix;
          this.camera.projectionMatrix = m.clone().multiply(l);
          this.camera.matrixWorldInverse = new THREE.Matrix4();
          this.renderer.resetState();

          const freeCamera = this.map.getFreeCameraOptions();
          let cameraPosition = new THREE.Vector4(freeCamera.position.x, freeCamera.position.y, freeCamera.position.z, 1);
          cameraPosition.applyMatrix4(l.invert());
          let direction = mouse.clone().applyMatrix4(this.camera.projectionMatrix.clone().invert());
          direction.divideScalar(direction.w);
          this.raycaster.set(cameraPosition, direction.sub(cameraPosition).normalize());

          // const intersects = this.raycaster.intersectObjects( this.scene.children, true);
          // console.log(mouse, 'Intersection count:', intersects.length)
          this.renderer.render(this.scene, this.camera);
          this.map.triggerRepaint();
        }
      };
      this.map.addLayer(customLayer);
      this.map.on('mousemove', (event) => {
        mouse.x = ( event.point.x / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.point.y / window.innerHeight ) * 2 + 1;
        // this.map.triggerRepaint();
      });
    },
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容