一、背景

做三维WebGIS开发的朋友们都知道,我们加载倾斜摄影模型,一般使用cesium加载3dtiles格式的数据很简单,官网和网上都有很多例子,这里也不再详细赘述。但是在使用cesium场景中我们会遇到这样一个问题,在加载整个球的时候其实是影响了性能的,在加载局部小场景的时候我们是不需要加载整个地球的,例如我们在做智慧园区的项目时候,基本上只关注园区及其周边范围。如果加载整个地球无疑对资源开销造成了一定的浪费,我们要尽可能的提升用户的体验,将流畅度提升至最大化。所以我们可以使用three.js来完成,如果单纯的只是用来展示three.js无疑是比较不错的选择,但是如果我们想做一些空间查询、空间分析的话,three就不行了。于是我就想到了mapbox,mapbox地图可以拖拽成一定的倾斜角度,形成2.5d的三维效果,加载渲染速度比cesium快多了,不是说cesium不好,在大场景使用中,cesium还是不错的选择。
使用mapbox中的customLayer,结合three很方便加载进来,mapbox官网例子。官网例子只给出了加载gltf格式模型,对于fbx、obj格式的模型可以仿照该例子同样可以加载进来,但是如果我想加载倾斜摄影模型,找了好久找到了mapbox+deck.gl解决方案,deck.gl官网例子

二、数据处理

对于倾斜摄影数据,大多数是osgb格式的,我们在cesium加载倾斜摄影模型,将数据处理成3dtiles加载进来非常方便。在mapbox中结合deck.gl中的Tile3DLayer也可以轻松加进来,处理成3dtiles格式,我们可以选择如下

  1. Github 开源的小工具 地址
  2. Cesium官方推出的 Cesium Ion在线平台(用的少)地址
  3. 一些商家推出的工具集(如cesiumlab)下载地址

推荐使用cesiumlab功能很强大,能处理各种数据,文章最后给大家提供了osgb格式的倾斜摄影模型数据,方便大家测试,能帮到大家我也很高兴,也欢迎交流讨论 QQ 1826356125

三、加载3dtiles

import { MapboxLayer } from "@deck.gl/mapbox"
import { TripsLayer,Tile3DLayer } from "@deck.gl/geo-layers"
import {Tiles3DLoader} from '@loaders.gl/3d-tiles'
const core_1 = require("@math.gl/core")

//添加cesium格式3dtiles
  load3DTiles(layerConfig) {
    let layer=new MapboxLayer({
      id: layerConfig.id,
      type: Tile3DLayer,
      data: layerConfig.url,
      loader: Tiles3DLoader,
      onTileError: (err) => {
        console.log(err)
      },
      onTilesetLoad: (tileset) => {
        tileset.setProps({ maximumScreenSpaceError: 1 })
        const { cartographicCenter, zoom } = tileset;
        this.viewState = {
          ...this.viewState,
          longitude: cartographicCenter[0],
          latitude: cartographicCenter[1],
          zoom
        }
        let viewState = this.viewState
        //设置x、y、z偏移,有些倾斜摄影模型加载进来不在该位置
        //需要进行位置的调整,但我在进行旋转、和比例缩放的时候不起作用
        //欢迎来指正
        let mMtx=new core_1.Matrix4().makeTranslation(1,1,-200)
        
        tileset.modelMatrix=mMtx
        this.map.jumpTo({
          center: [viewState.longitude, viewState.latitude],
          zoom: viewState.zoom,
          //bearing: viewState.bearing,
          //pitch: viewState.pitch,
        });

      }
    })
    return layer
  }
let layer=load3DTiles({
	id: "3dTiles-xxxxxx",
    describe:"倾斜摄影",
    url:'http://localhost:8084/3DModel/qxsy/tileset.json',
    layerType: "3DTiles"
})
this.map.addLayer(layer)

最终效果

加载发现没有贴地,悬浮了一定高度
在这里插入图片描述
向下调整位置
let mMtx=new core_1.Matrix4().makeTranslation(1,1,-200) tileset.modelMatrix=mMtx
在这里插入图片描述

源码分析

在deck.gl例子中只给了加载CesiumIonLoader,在线的3dtiles,但是我们想加载自己部署发布的3dtiles,查看源码发现
在这里插入图片描述
Tiles3DLoader可以使用

MapboxLayer其实是对mapbox中的customLayer的进一步封装,实例化其实就是customLayer图层

mapbox-layer.js

import { getDeckInstance, addLayer, removeLayer, updateLayer, drawLayer } from './deck-utils';
export default class MapboxLayer {
  constructor(props) {
    if (!props.id) {
      throw new Error('Layer must have an unique id');
    }
    this.id = props.id;
    // mapbox中custom类型图层
    this.type = 'custom';
    // 3d模式
    this.renderingMode = props.renderingMode || '3d';
    this.map = null;
    this.deck = null;
    this.props = props;
  }
  // mapbox中添加图层触发盖事件 this.map.addLayer(layer)
  onAdd(map, gl) {
    this.map = map;
    //实例化deck
    this.deck = getDeckInstance({
      map,
      gl,
      deck: this.props.deck
    });
    //addLayer → updateLayers
    addLayer(this.deck, this);
  }
  onRemove() {
    removeLayer(this.deck, this);
  }
  setProps(props) {
    Object.assign(this.props, props, {
      id: this.id
    });
    if (this.deck) {
      updateLayer(this.deck, this);
    }
  }
  render(gl, matrix) {
    drawLayer(this.deck, this.map, this);
  }
}

deck-utils.js

function updateLayers(deck) {
  if (deck.props.userData.isExternal) {
    return;
  }
  const layers = [];
  let layerIndex = 0;
  deck.props.userData.mapboxLayers.forEach(deckLayer => {
    const LayerType = deckLayer.props.type;
    // 实例化图层,本案例加载LayerType:Tile3DLayer tile-3d-layer.js
    const layer = new LayerType(deckLayer.props, {
      _offset: layerIndex++
    });
    layers.push(layer);
  });
  deck.setProps({
    layers
  });
}

tile-3d-layer.js
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
tileset-3d.js
在这里插入图片描述
在这里插入图片描述

相关下载及参考文档

demo代码下载
osgb格式倾斜摄影数据下载
链接:https://pan.baidu.com/s/1_FPxf1niJT2DoD7vGsdd-g
提取码:zwd3

mapbox加载3d模型
deck.gl加载3dtiles

最后打个广告吧,自己花了好几个月写了一个基于mapbox的gis框架,下载地址,能很方便大家学习,也很容易应用到gis展示的项目中,感兴趣加我QQ了解

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐