UNPKG

planck-js

Version:

2D physics engine for JavaScript/HTML5 game development

179 lines (154 loc) 4.53 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 = Mat22; var Math = require('./Math'); var Vec2 = require('./Vec2'); /** * A 2-by-2 matrix. Stored in column-major order. */ function Mat22(a, b, c, d) { if (typeof a === 'object' && a !== null) { this.ex = Vec2.Clone(a); this.ey = Vec2.Clone(b); } else if (typeof a === 'number') { this.ex = Vec2(a, c); this.ey = Vec2(b, d) } else { this.ex = Vec2(); this.ey = Vec2() } }; Mat22.prototype.toString = function() { return JSON.stringify(this); }; Mat22.IsValid = function(o) { return o && Vec2.IsValid(o.ex) && Vec2.IsValid(o.ey); }; Mat22.Assert = function(o) { if (!Mat22.IsValid(o)) { console.log(o); throw new Error('Invalid Mat22!'); } }; Mat22.prototype.Set = function(a, b, c, d) { if (typeof a === 'number' && typeof b === 'number' && typeof c === 'number' && typeof d === 'number') { this.ex.Set(a, c); this.ey.Set(b, d); } else if (typeof a === 'object' && typeof b === 'object') { this.ex.Set(a); this.ey.Set(b); } else if (typeof a === 'object') { Mat22.Assert(a); this.ex.Set(a.ex); this.ey.Set(a.ey); } else { Assert(false); } } Mat22.prototype.SetIdentity = function() { this.ex.x = 1.0; this.ey.x = 0.0; this.ex.y = 0.0; this.ey.y = 1.0; } Mat22.prototype.SetZero = function() { this.ex.x = 0.0; this.ey.x = 0.0; this.ex.y = 0.0; this.ey.y = 0.0; } Mat22.prototype.GetInverse = function() { 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; } var imx = new Mat22(); imx.ex.x = det * d; imx.ey.x = -det * b; imx.ex.y = -det * c; imx.ey.y = det * a; return imx; } /** * Solve A * x = b, where b is a column vector. This is more efficient than * computing the inverse in one-shot cases. */ Mat22.prototype.Solve = function(v) { Vec2.Assert(v); 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; } var w = new Vec2(); w.x = det * (d * v.x - b * v.y); w.y = det * (a * v.y - c * v.x); return w; } /** * Multiply a matrix times a vector. If a rotation matrix is provided, then this * transforms the vector from one frame to another. */ Mat22.Mul = function(mx, v) { if (v && 'x' in v && 'y' in v) { // Vec2 Vec2.Assert(v); var x = mx.ex.x * v.x + mx.ey.x * v.y; var y = mx.ex.y * v.x + mx.ey.y * v.y; return new Vec2(x, y); } else if (v && 'ex' in v && 'ey' in v) { // Mat22 Mat22.Assert(v); return new Mat22(Vec2.Mul(mx, v.ex), Vec2.Mul(mx, v.ey)); } Assert(false); } /** * * Multiply a matrix transpose times a vector. If a rotation matrix is provided, * then this transforms the vector from one frame to another (inverse * transform). */ Mat22.MulT = function(mx, v) { if (v && 'x' in v && 'y' in v) { // Vec2 Vec2.Assert(v); return new Vec2(Vec2.Dot(v, mx.ex), Vec2.Dot(v, mx.ey)); } else if (v && 'ex' in v && 'ey' in v) { // Mat22 Mat22.Assert(v); var c1 = new Vec2(Vec2.Dot(mx.ex, v.ex), Vec2.Dot(mx.ey, v.ex)); var c2 = new Vec2(Vec2.Dot(mx.ex, v.ey), Vec2.Dot(mx.ey, v.ey)); return new Mat22(c1, c2); } Assert(false); } Mat22.Abs = function(mx) { Mat22.Assert(mx); return new Mat22(Vec2.Abs(mx.ex), Vec2.Abs(mx.ey)); } Mat22.Add = function(mx1, mx2) { Mat22.Assert(mx1); Mat22.Assert(mx2); return new Mat22(Vec2.Add(mx1.ex + mx2.ex), Vec2.Add(mx1.ey + mx2.ey)); }