參考文檔鏈接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/
加載地圖后調用該函數
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 )
// 創建兩個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加載程序將三維模型添加到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;
// 通過攝像機和鼠標位置更新射線
// this.raycaster.setFromCamera(mouse, this.camera);
// 計算物體和射線的焦點
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();
});
},