planck-js
Version:
2D physics engine for JavaScript/HTML5 game development
158 lines (140 loc) • 3.68 kB
JavaScript
/*
* 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);
}
}