UNPKG

planck-js

Version:

2D physics engine for JavaScript/HTML5 game development

198 lines (179 loc) 4.92 kB
/* * Copyright (c) 2016 Ali Shakiba http://shakiba.me/planck.js * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ module.exports = Mat33; var Math = require('./Math'); var Vec2 = require('./Vec2'); var Vec3 = require('./Vec3'); /** * A 3-by-3 matrix. Stored in column-major order. */ function Mat33(a, b, c) { if (typeof a === 'object' && a !== null) { this.ex = Vec3.Clone(a); this.ey = Vec3.Clone(b); this.ez = Vec3.Clone(c); } else { this.ex = Vec3(); this.ey = Vec3() this.ez = Vec3(); } }; Mat33.prototype.toString = function() { return JSON.stringify(this); }; Mat33.IsValid = function(o) { return o && Vec3.IsValid(o.ex) && Vec3.IsValid(o.ey) && Vec3.IsValid(o.ez); }; Mat33.Assert = function(o) { if (!Mat33.IsValid(o)) { console.log(o); throw new Error('Invalid Mat33!'); } }; /** * Set this matrix to all zeros. */ Mat33.prototype.SetZero = function() { this.ex.SetZero(); this.ey.SetZero(); this.ez.SetZero(); return this; } /** * Solve A * x = b, where b is a column vector. This is more efficient than * computing the inverse in one-shot cases. * * @param {Vec3} v * @returns {Vec3} */ Mat33.prototype.Solve33 = function(v) { var det = Vec3.Dot(this.ex, Vec3.Cross(this.ey, this.ez)); if (det != 0.0) { det = 1.0 / det; } var r = new Vec3(); r.x = det * Vec3.Dot(v, Vec3.Cross(this.ey, this.ez)); r.y = det * Vec3.Dot(this.ex, Vec3.Cross(v, this.ez)); r.z = det * Vec3.Dot(this.ex, Vec3.Cross(this.ey, v)); return r; } /** * Solve A * x = b, where b is a column vector. This is more efficient than * computing the inverse in one-shot cases. Solve only the upper 2-by-2 matrix * equation. * * @param {Vec2} v * * @returns {Vec2} */ Mat33.prototype.Solve22 = function(v) { var a11 = this.ex.x; var a12 = this.ey.x; var a21 = this.ex.y; var a22 = this.ey.y; var det = a11 * a22 - a12 * a21; if (det != 0.0) { det = 1.0 / det; } var r = new Vec2(); r.x = det * (a22 * v.x - a12 * v.y); r.y = det * (a11 * v.y - a21 * v.x); return r; } /** * Get the inverse of this matrix as a 2-by-2. Returns the zero matrix if * singular. * * @param {Mat33} M */ Mat33.prototype.GetInverse22 = function(M) { var a = this.ex.x; var b = this.ey.x; var c = this.ex.y; var d = this.ey.y; var det = a * d - b * c; if (det != 0.0) { det = 1.0 / det; } M.ex.x = det * d; M.ey.x = -det * b; M.ex.z = 0.0; M.ex.y = -det * c; M.ey.y = det * a; M.ey.z = 0.0; M.ez.x = 0.0; M.ez.y = 0.0; M.ez.z = 0.0; } /** * Get the symmetric inverse of this matrix as a 3-by-3. Returns the zero matrix * if singular. * * @param {Mat33} M */ Mat33.prototype.GetSymInverse33 = function(M) { var det = Vec3.Dot(this.ex, Vec3.Cross(this.ey, this.ez)); if (det != 0.0) { det = 1.0 / det; } var a11 = this.ex.x; var a12 = this.ey.x; var a13 = this.ez.x; var a22 = this.ey.y; var a23 = this.ez.y; var a33 = this.ez.z; M.ex.x = det * (a22 * a33 - a23 * a23); M.ex.y = det * (a13 * a23 - a12 * a33); M.ex.z = det * (a12 * a23 - a13 * a22); M.ey.x = M.ex.y; M.ey.y = det * (a11 * a33 - a13 * a13); M.ey.z = det * (a13 * a12 - a11 * a23); M.ez.x = M.ex.z; M.ez.y = M.ey.z; M.ez.z = det * (a11 * a22 - a12 * a12); } /** * Multiply a matrix times a vector. * * @param {Mat33} a * @param {Vec3|Vec2} b * * @returns {Vec3|Vec2} */ Mat33.Mul = function(a, b) { Mat33.Assert(a); if (b && 'z' in b && 'y' in b && 'x' in b) { Vec3.Assert(b); var x = a.ex.x * b.x + a.ey.x * b.y + a.ez.x * b.z; var y = a.ex.y * b.x + a.ey.y * b.y + a.ez.y * b.z; var z = a.ex.z * b.x + a.ey.z * b.y + a.ez.z * b.z; return new Vec3(x, y, z); } else if (b && 'y' in b && 'x' in b) { Vec2.Assert(b); var x = a.ex.x * b.x + a.ey.x * b.y; var y = a.ex.y * b.x + a.ey.y * b.y; return new Vec2(x, y); } Assert(false); } Mat33.Add = function(a, b) { Mat33.Assert(a); Mat33.Assert(b); return new Vec3(a.x + b.x, a.y + b.y, a.z + b.z); }