UNPKG

ts-game-engine

Version:

Simple WebGL game/render engine written in TypeScript

112 lines (111 loc) 6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Entity_1 = require("./Entity"); const gl_matrix_1 = require("gl-matrix"); const Frustum_1 = require("../Math/Frustum"); class Camera extends Entity_1.Entity { constructor(scene, name) { super(scene, name); this.fov = 45; this.near = 0.1; this.far = 1000; this.viewMatrix = gl_matrix_1.mat4.create(); this.projectionMatrix = gl_matrix_1.mat4.create(); this.viewDirectionProjectionInverseMatrix = gl_matrix_1.mat4.create(); this.frustum = new Frustum_1.Frustum(); this.isViewMatrixDirty = true; this.isProjectionMatrixDirty = true; this.isViewDirectionProjectionDirty = true; this.isFrustumDirty = true; this.Transform.OnTransformChange = () => this.isViewMatrixDirty = true; } get FOV() { return this.fov; } set FOV(fov) { if (this.fov === fov) return; this.fov = fov; this.isProjectionMatrixDirty = true; } get Near() { return this.near; } set Near(near) { if (this.near === near) return; this.near = near; this.isProjectionMatrixDirty = true; } get Far() { return this.far; } set Far(far) { if (this.far === far) return; this.far = far; this.isProjectionMatrixDirty = true; } get ViewMatrix() { return this.viewMatrix; } get ProjectionMatrix() { return this.projectionMatrix; } get ViewDirectionProjectionInverseMatrix() { return this.viewDirectionProjectionInverseMatrix; } get Frustum() { return this.frustum; } Update(deltaTime) { super.Update(deltaTime); if (this.isViewMatrixDirty) this.UpdateViewMatrix(); if (this.isProjectionMatrixDirty) this.UpdateProjectionMatrix(); if (this.isViewDirectionProjectionDirty) this.UpdateViewDirectionProjectionMatrices(); if (this.isFrustumDirty) this.UpdateFrustum(); } Resize(width, height) { this.isProjectionMatrixDirty = true; } UpdateViewMatrix() { let position = this.Transform.Position; let target = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.add(target, position, this.Transform.Forward); gl_matrix_1.mat4.lookAt(this.viewMatrix, position, target, this.Transform.Up); this.isViewDirectionProjectionDirty = true; this.isFrustumDirty = true; this.isViewMatrixDirty = false; } UpdateProjectionMatrix() { gl_matrix_1.mat4.perspective(this.projectionMatrix, gl_matrix_1.glMatrix.toRadian(this.fov), this.Scene.Game.GraphicsSystem.AspectRatio, this.near, this.far); this.isViewDirectionProjectionDirty = true; this.isFrustumDirty = true; this.isProjectionMatrixDirty = false; } UpdateViewDirectionProjectionMatrices() { gl_matrix_1.mat4.copy(this.viewDirectionProjectionInverseMatrix, this.viewMatrix); this.viewDirectionProjectionInverseMatrix[12] = 0; this.viewDirectionProjectionInverseMatrix[13] = 0; this.viewDirectionProjectionInverseMatrix[14] = 0; gl_matrix_1.mat4.multiply(this.viewDirectionProjectionInverseMatrix, this.projectionMatrix, this.viewDirectionProjectionInverseMatrix); gl_matrix_1.mat4.invert(this.viewDirectionProjectionInverseMatrix, this.viewDirectionProjectionInverseMatrix); this.isViewDirectionProjectionDirty = false; } UpdateFrustum() { let t = 2 * Math.tan(gl_matrix_1.glMatrix.toRadian(this.fov) / 2); const aspectRatio = this.Scene.Game.GraphicsSystem.AspectRatio; let Hnear = t * this.near; let Wnear = Hnear * aspectRatio; let Hfar = t * this.far; let Wfar = Hfar * aspectRatio; let fc = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.scaleAndAdd(fc, this.Transform.Position, this.Transform.Forward, this.far); let temp1 = gl_matrix_1.vec3.create(); let temp2 = gl_matrix_1.vec3.create(); let ftl = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.add(ftl, fc, gl_matrix_1.vec3.subtract(ftl, gl_matrix_1.vec3.scale(temp1, this.Transform.Up, Hfar / 2), gl_matrix_1.vec3.scale(temp2, this.Transform.Right, Wfar / 2))); let ftr = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.scaleAndAdd(ftr, ftl, this.Transform.Right, Wfar); let fbl = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.subtract(fbl, ftl, gl_matrix_1.vec3.scale(fbl, this.Transform.Up, Hfar)); let fbr = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.subtract(fbr, ftr, gl_matrix_1.vec3.scale(fbr, this.Transform.Up, Hfar)); let nc = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.scaleAndAdd(nc, this.Transform.Position, this.Transform.Forward, this.near); let ntl = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.add(ntl, nc, gl_matrix_1.vec3.subtract(ntl, gl_matrix_1.vec3.scale(temp1, this.Transform.Up, Hnear / 2), gl_matrix_1.vec3.scale(temp2, this.Transform.Right, Wnear / 2))); let ntr = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.scaleAndAdd(ntr, ntl, this.Transform.Right, Wnear); let nbl = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.subtract(nbl, ntl, gl_matrix_1.vec3.scale(nbl, this.Transform.Up, Hnear)); let nbr = gl_matrix_1.vec3.create(); gl_matrix_1.vec3.subtract(nbr, ntr, gl_matrix_1.vec3.scale(nbr, this.Transform.Up, Hnear)); this.frustum.Planes[0].SetPoints(ntr, ntl, ftl); //Top this.frustum.Planes[1].SetPoints(nbl, nbr, fbr); //Bottom this.frustum.Planes[2].SetPoints(ntl, nbl, fbl); //Left this.frustum.Planes[3].SetPoints(nbr, ntr, fbr); //Right this.frustum.Planes[4].SetPoints(ntl, ntr, nbr); //Near this.frustum.Planes[5].SetPoints(ftr, ftl, fbl); //Far this.isFrustumDirty = false; } } exports.Camera = Camera;