From 5ff9894925b110e700cd186f4485edc97d744b94 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Thu, 17 Sep 2020 18:08:07 +0100 Subject: [PATCH] MeshCamera now supports orbit and pan modes --- src/gameobjects/mesh/MeshCamera.js | 175 ++++++++++++++++++++++++++--- 1 file changed, 158 insertions(+), 17 deletions(-) diff --git a/src/gameobjects/mesh/MeshCamera.js b/src/gameobjects/mesh/MeshCamera.js index 089266ea1..2030ed55c 100644 --- a/src/gameobjects/mesh/MeshCamera.js +++ b/src/gameobjects/mesh/MeshCamera.js @@ -8,6 +8,7 @@ var Class = require('../../utils/Class'); var DegToRad = require('../../math/DegToRad'); var Matrix4 = require('../../math/Matrix4'); var Vector3 = require('../../math/Vector3'); +var Vector4 = require('../../math/Vector4'); /** * @classdesc @@ -31,24 +32,116 @@ var MeshCamera = new Class({ this._near = near; this._far = far; - this._position = new Vector3(x, y, z); - this._target = new Vector3(); + this.position = new Vector3(); + this.rotation = new Vector3(); - this.orientation = Vector3.DOWN; + this.forward = new Vector4(); + this.up = new Vector4(); // What the up direction is, invert to get bottom + this.right = new Vector4(); // What the right direction is, invert to get left + this.matView = new Matrix4(); this.viewMatrix = new Matrix4(); this.projectionMatrix = new Matrix4(); + + this.mode = MeshCamera.MODE_ORBIT; + }, + + panX: function (v) + { + this.updateViewMatrix(); + + this.position.addScale(this.right, v); + }, + + panY: function (v) + { + this.updateViewMatrix(); + + this.position.y += this.up.y * v; + + if (this.mode === MeshCamera.MODE_ORBIT) + { + // Can only move up and down the y axix in orbit mode + return; + } + + this.position.x += this.up.x * v; + this.position.z += this.up.z * v; + }, + + panZ: function (v) + { + this.updateViewMatrix(); + + if (this.mode === MeshCamera.MODE_ORBIT) + { + // orbit mode does translate after rotate, so only need to set Z, the rotate will handle the rest. + this.position.z += v; + } + else + { + // In freemode to move forward, we need to move based on our forward which is relative to our current rotation + this.position.addScale(this.forward, v); + } + }, + + // To have different modes of movements, this function handles the view matrix update for the transform object. + updateViewMatrix: function () + { + var d = Math.PI / 180; + var matView = this.matView; + var rotation = this.rotation; + + matView.identity(); + + // Optimize camera transform update, no need for scale nor rotateZ + if (this.mode === MeshCamera.MODE_FREE) + { + matView.translate(this.position); + matView.rotateX(rotation.x * d); + matView.rotateY(rotation.y * d); + } + else + { + matView.rotateX(rotation.x * d); + matView.rotateY(rotation.y * d); + matView.translate(this.position); + } + + this.updateDirection(); + + this.viewMatrix.copy(matView); + this.viewMatrix.invert(); + + this.dirty = true; }, update: function (width, height) { this.aspectRatio = width / height; - this.viewMatrix.lookAt(this._position, this._target, this.orientation); + this.updateViewMatrix(); this.projectionMatrix.perspective(DegToRad(this._fov), this.aspectRatio, this._near, this._far); }, + updateDirection: function () + { + var matView = this.matView; + + this.forward.set(0, 0, 1, 0).transformMat4(matView); + this.up.set(0, 1, 0, 0).transformMat4(matView); + this.right.set(1, 0, 0, 0).transformMat4(matView); + }, + + reset: function () + { + this.position.set(); + this.rotation.set(); + + this.updateViewMatrix(); + }, + fov: { get: function () @@ -107,13 +200,13 @@ var MeshCamera = new Class({ get: function () { - return this._position.x; + return this.position.x; }, set: function (value) { - this._position.x = value; - this.dirty = true; + this.position.x = value; + this.updateViewMatrix(); } }, @@ -122,13 +215,13 @@ var MeshCamera = new Class({ get: function () { - return this._position.y; + return this.position.y; }, set: function (value) { - this._position.y = value; - this.dirty = true; + this.position.y = value; + this.updateViewMatrix(); } }, @@ -137,25 +230,73 @@ var MeshCamera = new Class({ get: function () { - return this._position.z; + return this.position.z; }, set: function (value) { - this._position.z = value; - this.dirty = true; + this.position.z = value; + this.updateViewMatrix(); + } + + }, + + rotationX: { + + get: function () + { + return this.rotation.x; + }, + + set: function (value) + { + this.rotation.x = value; + this.updateViewMatrix(); + } + + }, + + rotationY: { + + get: function () + { + return this.rotation.y; + }, + + set: function (value) + { + this.rotation.y = value; + this.updateViewMatrix(); + } + + }, + + rotationZ: { + + get: function () + { + return this.rotation.z; + }, + + set: function (value) + { + this.rotation.z = value; + this.updateViewMatrix(); } }, destroy: function () { - this._position = null; - this._target = null; - this.viewMatrix = null; - this.projectionMatrix = null; + // TODO - Needed? } }); +// Allows free movement of position and rotation +MeshCamera.MODE_FREE = 0; + +// Movement is locked to rotate around the origin +MeshCamera.MODE_ORBIT = 1; + module.exports = MeshCamera;