import { mat4 , vec2 , vec3 } from 'gl-matrix' ; import { m4 , v2 , v3 } from './gl-matrix-extensions' ; import { CameraModifier } from './cameramodifier' ; /**
 * Math for camera rotation based on the turntable metaphor. The rotation computed by an initial (@see startRotate) and
 * subsequent (@see updateRotate) event points and can be applied to a camera via an explicit update (@see update).
 * In contrast to the trackball, this metaphor is usually less confusing for non-professionals.
 */ export class TurntableModifier extends CameraModifier { protected static readonly DEFAULT_SENSITIVITY = 0.002 ; /**
     * Current rotation matrix.
     */ protected _rotation : mat4 = m4 ( ) ; protected _maxAzimuth : number | undefined = + Math . PI * 0.5 - 1e-4 ; protected _minAzimuth : number | undefined = - Math . PI * 0.5 + 1e-4 ; protected _xAxisScreenSpace = v3 ( ) ; protected _azimuth : number ; see sensitivity protected _sensitivity : number = TurntableModifier . DEFAULT_SENSITIVITY ; param point initiate ( point ) { Object . assign ( this . _reference , this . _camera ) ; this . _initialPoint = point ; const centerToEye = vec3 . sub ( v3 ( ) , this . _reference . eye , this . _reference . center ) ; vec3 . normalize ( centerToEye , centerToEye ) ; this . _xAxisScreenSpace = vec3 . cross ( v3 ( ) , [ 0.0 , 1.0 , 0.0 ] , centerToEye ) ; this . _azimuth = Math . acos ( vec3 . dot ( centerToEye , [ 0.0 , 1.0 , 0.0 ] ) ) ; this . _azimuth = Math . PI * 0.5 - this . _azimuth ; } param point process ( point ) { this . _currentPoint = point ; const magnitudes = vec2 . subtract ( v2 ( ) , this . _initialPoint , this . _currentPoint ) ; vec2 . scale ( magnitudes , magnitudes , window . devicePixelRatio * this . _sensitivity ) ; if ( this . _minAzimuth ) { magnitudes [ 1 ] = Math . min ( this . _azimuth - this . _minAzimuth , magnitudes [ 1 ] ) ; } if ( this . _maxAzimuth ) { magnitudes [ 1 ] = Math . max ( this . _azimuth - this . _maxAzimuth , magnitudes [ 1 ] ) ; } mat4 . rotateY ( this . _rotation , m4 ( ) , magnitudes [ 0 ] ) ; mat4 . rotate ( this . _rotation , this . _rotation , magnitudes [ 1 ] , this . _xAxisScreenSpace ) ; this . update ( ) ; } /**
     * Actually applies the trackball rotation to the given camera.
     */ update ( ) { if ( this . _camera === undefined ) { return ; } const T = mat4 . fromTranslation ( m4 ( ) , this . _reference . center ) ; mat4 . multiply ( T , T , this . _rotation ) ; mat4 . translate ( T , T , vec3 . negate ( v3 ( ) , this . _reference . center ) ) ; const up = vec3 . transformMat4 ( v3 ( ) , [ 0.0 , 1.0 , 0.0 ] , this . _rotation ) ; const eye = vec3 . transformMat4 ( v3 ( ) , this . _reference . eye , T ) ; this . _camera . up = up ; this . _camera . eye = eye ; } /**
     * Rotational sensitivity.
     */ set sensitivity ( sensitivity ) { this . _sensitivity = sensitivity ; } get sensitivity ( ) : number { return this . _sensitivity ; } }