UNPKG

planck-js

Version:

2D physics engine for JavaScript/HTML5 game development

158 lines (140 loc) 3.68 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 = Rot; var Vec2 = require('./Vec2'); var Math = require('./Math'); // TODO merge with Transform /** * Initialize from an angle in radians. */ function Rot(angle) { if (!(this instanceof Rot)) { return new Rot(angle); } if (typeof angle === 'number') { this.Set(angle); } else { this.SetIdentity(); } } Rot.IsValid = function(o) { return o && Math.isFinite(o.s) && Math.isFinite(o.c); } Rot.Assert = function(o) { if (!Rot.IsValid(o)) { console.log(o); throw new Error('Invalid Rot!'); } } /** * Set to the identity rotation. */ Rot.prototype.SetIdentity = function() { this.s = 0.0; this.c = 1.0; } /** * Set using an angle in radians. */ Rot.prototype.Set = function(angle) { if (typeof angle === 'object') { Rot.Assert(angle); this.s = angle.s; this.c = angle.c; } else { Math.Assert(angle); // TODO_ERIN optimize this.s = Math.sin(angle); this.c = Math.cos(angle); } } /** * Get the angle in radians. */ Rot.prototype.GetAngle = function() { return Math.atan2(this.s, this.c); } /** * Get the x-axis. */ Rot.prototype.GetXAxis = function() { return new Vec2(this.c, this.s); } /** * Get the u-axis. */ Rot.prototype.GetYAxis = function() { return new Vec2(-this.s, this.c); } /** * Multiply two rotations: q * r * * @returns Rot * * Rotate a vector * * @returns Vec2 */ Rot.Mul = function(rot, m) { Rot.Assert(rot); if ('c' in m && 's' in m) { Rot.Assert(m); // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc] // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc] // s = qs * rc + qc * rs // c = qc * rc - qs * rs var qr = new Rot(); qr.s = rot.s * m.c + rot.c * m.s; qr.c = rot.c * m.c - rot.s * m.s; return qr; } else if ('x' in m && 'y' in m) { Vec2.Assert(m); return Vec2(rot.c * m.x - rot.s * m.y, rot.s * m.x + rot.c * m.y); } } Rot.MulSub = function(rot, v, w) { var x = rot.c * (v.x - w.x) - rot.s * (v.y - w.y); var y = rot.s * (v.x - w.y) + rot.c * (v.y - w.y); return Vec2(x, y); } /** * Transpose multiply two rotations: qT * r * * @returns Rot * * Inverse rotate a vector * * @returns Vec2 */ Rot.MulT = function(rot, m) { if ('c' in m && 's' in m) { Rot.Assert(m); // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc] // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc] // s = qc * rs - qs * rc // c = qc * rc + qs * rs var qr = new Rot(); qr.s = rot.c * m.s - rot.s * m.c; qr.c = rot.c * m.c + rot.s * m.s; return qr; } else if ('x' in m && 'y' in m) { Vec2.Assert(m); return Vec2(rot.c * m.x + rot.s * m.y, -rot.s * m.x + rot.c * m.y); } }