import * as THREE from 'three' ; import { clamp } from 'lodash' ; import { ObjectVector2 } from './scenarioUtils' ; let offset = new THREE . Vector3 ( ) ; let delta = new THREE . Vector3 ( ) ; function panLeft ( camera , distance , offset ) { delta . setFromMatrixColumn ( camera . matrix , 0 ) ; delta . multiplyScalar ( - distance ) ; offset . add ( delta ) ; } function panUp ( camera , distance , offset ) { delta . setFromMatrixColumn ( camera . matrix , 2 ) ; delta . set ( delta . x , 0 , delta . z ) . normalize ( ) ; delta . multiplyScalar ( - distance ) ; offset . add ( delta ) ; } export function panCamera ( { x : deltaX , y : deltaY } , camera , lookAt , position , clientWidth , clientHeight ) { offset . copy ( position ) . sub ( lookAt ) ; let targetDistance = offset . length ( ) ; targetDistance *= Math . tan ( ( camera . fov / 2 ) * Math . PI / 180.0 ) ; offset . set ( 0 , 0 , 0 ) ; panLeft ( camera , 2 * deltaX * targetDistance / clientHeight , offset ) ; panUp ( camera , 2 * deltaY * targetDistance / clientHeight , offset ) ; return { cameraPosition : position . clone ( ) . add ( offset ) , cameraLookAt : lookAt . clone ( ) . add ( offset ) } ; } const quat = new THREE . Quaternion ( ) . setFromUnitVectors ( new THREE . Vector3 ( 0 , 1 , 0 ) , new THREE . Vector3 ( 0 , 1 , 0 ) ) ; const quatInverse = quat . clone ( ) . invert ( ) ; let spherical = new THREE . Spherical ( ) ; export function rotateCamera ( { x : deltaX , y : deltaY } , camera , lookAt , position , clientWidth , clientHeight ) { const deltaTheta = - Math . PI * deltaX / clientWidth ; const deltaPhi = - Math . PI * deltaY / clientHeight ; offset . copy ( position ) . sub ( lookAt ) ; spherical . setFromVector3 ( offset ) ; spherical . theta += deltaTheta ; spherical . phi = clamp ( spherical . phi + deltaPhi , 0 , Math . PI * .495 ) ; spherical . makeSafe ( ) ; offset . setFromSpherical ( spherical ) ; offset . applyQuaternion ( quatInverse ) ; return { cameraPosition : lookAt . clone ( ) . add ( offset ) } ; } export function zoomCamera ( { y : deltaY } , lookAt , position , minDistance , maxDistance ) { offset . copy ( position ) . sub ( lookAt ) ; let distance = offset . length ( ) ; let scale = clamp ( ( 100 + deltaY ) / 100 , minDistance / distance , maxDistance / distance ) ; offset . multiplyScalar ( scale ) ; return { cameraPosition : lookAt . clone ( ) . add ( offset ) } ; }