import * as THREE from 'three'; import { Vector3 } from 'three'; import { Orbit } from './Orbit'; /** * * 相机的控制. * ->切换相机 * ->设置视口大小 * ->旋转和移动相机. * * @export * @class ViewCameraManage */ export class CameraUpdate { private m_CurCamera: THREE.Camera; private m_CameraArray: Map = new Map(); //视口的画布大小 private m_Width: number; private m_Height: number; //视口显示的高度 private m_ViewHeight: number = 10; //观察的位置 private m_Target: THREE.Vector3 = new THREE.Vector3(); //观察向量 private m_Direction: THREE.Vector3 = new THREE.Vector3(0, 0, -1); //观察的轨道. private m_Orbit: Orbit = new Orbit(); m_MinViewHeight = 10; m_MaxViewHeight = 3e4; constructor() { this.m_CameraArray.set(THREE.OrthographicCamera, new THREE.OrthographicCamera(-2, 2, 2, -2, -1e6, 1e6)); this.m_CameraArray.set(THREE.PerspectiveCamera, new THREE.PerspectiveCamera(50, 1, 0.01, 10000)); this.m_CurCamera = this.m_CameraArray.get(THREE.OrthographicCamera); this.m_Orbit.UpdateRoValue(this.m_Direction); this.UpdateUp(); this.Update(); } get Aspect(): number { return this.m_Width / this.m_Height; } get Camera(): THREE.Camera { return this.m_CurCamera; } get ViewHeight() { return this.m_ViewHeight; } set ViewHeight(height) { this.m_ViewHeight = THREE.Math.clamp(height, this.m_MinViewHeight, this.m_MaxViewHeight); } SetSize(width: number, height: number) { this.m_Width = width; this.m_Height = height; } /** * 平移相机. * * @param {THREE.Vector3} mouseMove * @memberof CameraControl */ Pan(mouseMove: THREE.Vector3) { mouseMove.y *= -1; mouseMove.multiplyScalar(-this.m_ViewHeight / this.m_Height); mouseMove.applyQuaternion(this.Camera.quaternion); this.m_Target.add(mouseMove); this.Update(); } Rotate(mouseMove: THREE.Vector3, target: THREE.Vector3) { this.m_Orbit.RoX -= mouseMove.y * 0.003; this.m_Orbit.RoZ -= mouseMove.x * 0.003; //缓存观察点 let oldTargetFormCameraSpace = target.clone().applyMatrix4(this.Camera.matrixWorldInverse); this.m_Orbit.UpdateDirection(this.m_Direction); this.UpdateUp(); this.Update(); //-----还原观察点 //得到新的观察点相对于相机的位置 let newTargetFormCameraSpace = target.clone().applyMatrix4(this.Camera.matrixWorldInverse); //减去原先的位置. 得到观测点在相机内移动的向量 newTargetFormCameraSpace.sub(oldTargetFormCameraSpace); //乘以相机的矩阵. 得到向量在世界坐标系的位置 newTargetFormCameraSpace.applyMatrix4(this.Camera.matrix); //因为使用的是点变换,所以减去基点,得到向量 newTargetFormCameraSpace.sub(this.Camera.position); //加上移动的向量. 使得观察点时钟在相机的某个位置 this.m_Target.add(newTargetFormCameraSpace); this.Update(); } Zoom(scale: number, scaleCenter?: THREE.Vector3) { if (this.Camera instanceof THREE.OrthographicCamera) { this.ViewHeight *= scale; if (scaleCenter && this.m_ViewHeight < this.m_MaxViewHeight) { this.m_Target.sub(scaleCenter); this.m_Target.multiplyScalar(scale); this.m_Target.add(scaleCenter); } } else if (this.Camera instanceof THREE.PerspectiveCamera) { let add = scale > 1 ? 1 : -1; add *= this.Camera.position.distanceTo(this.m_Target) / 10; this.m_Target.add(this.m_Direction.clone().multiplyScalar(-add)); } this.Update(); } ZoomExtensBox3(box3: THREE.Box3) { if (!box3) return; this.Camera.updateMatrixWorld(false); //变换到相机坐标系 box3.applyMatrix4(this.Camera.matrixWorldInverse); // box3.getCenter(this.m_Target); //世界坐标系 this.m_Target.applyMatrix4(this.Camera.matrix); //size let size = box3.getSize(new Vector3()); //宽高比 let aspectRatio = size.x / size.y; let viewAspectRatio = this.Aspect; // if (aspectRatio > viewAspectRatio) { this.m_ViewHeight = size.x / viewAspectRatio; } else { this.m_ViewHeight = size.y; } this.Update(); } LookAt(dir: THREE.Vector3) { this.m_Orbit.UpdateRoValue(dir); this.m_Direction.copy(dir); this.UpdateUp(); this.Update(); } UpdateUp() { Orbit.ComputUpDirection(this.m_Direction, this.Camera.up); } /** * 根据视口大小,设置相机视口范围. * * @returns * @memberof CameraControl */ Update() { this.Camera.position.copy(this.m_Target); if (this.Camera instanceof THREE.OrthographicCamera) { this.Camera.left = this.Aspect * this.m_ViewHeight / -2; this.Camera.right = this.Aspect * this.m_ViewHeight / 2; this.Camera.bottom = this.m_ViewHeight / -2; this.Camera.top = this.m_ViewHeight / 2; this.Camera.position.sub(this.m_Direction); } else if (this.Camera instanceof THREE.PerspectiveCamera) { this.Camera.aspect = this.Aspect; let distens = (this.m_ViewHeight / 2) / (Math.tan(THREE.Math.degToRad(this.Camera.fov) / 2)); this.Camera.position.sub(this.m_Direction.clone().multiplyScalar(distens)); } else { return; } this.Camera.lookAt(this.m_Target); this.Camera.updateProjectionMatrix(); this.Camera.updateMatrixWorld(false); } SwitchCamera() { if (this.Camera instanceof THREE.OrthographicCamera) { this.m_CurCamera = this.m_CameraArray.get(THREE.PerspectiveCamera); } else { this.m_CurCamera = this.m_CameraArray.get(THREE.OrthographicCamera); } this.UpdateUp(); this.Update(); } }