如何在Vue中使用Mapbox和Three.js確保三維物體的底部固定在地圖上?

如何在Vue中使用Mapbox和Three.js確保三維物體的底部固定在地圖上?

vue中Mapbox和Three.JS:實現(xiàn)3D模型與地圖視角的完美適配

本文探討如何在Vue.js應用中,結(jié)合Mapbox GL JS和Three.js,實現(xiàn)三維模型與地圖視角的同步,確保模型底部始終固定在地圖表面,不會因視角變化而偏移。這在構(gòu)建地理信息系統(tǒng)或3D地圖可視化應用中至關(guān)重要。

假設(shè)你已成功渲染3D立方體到Mapbox地圖,但視角移動時立方體位置發(fā)生漂移。問題在于Three.js坐標系與Mapbox地圖坐標系的轉(zhuǎn)換和模型位置的設(shè)置。

以下代碼片段展示了可能存在問題的代碼結(jié)構(gòu),其中render函數(shù)更新Three.js相機矩陣,calculatemodeltransform函數(shù)進行坐標轉(zhuǎn)換:

render: (gl, matrix) => {   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(new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX))       .multiply(new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY))       .multiply(new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ));   customLayer.camera.projectionMatrix = m.multiply(l);   customLayer.renderer.resetState();   customLayer.renderer.render(customLayer.scene, customLayer.camera);   customLayer.map.triggerRepaint(); },  calculatemodeltransform(point) {   const modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat([point.lng, point.lat], this.modelAltitude);   return {     translateX: modelAsMercatorCoordinate.x,     translateY: modelAsMercatorCoordinate.y,     translateZ: modelAsMercatorCoordinate.z,     rotateX: this.modelRotate[0],     rotateY: this.modelRotate[1],     rotateZ: this.modelRotate[2],     scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()   }; }

核心問題在于模型的translateZ以及模型創(chuàng)建時的垂直位置。 我們需要調(diào)整模型位置,使其底部與地圖平面精確對齊。

立即學習前端免費學習筆記(深入)”;

解決方案:

  1. 模型創(chuàng)建調(diào)整: 在創(chuàng)建Three.js模型時,考慮模型高度,并調(diào)整其垂直位置(y軸)使其底部位于地圖平面(通常y=0)。
// 創(chuàng)建一個正方體幾何體,altitude 為模型高度 const geometry = new THREE.BoxGeometry(20, altitude, 20); const material = new THREE.MeshStandardMaterial({ color, transparent: true, opacity: 0.8 }); const cube = new THREE.Mesh(geometry, material);  // 關(guān)鍵步驟:將立方體底部放置在地圖平面上 cube.position.y = altitude / 2; 
  1. render函數(shù)調(diào)整: 在render函數(shù)中,根據(jù)模型高度調(diào)整translateZ值,確保模型底部始終與地圖平面對齊。
const l = new THREE.Matrix4().makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ - altitude / 2)   .scale(new THREE.Vector3(modelTransform.scale, -modelTransform.scale, modelTransform.scale))   // ... 其他轉(zhuǎn)換矩陣

通過以上調(diào)整,即使地圖視角變化,三維模型的底部也會保持在地圖表面,實現(xiàn)完美的視角適配。 請確保altitude變量正確反映模型的高度。 如有需要,可以根據(jù)模型的實際幾何形狀進一步微調(diào)垂直位置。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊9 分享