UNPKG

@giro3d/giro3d

Version:

A JS/WebGL framework for 3D geospatial data visualization

89 lines (87 loc) 3.87 kB
/* * Copyright (c) 2015-2018, IGN France. * Copyright (c) 2018-2026, Giro3D team. * SPDX-License-Identifier: MIT */ import { CameraHelper, Mesh, MeshBasicMaterial, SphereGeometry } from 'three'; import Ellipsoid from '../core/geographic/Ellipsoid'; import { isOrthographicCamera, isPerspectiveCamera } from '../utils/predicates'; import Panel from './Panel'; class CameraInspector extends Panel { snapshots = []; horizonDistance = 'N/A'; /** * @param gui - The GUI. * @param instance - The Giro3D instance. */ constructor(gui, instance) { super(gui, instance, 'View'); this.view = this.instance.view; this.camera = this.view.camera; const notify = this.notify.bind(this); this.addController(this.camera, 'type').name('Type'); if (isPerspectiveCamera(this.camera)) { this.addController(this.camera, 'fov').min(25).max(150).name('FOV'); } else if (isOrthographicCamera(this.camera)) { this.addController(this.camera, 'zoom'); this.addController(this.camera, 'left'); this.addController(this.camera, 'right'); this.addController(this.camera, 'top'); this.addController(this.camera, 'bottom'); } this.addController(instance.mainLoop, 'automaticCameraPlaneComputation').name('Automatic plane computation').onChange(notify); this.addController(this.camera, 'far').name('Far plane').onChange(notify); this.addController(this.camera, 'near').name('Near plane').onChange(notify); this.addController(this.view, 'maxFarPlane').name('Max far plane').onChange(notify); this.addController(this.view, 'minNearPlane').name('Min near plane').onChange(notify); this.addController(this.view, 'width').name('Width (pixels)'); this.addController(this.view, 'height').name('Height (pixels)'); if (instance.coordinateSystem.isEpsg(4978)) { this.addController(this, 'horizonDistance'); instance.addEventListener('after-camera-update', () => { const distance = Ellipsoid.WGS84.getOpticalHorizon(instance.view.camera.position); this.horizonDistance = distance != null ? distance > 10000 ? (distance / 1000).toFixed(0) + ' km' : distance.toFixed(0) + 'm' : 'N/A'; }); } this.addController(this, 'createFrustumSnapshot').name('Create frustum snapshot'); this.addController(this, 'deleteSnapshots').name('Delete frustum snapshots'); const position = this.gui.addFolder('Position'); position.close(); this._controllers.push(position.add(this.camera.position, 'x')); this._controllers.push(position.add(this.camera.position, 'y')); this._controllers.push(position.add(this.camera.position, 'z')); if (this.view.controls && 'target' in this.view.controls) { const target = this.gui.addFolder('Target'); target.close(); const targetObj = this.view.controls.target; this._controllers.push(target.add(targetObj, 'x')); this._controllers.push(target.add(targetObj, 'y')); this._controllers.push(target.add(targetObj, 'z')); } } deleteSnapshots() { this.snapshots.forEach(helper => { helper.dispose(); this.instance.remove(helper); }); this.snapshots.length = 0; } createFrustumSnapshot() { const helper = new CameraHelper(this.instance.view.camera); this.instance.add(helper); helper.update(); this.instance.notifyChange(); if (this.instance.coordinateSystem.isEpsg(4978) && isPerspectiveCamera(this.instance.view.camera)) { const distance = Ellipsoid.WGS84.getOpticalHorizon(this.instance.view.camera.position); if (distance != null) { helper.add(new Mesh(new SphereGeometry(distance, 32, 16), new MeshBasicMaterial({ wireframe: true, color: 'green' }))); } } helper.updateMatrixWorld(true); this.snapshots.push(helper); } } export default CameraInspector;