import { mat4 , vec2 , vec3 , vec4 } from "gl-matrix" ; import { AABB } from "../AABB" ; import { EventEmitter } from "../utils" ; export interface ICameraOptions { width ? : number ; height ? : number ; } export const CAMERA_DEFAULT_OPTIONS = { width : 0 , height : 0 } ; export abstract class AbstractCamera extends EventEmitter { private _width : number = 0 ; private _height : number = 0 ; private _translation : vec3 = null ; private _viewMatrix : mat4 = null ; private _projectionMatrix : mat4 = null ; private _viewInverseMatrix : mat4 = null ; private _projectionInverseMatrix : mat4 = null ; private _viewProjectionMatrix : mat4 = null ; private _viewProjectionInverseMatrix : mat4 = null ; private _frustumPlanes : vec4 [ ] = null ; param options public constructor ( options ? ) { super ( ) ; options = Object . assign ( { } , CAMERA_DEFAULT_OPTIONS , options ) ; this . _width = options . width ; this . _height = options . height ; this . _translation = vec3 . create ( ) ; this . _viewMatrix = mat4 . create ( ) ; this . _projectionMatrix = mat4 . create ( ) ; this . _viewInverseMatrix = mat4 . create ( ) ; this . _projectionInverseMatrix = mat4 . create ( ) ; this . _viewProjectionMatrix = mat4 . create ( ) ; this . _viewProjectionInverseMatrix = mat4 . create ( ) ; this . _frustumPlanes = [ vec4 . create ( ) , vec4 . create ( ) , vec4 . create ( ) , vec4 . create ( ) , vec4 . create ( ) , vec4 . create ( ) ] ; } /**
     * The camera width
     */ public getWidth ( ) { return this . _width ; } param value public setWidth ( value ) { this . _width = value ; } /**
     * The camera height
     */ public getHeight ( ) { return this . _height ; } param value public setHeight ( value ) { this . _height = value ; } /**
     * The aspect size of the rendering surface
     */ public getAspect ( ) { return this . getWidth ( ) / this . getHeight ( ) ; } /**
     * Returns the translation of the camera
     */ public getTranslation ( ) { return this . _translation ; } /**
     * Returns the view matrix of the camera
     */ public getViewMatrix ( ) { return this . _viewMatrix ; } /**
     * Returns the projection matrix of the camera
     */ public getProjectionMatrix ( ) { return this . _projectionMatrix ; } /**
     * Returns the view inverse matrix of the camera
     */ public getViewInverseMatrix ( ) { return this . _viewInverseMatrix ; } /**
     * Returns the projection inverse matrix of the camera
     */ public getProjectionInverseMatrix ( ) { return this . _projectionInverseMatrix ; } /**
     * Returns the view-projection matrix of the camera
     */ public getViewProjectionMatrix ( ) { return this . _viewProjectionMatrix ; } /**
     * Returns the view-projection inverse matrix of the camera
     */ public getViewProjectionInverseMatrix ( ) { return this . _viewProjectionInverseMatrix ; } /**
     * Should be called every frame, must be overridden
     */ public abstract update ( ) ; param mCameraView param mCameraProjection public updateTransforms ( mCameraView , mCameraProjection ) { const mView = this . getViewMatrix ( ) ; const mProjection = this . getProjectionMatrix ( ) ; const mViewInverse = this . getViewInverseMatrix ( ) ; const mProjectionInverse = this . getProjectionInverseMatrix ( ) ; const mViewProjection = this . getViewProjectionMatrix ( ) ; const mViewProjectionInverse = this . getViewProjectionInverseMatrix ( ) ; mat4 . copy ( mView , mCameraView ) ; mat4 . copy ( mProjection , mCameraProjection ) ; mat4 . multiply ( mViewProjection , mCameraProjection , mCameraView ) ; mat4 . invert ( mViewInverse , mCameraView ) ; mat4 . invert ( mProjectionInverse , mCameraProjection ) ; mat4 . invert ( mViewProjectionInverse , mViewProjection ) ; } /**
     * Destroy this Object
     */ public destroy ( ) { this . _viewMatrix = null ; this . _projectionMatrix = null ; this . _viewProjectionMatrix = null ; this . _viewProjectionInverseMatrix = null ; this . emit ( "destroy" ) ; } param width param height public resize ( width , height ) { this . _width = width ; this . _height = height ; this . emit ( "resize" , width , height ) ; } param pt public screenToWorldPoint ( pt ) { const out = vec3 . create ( ) ; const x = ( 2.0 * pt [ 0 ] / this . getWidth ( ) ) - 1.0 ; const y = ( this . getHeight ( ) - ( 2.0 * pt [ 1 ] ) ) / this . getHeight ( ) ; const z = ( 2.0 * pt [ 2 ] ) - 1.0 ; vec3 . set ( out , x , y , z ) ; vec3 . transformMat4 ( out , out , this . getViewProjectionInverseMatrix ( ) ) ; return out ; } param pt public worldToScreenPoint ( pt ) { const out = vec2 . create ( ) ; const v = vec3 . copy ( vec3 . create ( ) , pt ) ; vec3 . transformMat4 ( v , v , this . getViewProjectionMatrix ( ) ) ; out [ 0 ] = Math . round ( ( ( v [ 0 ] + 1.0 ) * 0.5 ) * this . getWidth ( ) ) ; out [ 1 ] = Math . round ( ( ( 1.0 - v [ 1 ] ) * 0.5 ) * this . getHeight ( ) ) ; return out ; } param aabb public intersectsAABB ( aabb ) { const frustumPlanes = this . _frustumPlanes ; for ( let ii = 0 ; ii < 6 ; ++ ii ) { const plane = frustumPlanes [ ii ] ; const min = aabb . getMin ( ) ; const max = aabb . getMax ( ) ; const px = plane [ 0 ] > 0 ? max [ 0 ] : min [ 0 ] ; const py = plane [ 1 ] > 0 ? max [ 1 ] : min [ 1 ] ; const pz = plane [ 2 ] > 0 ? max [ 2 ] : min [ 2 ] ; if ( ( plane [ 0 ] * px ) + ( plane [ 1 ] * py ) + ( plane [ 2 ] * pz ) + ( plane [ 3 ] ) < 0 ) { return false ; } } return true ; } /**
     * Update the frustum of the camera
     */ public updateFrustum ( ) { const frustumPlanes = this . _frustumPlanes ; const [ m0 , m1 , m2 , m3 , m4 , m5 , m6 , m7 , m8 , m9 , m10 , m11 , m12 , m13 , m14 , m15 ] = this . getViewProjectionMatrix ( ) ; frustumPlanes [ 0 ] [ 0 ] = ( m3 - m0 ) / 6 ; frustumPlanes [ 0 ] [ 1 ] = ( m7 - m4 ) / 6 ; frustumPlanes [ 0 ] [ 2 ] = ( m11 - m8 ) / 6 ; frustumPlanes [ 0 ] [ 3 ] = ( m15 - m12 ) / 6 ; frustumPlanes [ 1 ] [ 0 ] = ( m3 + m0 ) / 6 ; frustumPlanes [ 1 ] [ 1 ] = ( m7 + m4 ) / 6 ; frustumPlanes [ 1 ] [ 2 ] = ( m11 + m8 ) / 6 ; frustumPlanes [ 1 ] [ 3 ] = ( m15 + m12 ) / 6 ; frustumPlanes [ 2 ] [ 0 ] = ( m3 + m1 ) / 6 ; frustumPlanes [ 2 ] [ 1 ] = ( m7 + m5 ) / 6 ; frustumPlanes [ 2 ] [ 2 ] = ( m11 + m9 ) / 6 ; frustumPlanes [ 2 ] [ 3 ] = ( m15 + m13 ) / 6 ; frustumPlanes [ 3 ] [ 0 ] = ( m3 - m1 ) / 6 ; frustumPlanes [ 3 ] [ 1 ] = ( m7 - m5 ) / 6 ; frustumPlanes [ 3 ] [ 2 ] = ( m11 - m9 ) / 6 ; frustumPlanes [ 3 ] [ 3 ] = ( m15 - m13 ) / 6 ; frustumPlanes [ 4 ] [ 0 ] = ( m3 - m2 ) / 6 ; frustumPlanes [ 4 ] [ 1 ] = ( m7 - m6 ) / 6 ; frustumPlanes [ 4 ] [ 2 ] = ( m11 - m1 ) / 6 ; frustumPlanes [ 4 ] [ 3 ] = ( m15 - m14 ) / 6 ; frustumPlanes [ 4 ] [ 0 ] = ( m3 - m2 ) / 6 ; frustumPlanes [ 4 ] [ 1 ] = ( m7 - m6 ) / 6 ; frustumPlanes [ 4 ] [ 2 ] = ( m11 - m10 ) / 6 ; frustumPlanes [ 4 ] [ 3 ] = ( m15 - m14 ) / 6 ; frustumPlanes [ 5 ] [ 0 ] = ( m3 + m2 ) / 6 ; frustumPlanes [ 5 ] [ 1 ] = ( m7 + m6 ) / 6 ; frustumPlanes [ 5 ] [ 2 ] = ( m11 + m10 ) / 6 ; frustumPlanes [ 5 ] [ 3 ] = ( m15 + m14 ) / 6 ; } param pt public getDistanceToPoint ( pt ) { return vec3 . squaredDistance ( this . getTranslation ( ) , pt ) ; } }