let PigeonGLConstants = require("../constants.js"); let utils = require("../Utils/Utils.js"); /** * 相机控制类 * @class * @param {object} map - 包含位置信息的地图对象 * @param {object} camera - 相机对象 * @param {object} world - 世界对象 */ class CameraControl { constructor(map) { this.scope = map; this.map = map.map; this.camera = map.camera; this.active = true; this.world = map.world || new THREE.Group(); this.world.position.x = this.world.position.y = 0; this.camera.matrixAutoUpdate = false; this.update(); } /** * 更新地图参数,当this.map的参数发生变化时,需要执行该函数同步变化 */ update(map) { this.map = Object.assign(this.map, map); this.initMapTransform(); this.updateCamera(); } /** * 监听地图瓦片层的变化,并同步执行updateCamera()同步相机 */ listenMapChange() { //更新地图对象 this.update(this.map); } /** * 重新初始化没有地图瓦片层时的位置参数 */ initMapTransform() { let transform = {}; transform.width = this.map.width; transform.height = this.map.height; transform.zHeight = this.map.zHeight || 0; //z轴凸起高度 transform.x = this.map.center[0]; transform.y = this.map.center[1]; transform.z = this.map.center[2] || this.getZ(this.map.zoom); transform._pitch = (this.map.pitch * Math.PI) / 180 || 0; transform.angle = (this.map.rotation * Math.PI) / 180 || 0; this.map.transform = transform; } /** * 获取地图放大倍数 * @param {number} zoom - 地图zoom */ getZ(zoom) { return zoom } /** * 设置地图中心 * @param {Array} center - [lng,lat] */ setCenter(center) { this.map.center = center; this.initMapTransform(); } /** * 设置旋转角度 * @param {number} deg - 旋转的角度(!不是弧度) */ setRotation(rad) { this.map.rotation = rad; this.map.transform.angle = (this.map.rotation * Math.PI) / 180; } /** * 设置旋转的俯角 * @param {number} deg - 俯视的角度 */ setPitch(rad) { this.map.pitch = rad; this.map.transform._pitch = (this.map.pitch * Math.PI) / 180; } /** * 更新相机位置,当map位置信息变化时执行 */ updateCamera(ev) { let height = Math.abs(this.map.transform.z) + this.map.transform.zHeight; const fov = this.map.fov || 0.6435011087932844; //*2/Math.pow(this.map.zoom,2); let cameraToCenterDistance = height; const halfFov = fov / 2; const groundAngle = Math.PI / 2 + this.map.transform._pitch; const topHalfSurfaceDistance = (Math.sin(halfFov) * cameraToCenterDistance) / Math.sin(Math.PI - groundAngle - halfFov); const furthestDistance = Math.cos(Math.PI / 2 - this.map.transform._pitch) * topHalfSurfaceDistance + cameraToCenterDistance; const farZ = furthestDistance * 1.01; this.camera.projectionMatrix = utils.makePerspectiveMatrix( fov, this.map.transform.width / this.map.transform.height, 1, farZ ); let cameraWorldMatrix = new THREE.Matrix4(); let cameraTranslateZ = new THREE.Matrix4().makeTranslation(0, 0, height); let cameraRotateX = new THREE.Matrix4().makeRotationX(this.map.transform._pitch); let cameraRotateZ = new THREE.Matrix4().makeRotationZ(this.map.transform.angle); cameraWorldMatrix .premultiply(cameraTranslateZ) .premultiply(cameraRotateX) .premultiply(cameraRotateZ); this.camera.matrixWorld.copy(cameraWorldMatrix); // this.camera.position.z = height; // this.camera.rotation.x = (this.map.transform._pitch); // this.camera.rotation.z = (this.map.transform.angle); // this.camera.rotateOnWorldAxis(new THREE.Vector3(1,0,0),this.map.transform._pitch); // this.camera.rotateOnWorldAxis ( new THREE.Vector3(0,0,1), this.map.transform.angle ) //把整个地图挪到原点 this.world.position.x = -this.map.transform.x; this.world.position.y = -this.map.transform.y; } } export default CameraControl;