// ********************************************************************************************************************** // // Copyright (c)2011, YoYo Games Ltd. All Rights reserved. // // File: Matrix.js // Created: 02/06/2011 // Author: Mike // Project: HTML5 // Description: Simple 4x4 Matrix class // // Date Version BY Comment // ---------------------------------------------------------------------------------------------------------------------- // 01/12/2011 V1.0 MJD 1st version // // ********************************************************************************************************************** var _11 = 0; var _12 = 1; var _13 = 2; var _14 = 3; var _21 = 4; var _22 = 5; var _23 = 6; var _24 = 7; var _31 = 8; var _32 = 9; var _33 = 10; var _34 = 11; var _41 = 12; var _42 = 13; var _43 = 14; var _44 = 15; var __00 = 0; var __01 = 1; var __02 = 2; var __03 = 3; var __10 = 4; var __11 = 5; var __12 = 6; var __13 = 7; var __20 = 8; var __21 = 9; var __22 = 10; var __23 = 11; var __30 = 12; var __31 = 13; var __32 = 14; var __33 = 15; // ############################################################################################# /// Function:

/// Create a new matrix object /// // ############################################################################################# /** @constructor * @param {Object=} _matrix Some value (optional). */ function Matrix( _matrix ) { this.m = new Float32Array( 16 ); if (arguments.length > 0) { var srcMatrix = _matrix.m || _matrix; // Copy the matrix for (var i = 0; i /// Create a new matrix object /// // ############################################################################################# //function Equals( _matrix ) { // // for (var i=0; i /// Set the matrix to be a UNIT matrix /// // ############################################################################################# Matrix.prototype.identity = function (v2) { this.m[1] = this.m[2] = this.m[3] = this.m[4] = this.m[6] = this.m[7] = this.m[8] = this.m[9] = this.m[11] = this.m[12] = this.m[13] = this.m[14] = 0.0; this.m[0] = this.m[5] = this.m[10] = this.m[15] = 1.0; }; // ############################################################################################# /// Property: /// Set the matrix to be a UNIT matrix /// // ############################################################################################# Matrix.prototype.unit = function (v2) { this.m[1] = this.m[2] = this.m[3] = this.m[4] = this.m[6] = this.m[7] = this.m[8] = this.m[9] = this.m[11] = this.m[12] = this.m[13] = this.m[14] = 0.0; this.m[0] = this.m[5] = this.m[10] = this.m[15] = 1.0; }; // ############################################################################################# /// Property: /// Copies the values of a given matrix /// // ############################################################################################# Matrix.prototype.Copy = function (_copy) { for (var i = 0; i /// Create a LookAT Vector /// /// /// In:
OUT: Destination matrix ///
Current position /// Look AT position /// Up vector /// // ############################################################################################# Matrix.prototype.LookAtLH = function( _pPos, _pAt, _pUp) { var Up = new Vector3(_pUp); var Right = new Vector3(); var Look = _pAt.Sub( _pPos ); Look.Normalise(); Up.Normalise(); Right.SetCrossProduct(Up,Look); Right.Normalise(); Up.SetCrossProduct(Look,Right); Up.Normalise(); var X = _pPos.Projection(Right); var Y = _pPos.Projection(Up); var Z = _pPos.Projection(Look); this.m[_11] = Right.X; this.m[_12] = Up.X; this.m[_13] = Look.X; this.m[_14] = 0.0; this.m[_21] = Right.Y; this.m[_22] = Up.Y; this.m[_23] = Look.Y; this.m[_24] = 0.0; this.m[_31] = Right.Z; this.m[_32] = Up.Z; this.m[_33] = Look.Z; this.m[_34] = 0.0; this.m[_41] = -X; this.m[_42] = -Y; this.m[_43] = -Z; this.m[_44] = 1; }; // ############################################################################################# /// Function: /// Builds a left-handed perspective projection matrix based on a field of view. /// /// /// In: OUT: Destination matrix /// /// /// /// /// // ############################################################################################# Matrix.prototype.PerspectiveFovLH = function( _fovY, _aspect, _zn, _zf ) { if ((_fovY == 0.0) || (_aspect == 0.0) || (_zn == _zf)) { // avoid divide by zero this.unit(); return; } var a = Deg2Rad(_fovY); var yScale = 1.0 / Math.tan(a * 0.5); var xScale = yScale / _aspect; this.m[_11] = xScale; this.m[_12] = this.m[_13] = this.m[_14] = 0.0; this.m[_22] = yScale; this.m[_21] = this.m[_23] = this.m[_24] = 0.0; this.m[_31] = this.m[_32] = 0.0; this.m[_34] = 1.0; this.m[_33] = _zf / (_zf - _zn); this.m[_41] = this.m[_42] = this.m[_44] = 0.0; this.m[_43] = -_zn*_zf / (_zf - _zn); }; // ############################################################################################# /// Function: /// Builds a left-handed perspective projection matrix /// /// /// In: OUT: Destination matrix /// Width of viewport /// Height of viewport /// Near Z /// Far Z /// // ############################################################################################# Matrix.prototype.PerspectiveLH = function (_w, _h, _zn, _zf) { if ((_w == 0.0) || (_h == 0.0) || (_zn == _zf)) { // avoid divide by zero this.unit(); return; } this.m[_11] = 2*_zn / _w; this.m[_12] = this.m[_13] = this.m[_14] = 0.0; this.m[_22] = 2*_zn / _h; this.m[_21] = this.m[_23] = this.m[_24] = 0.0; this.m[_31] = this.m[_32] = 0.0; this.m[_34] = 1.0; this.m[_33] = _zf / (_zf - _zn); this.m[_41] = this.m[_42] = this.m[_44] = 0.0; this.m[_43] = -_zn*_zf / (_zf - _zn); }; // ############################################################################################# /// Function: /// Builds a left-handed orthographic projection matrix. /// /// /// In: OUT: Destination matrix /// Width of viewport /// Height of viewport /// Near Z /// Far Z /// Out: /// /// // ############################################################################################# Matrix.prototype.OrthoLH= function (_w, _h, _zn, _zf) { if ((_w == 0.0) || (_h == 0.0) || (_zn == _zf)) { // avoid divide by zero this.unit(); return; } this.m[_11] = 2.0/ _w; this.m[_12] = this.m[_13] = 0.0; this.m[_14] = 0; this.m[_22] = 2.0/_h; this.m[_21] = this.m[_23] = 0.0; this.m[_24] = 0; this.m[_31] = this.m[_32] =0.0; this.m[_33] = 1.0 / (_zf - _zn); this.m[_34] = 0; this.m[_41] = this.m[_42] = 0.0; this.m[_43] = _zn / (_zn - _zf); this.m[_44] = 1.0; }; // ############################################################################################# /// Function: /// 4x4 matric multiply /// /// /// In: OUT: Dest Matrix /// Source 1 /// Source 2 /// // ############################################################################################# Matrix.prototype.Multiply = function (_pS1, _pS2) { this.m[_11] = (_pS1.m[_11] * _pS2.m[_11]) + (_pS1.m[_12] * _pS2.m[_21]) + (_pS1.m[_13] * _pS2.m[_31]) + (_pS1.m[_14] * _pS2.m[_41]); this.m[_12] = (_pS1.m[_11] * _pS2.m[_12]) + (_pS1.m[_12] * _pS2.m[_22]) + (_pS1.m[_13] * _pS2.m[_32]) + (_pS1.m[_14] * _pS2.m[_42]); this.m[_13] = (_pS1.m[_11] * _pS2.m[_13]) + (_pS1.m[_12] * _pS2.m[_23]) + (_pS1.m[_13] * _pS2.m[_33]) + (_pS1.m[_14] * _pS2.m[_43]); this.m[_14] = (_pS1.m[_11] * _pS2.m[_14]) + (_pS1.m[_12] * _pS2.m[_24]) + (_pS1.m[_13] * _pS2.m[_34]) + (_pS1.m[_14] * _pS2.m[_44]); this.m[_21] = (_pS1.m[_21] * _pS2.m[_11]) + (_pS1.m[_22] * _pS2.m[_21]) + (_pS1.m[_23] * _pS2.m[_31]) + (_pS1.m[_24] * _pS2.m[_41]); this.m[_22] = (_pS1.m[_21] * _pS2.m[_12]) + (_pS1.m[_22] * _pS2.m[_22]) + (_pS1.m[_23] * _pS2.m[_32]) + (_pS1.m[_24] * _pS2.m[_42]); this.m[_23] = (_pS1.m[_21] * _pS2.m[_13]) + (_pS1.m[_22] * _pS2.m[_23]) + (_pS1.m[_23] * _pS2.m[_33]) + (_pS1.m[_24] * _pS2.m[_43]); this.m[_24] = (_pS1.m[_21] * _pS2.m[_14]) + (_pS1.m[_22] * _pS2.m[_24]) + (_pS1.m[_23] * _pS2.m[_34]) + (_pS1.m[_24] * _pS2.m[_44]); this.m[_31] = (_pS1.m[_31] * _pS2.m[_11]) + (_pS1.m[_32] * _pS2.m[_21]) + (_pS1.m[_33] * _pS2.m[_31]) + (_pS1.m[_34] * _pS2.m[_41]); this.m[_32] = (_pS1.m[_31] * _pS2.m[_12]) + (_pS1.m[_32] * _pS2.m[_22]) + (_pS1.m[_33] * _pS2.m[_32]) + (_pS1.m[_34] * _pS2.m[_42]); this.m[_33] = (_pS1.m[_31] * _pS2.m[_13]) + (_pS1.m[_32] * _pS2.m[_23]) + (_pS1.m[_33] * _pS2.m[_33]) + (_pS1.m[_34] * _pS2.m[_43]); this.m[_34] = (_pS1.m[_31] * _pS2.m[_14]) + (_pS1.m[_32] * _pS2.m[_24]) + (_pS1.m[_33] * _pS2.m[_34]) + (_pS1.m[_34] * _pS2.m[_44]); this.m[_41] = (_pS1.m[_41] * _pS2.m[_11]) + (_pS1.m[_42] * _pS2.m[_21]) + (_pS1.m[_43] * _pS2.m[_31]) + (_pS1.m[_44] * _pS2.m[_41]); this.m[_42] = (_pS1.m[_41] * _pS2.m[_12]) + (_pS1.m[_42] * _pS2.m[_22]) + (_pS1.m[_43] * _pS2.m[_32]) + (_pS1.m[_44] * _pS2.m[_42]); this.m[_43] = (_pS1.m[_41] * _pS2.m[_13]) + (_pS1.m[_42] * _pS2.m[_23]) + (_pS1.m[_43] * _pS2.m[_33]) + (_pS1.m[_44] * _pS2.m[_43]); this.m[_44] = (_pS1.m[_41] * _pS2.m[_14]) + (_pS1.m[_42] * _pS2.m[_24]) + (_pS1.m[_43] * _pS2.m[_34]) + (_pS1.m[_44] * _pS2.m[_44]); }; // ############################################################################################# /// Function: /// Set the destination to a Z Rotation matrix /// /// /// In: Destination matrix /// angle in degrees /// // ############################################################################################# Matrix.prototype.SetZRotation = function( _angle ) { this.unit(); var a = Deg2Rad(_angle); var s = Math.sin(a); var c = Math.cos(a); this.m[_11] = c; this.m[_12] = -s; this.m[_21] = s; this.m[_22] = c; }; // ############################################################################################# /// Function: /// Set the destination to a Z Rotation matrix /// /// /// In: Destination matrix /// angle in degrees /// // ############################################################################################# Matrix.prototype.SetYRotation = function ( _angle ) { this.unit(); var a = Deg2Rad(_angle); var s = Math.sin(a); var c = Math.cos(a); this.m[_11] = c; this.m[_13] = s; this.m[_31] = -s; this.m[_33] = c; }; // ############################################################################################# /// Function: /// Set the destination to a Z Rotation matrix /// /// /// In: Destination matrix /// angle in degrees /// // ############################################################################################# Matrix.prototype.SetXRotation = function( _angle ) { this.unit(); var a = Deg2Rad(_angle); var s = Math.sin(a); var c = Math.cos(a); this.m[_22] = c; this.m[_23] = -s; this.m[_32] = s; this.m[_33] = c; }; // ############################################################################################# /// Function: /// Build a translation matrix /// // ############################################################################################# Matrix.prototype.SetTranslation = function(_x, _y, _z) { this.unit(); this.m[_41] = _x; this.m[_42] = _y; this.m[_43] = _z; }; // ############################################################################################# /// Function: /// Translate the matrix /// /// /// In: X offset /// Y offset /// Z offset /// // ############################################################################################# Matrix.prototype.Translation = function (_x, _y, _z) { this.m[_41] += _x; this.m[_42] += _y; this.m[_43] += _z; }; // ############################################################################################# /// Function: /// Build a scale matrix /// // ############################################################################################# Matrix.prototype.SetScale = function(_xs, _ys, _zs) { this.unit(); this.m[_11] = _xs; this.m[_22] = _ys; this.m[_33] = _zs; }; // ############################################################################################# /// Function: /// Retrieves maximum unit scale. /// // ############################################################################################# Matrix.prototype.GetMaximumUnitScale = function () { var scaleX = Math.sqrt( (this.m[_11] * this.m[_11]) + (this.m[_21] * this.m[_21]) + (this.m[_31] * this.m[_31])); var scaleY = Math.sqrt( (this.m[_12] * this.m[_12]) + (this.m[_22] * this.m[_22]) + (this.m[_32] * this.m[_32])); var scaleZ = Math.sqrt( (this.m[_13] * this.m[_13]) + (this.m[_23] * this.m[_23]) + (this.m[_33] * this.m[_33])); return Math.max(scaleX, scaleY, scaleZ); }; // ############################################################################################# /// Function: /// Builds a matrix that rotates around an arbitrary axis. /// // ############################################################################################# Matrix.prototype.SetRotationAxis = function (_v, _angle) { _v.Normalise(); var a = Deg2Rad(_angle); var c = Math.cos(a); var s = Math.sin(a); var omc = 1.0 - c; this.unit(); this.m[0] = (omc * _v.X * _v.X + c); this.m[1] = (omc * _v.X * _v.Y + s * _v.Z); this.m[2] = (omc * _v.X * _v.Z - s * _v.Y); this.m[4] = (omc * _v.X * _v.Y - s * _v.Z); this.m[5] = (omc * _v.Y * _v.Y + c); this.m[6] = (omc * _v.Y * _v.Z + s * _v.X); this.m[8] = (omc * _v.X * _v.Z + s * _v.Y); this.m[9] = (omc * _v.Y * _v.Z - s * _v.X); this.m[10] = (omc * _v.Z * _v.Z + c); }; // ############################################################################################# /// Function: /// Build a full 2D matrix, assuming an orthographic view matrix is in play /// // ############################################################################################# Matrix.prototype.Build2DMatrix = function (_x, _y, _xs, _ys, _rot) { this.unit(); // Do a z-rotate var a = Deg2Rad(_rot); var s = Math.sin(a); var c = Math.cos(a); this.m[_11] = c; this.m[_12] = -s; this.m[_21] = s; this.m[_22] = c; // Set scale this.m[_11] *= _xs; this.m[_22] *= _ys; // Set transform this.m[_41] = _x; this.m[_42] = _y; }; // ############################################################################################# /// Function: /// Build a full fat matrix /// /// /// In: X translation /// Y translation /// Z translation /// X Rotation /// Y Rotation /// Z Rotation /// X Scale /// Y Scale /// Z Scale /// Out: /// Full fat matrix is build /// // ############################################################################################# Matrix.prototype.BuildMatrix = function ( _x,_y,_z, _xrot,_yrot,_zrot, _xscale,_yscale,_zscale ) { var sinp = Math.sin(_xrot); var cosp = Math.cos(_xrot); var sinh = Math.sin(_yrot); var cosh = Math.cos(_yrot); var sinr = Math.sin(_zrot); var cosr = Math.cos(_zrot); var sinrsinp = -sinr*-sinp; // common elements var cosrsinp = cosr*-sinp; this.m[0] = ((cosr * cosh) + (sinrsinp * -sinh)) * _xscale; this.m[4] = (-sinr * cosp) * _xscale; this.m[8] = ((cosr * sinh) + (sinrsinp * cosh)) * _xscale; this.m[12] = _x; this.m[1] = ((sinr * cosh) + (cosrsinp * -sinh)) * _yscale; this.m[5] = (cosr * cosp) * _yscale; this.m[9] = ((sinr * sinh) + (cosrsinp * cosh)) * _yscale; this.m[13] = _y; this.m[2] = (cosp * -sinh) * _zscale; this.m[6] = sinp * _zscale; this.m[10] = (cosp * cosh) * _zscale; this.m[14] = _z; this.m[3] = this.m[7] = this.m[11] = 0.0; this.m[15] = 1.0; }; Matrix.prototype.Invert = function(that) { var s0 = that.m[__00] * that.m[__11] - that.m[__10] * that.m[__01]; var s1 = that.m[__00] * that.m[__12] - that.m[__10] * that.m[__02]; var s2 = that.m[__00] * that.m[__13] - that.m[__10] * that.m[__03]; var s3 = that.m[__01] * that.m[__12] - that.m[__11] * that.m[__02]; var s4 = that.m[__01] * that.m[__13] - that.m[__11] * that.m[__03]; var s5 = that.m[__02] * that.m[__13] - that.m[__12] * that.m[__03]; var c5 = that.m[__22] * that.m[__33] - that.m[__32] * that.m[__23]; var c4 = that.m[__21] * that.m[__33] - that.m[__31] * that.m[__23]; var c3 = that.m[__21] * that.m[__32] - that.m[__31] * that.m[__22]; var c2 = that.m[__20] * that.m[__33] - that.m[__30] * that.m[__23]; var c1 = that.m[__20] * that.m[__32] - that.m[__30] * that.m[__22]; var c0 = that.m[__20] * that.m[__31] - that.m[__30] * that.m[__21]; var det = (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0); if(det!=0) { var invdet = 1.0/det; var b = new Float32Array(16); b[__00] = ( that.m[__11] * c5 - that.m[__12] * c4 + that.m[__13] * c3) * invdet; b[__01] = (-that.m[__01] * c5 + that.m[__02] * c4 - that.m[__03] * c3) * invdet; b[__02] = ( that.m[__31] * s5 - that.m[__32] * s4 + that.m[__33] * s3) * invdet; b[__03] = (-that.m[__21] * s5 + that.m[__22] * s4 - that.m[__23] * s3) * invdet; b[__10] = (-that.m[__10] * c5 + that.m[__12] * c2 - that.m[__13] * c1) * invdet; b[__11] = ( that.m[__00] * c5 - that.m[__02] * c2 + that.m[__03] * c1) * invdet; b[__12] = (-that.m[__30] * s5 + that.m[__32] * s2 - that.m[__33] * s1) * invdet; b[__13] = ( that.m[__20] * s5 - that.m[__22] * s2 + that.m[__23] * s1) * invdet; b[__20] = ( that.m[__10] * c4 - that.m[__11] * c2 + that.m[__13] * c0) * invdet; b[__21] = (-that.m[__00] * c4 + that.m[__01] * c2 - that.m[__03] * c0) * invdet; b[__22] = ( that.m[__30] * s4 - that.m[__31] * s2 + that.m[__33] * s0) * invdet; b[__23] = (-that.m[__20] * s4 + that.m[__21] * s2 - that.m[__23] * s0) * invdet; b[__30] = (-that.m[__10] * c3 + that.m[__11] * c1 - that.m[__12] * c0) * invdet; b[__31] = ( that.m[__00] * c3 - that.m[__01] * c1 + that.m[__02] * c0) * invdet; b[__32] = (-that.m[__30] * s3 + that.m[__31] * s1 - that.m[__32] * s0) * invdet; b[__33] = ( that.m[__20] * s3 - that.m[__21] * s1 + that.m[__22] * s0) * invdet; this.m = b; } if (det != 0) { return true; } else { return false; // indicate that we couldn't invert the matrix } }; Matrix.prototype.TransformVec3 = function(_vec) { var newvec = new Vector3(0.0,0.0,0.0); if (_vec != undefined) { newvec.X = (this.m[_11] * _vec.X) + (this.m[_21] * _vec.Y) + (this.m[_31] * _vec.Z) + this.m[_41]; newvec.Y = (this.m[_12] * _vec.X) + (this.m[_22] * _vec.Y) + (this.m[_32] * _vec.Z) + this.m[_42]; newvec.Z = (this.m[_13] * _vec.X) + (this.m[_23] * _vec.Y) + (this.m[_33] * _vec.Z) + this.m[_43]; } return newvec; };