You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Mapbox/Threebox中的3D模型自动贴合DEM图层?

自动让Threebox模型贴合Mapbox DEM地形的方法

解决思路

要让模型自动适配地形高度,核心就是用Mapbox的API拿到指定坐标的地形海拔,再把这个高度赋值给模型的Z轴,同时还要考虑模型自身的锚点偏移(避免模型埋地或悬空)。

具体实现

1. 加载模型时自动适配地形

修改模型加载的回调逻辑,先查询地形高度,再设置模型坐标:

threebox.current.loadObj(options, async (model) => {
  const lnglat = [23.72602949741895, 37.972941447007116];
  // 调用Mapbox API获取当前坐标的地形高度(已考虑地形 exaggeration)
  const terrainHeight = await map.current.queryTerrainElevation(lnglat);
  
  // 处理模型锚点:如果模型原点不在底部,计算偏移量
  model.object3D.geometry.computeBoundingBox();
  const bbox = model.object3D.geometry.boundingBox;
  const modelHalfHeight = (bbox.max.z - bbox.min.z) / 2; // 假设原点在模型中心,偏移一半高度
  
  // 设置模型坐标:地形高度 + 锚点偏移
  model.setCoords([...lnglat, terrainHeight + modelHalfHeight]);
  threebox.current.add(model);
});

2. 移动模型时实时更新高度(比如路径上的车辆)

如果模型需要沿路径移动,每次更新位置时重新查询地形高度即可:

// 示例:更新模型到新坐标
async function moveModelTo(newLnglat) {
  const terrainHeight = await map.current.queryTerrainElevation(newLnglat);
  const modelHalfHeight = (model.object3D.geometry.boundingBox.max.z - model.object3D.geometry.boundingBox.min.z) / 2;
  model.setCoords([...newLnglat, terrainHeight + modelHalfHeight]);
}

3. 关键注意点

  • 锚点偏移必须调:不同的GLTF模型原点位置不一样,一定要计算模型自身的高度偏移,不然模型要么卡进地里要么飘在空中。如果你的模型原点本来就在底部,那偏移量设为0就行。
  • 异步处理别忽略:queryTerrainElevation是异步方法,必须用await或者.then()等拿到高度后再设置坐标,不然模型初始位置会出错。
  • 性能优化(多模型/高频移动场景):如果有大量模型或者需要频繁更新位置,可以把已经查询过的坐标和高度存在一个对象里做缓存,重复坐标直接用缓存值,减少API调用次数。

完整修改后的代码

// 初始化Threebox
threebox.current = (window.tb = new Threebox(
  map.current,
  map.current.getCanvas().getContext('webgl'),
  {
    defaultLights: true,
    enableSelectingObjects:true,
    enableTooltips:true,
    realSunlight:true,
    sky:true
  }
));

// 添加自定义模型图层
map.current.addLayer({
  id: 'custom-threebox-model',
  type: 'custom',
  renderingMode: '3d',
  onAdd: async () => { 
    const options = {
      obj: 'https://docs.mapbox.com/mapbox-gl-js/assets/metlife-building.gltf',
      type: 'gltf',
      scale: { x: 0.2, y: 0.2, z: 0.2 },
      units: 'meters',
      rotation: { x: 90, y: -90, z: 0 }
    };
    
    threebox.current.loadObj(options, async (model) => {
      const lnglat = [23.72602949741895, 37.972941447007116];
      // 获取地形高度
      const terrainHeight = await map.current.queryTerrainElevation(lnglat);
      // 计算模型锚点偏移
      model.object3D.geometry.computeBoundingBox();
      const bbox = model.object3D.geometry.boundingBox;
      const modelHalfHeight = (bbox.max.z - bbox.min.z) / 2;
      // 设置模型坐标
      model.setCoords([...lnglat, terrainHeight + modelHalfHeight]);
      threebox.current.add(model); 
    });
  },            
  render: () => {
    threebox.current.update();
  }
});

// 添加DEM地形图层
map.current.addSource('mapbox-dem', {
  'type': 'raster-dem',
  'url': 'mapbox://mapbox-terrain-dem-v1',
  'tileSize': 512,
  'maxzoom': 18
});
map.current.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1 });

内容的提问来源于stack exchange,提问作者slevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:10:57