从零开始搭建开源智慧城市项目(七)场景导入到地图中。

前言

上一节通过MeshLine添加了飞线飞点 这一节把整个场景导入到mapbox中。

思路

主要思路就是mapboxcustomLayer图层,可以把three的3d场景通过场景和控制器的重叠进行导入,这样本质上mapbox和three还是两个互不干扰的场景。

实现步骤

  1. 初始化地图场景
  2. 当地图加载完成后,初始化custom图层(参考docs.mapbox.com/mapbox-gl-j…
  3. 设置render中模型位置和相机的相关变化(涉及到坐标转换这个方面准备专门写一章来讲一下自己的理解)
  4. 其他的three相关内容参考以前的章节

代码

  initmap() {
      mapboxgl.accessToken =
        "??"; //这里请换成自己的token
      map = new mapboxgl.Map({
        container: "map", // container id 绑定的组件的id
        style: "mapbox://styles/mapbox/streets-v11", //地图样式,可以使用官网预定义的样式,也可以自定义
        center: [121.47, 31.23], // 初始坐标系
        zoom: 15, // starting zoom 地图初始的拉伸比例
        pitch: 60, //地图的角度,不写默认是0,取值是0-60度,一般在3D中使用
        bearing: -17.6, //地图的初始方向,值是北的逆时针度数,默认是0,即是正北
        antialias: true, //抗锯齿,通过false关闭提升性能
      });
    }
    setCustomLayer() {
      const customLayer = {
        id: "3d-model",
        type: "custom",
        renderingMode: "3d",
        onAdd: this.initThree,
        // eslint-disable-next-line no-unused-vars
        render: this.threeRender,
      };
      return customLayer;
    },
       initThree(map, gl) {
      //创建场景
      scene = new THREE.Scene();
      /**
       * 透视投影相机设置
       */
      const width = window.innerWidth; // 窗口宽度
      const height = window.innerHeight; // 窗口高度

      /** 透视投影相机对象 */
      camera = new THREE.PerspectiveCamera(60, width / height, 1, 700);
      camera.position.set(600, 900, 600); // 树上面观察
      camera.lookAt(scene.position); // 设置相机方向(指向的场景对象)
      // 创建渲染器对象
      //   const container = document.getElementById("scene");
      renderer = new THREE.WebGLRenderer({
        canvas: map.getCanvas(),
        context: gl,
        antialias: true,
      });
      //   container.appendChild(renderer.domElement); // body元素中插入canvas对象

      //创建点光源和环境光源
      const point = new THREE.PointLight(0xffffff);
      point.position.set(600, 900, 600); // 点光源位置
      scene.add(point); // 点光源添加到场景中
      // 环境光
      const ambient = new THREE.AmbientLight(0x404040, 1);
      scene.add(ambient);
      renderer.autoClear = false;
      //   pickingScene = new THREE.Scene(); //离屏渲染
      //   pickingTexture = new THREE.WebGLRenderTarget(1, 1); //离屏渲染
    },
    threeRender(gl, matrix) {
      const modelOrigin = [121.47, 31.23];
      const modelAltitude = 770;
      const modelRotate = [Math.PI / 4, 0, 0];
      const modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
        modelOrigin,
        modelAltitude
      );
      const modelTransform = {
        translateX: modelAsMercatorCoordinate.x,
        translateY: modelAsMercatorCoordinate.y,
        translateZ: modelAsMercatorCoordinate.z,
        rotateX: modelRotate[0],
        rotateY: modelRotate[1],
        rotateZ: modelRotate[2],
        scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits(),
      };
      const rotationX = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(1, 0, 0),
        modelTransform.rotateX
      );
      const rotationY = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 1, 0),
        modelTransform.rotateY
      );
      const rotationZ = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 0, 1),
        modelTransform.rotateZ
      );

      const m = new THREE.Matrix4().fromArray(matrix);
      const 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);

      camera.projectionMatrix = m.multiply(l);
      this.cityanimate();
      renderer.resetState();
      renderer.render(scene, camera);
      map.triggerRepaint();
    },
复制代码

调用代码

this.initmap();
    map.on("style.load", () => {
      let customLayer = this.setCustomLayer();
      map.addLayer(customLayer, "waterway-label");
      this.addGLTF();
      this.creatWall();
      this.creatRunLine();
    });
复制代码

效果图

SDGIF_Rusult_1.gif

项目地址github.com/lixiaochjaj…

Guess you like

Origin juejin.im/post/7074862535089864741