Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Last active January 5, 2017 00:29
Show Gist options
  • Save SeijiEmery/c483196ea317eab3a328 to your computer and use it in GitHub Desktop.
Save SeijiEmery/c483196ea317eab3a328 to your computer and use it in GitHub Desktop.
Lightweight js vec3 impl with experimental dynamic type checking
// Defines a better type querry function that enables object prototypes to define their own type repr
$typeof = function(value) {
return value.__proto__.type || typeof(value);
}
// Switch to 'release' (or any other value) to disable expensive typechecking.
releaseMode = 'debug';
__handleTypeError = function (errMsg) { window.print("Type check failed: " + errMsg); }
Function.prototype.withTypeSignature = function (/* type arguments... */) {
var _this = this;
var numArgs = arguments.length();
var argTypes = arguments.join();
return function (/* arguments... */) {
if (numArgs !== arguments.length) {
__handleTypeError("Invalid argument count - expected " +
numArgs + " (" + argTypes + ") , got " +
arguments.length + " (" + arguments.map($typeof).join() + ")");
return null;
} else {
args = arguments.map($typeof).join();
if (argTypes !== args) {
__handleTypeError("Invalid argument types - expected (" + argTypes + "), got (" + args ")");
return null;
}
}
return _this.apply(_this, arguments);
}
}
Function.prototype.withArgRange = function (minArgs, maxArgs) {
var _this = this;
return function (/* arguments... */) {
if (minArgs > arguments.length() || maxArgs < arguments.length()) {
__handleTypeError("Expected between " + minArgs + " and " + maxArgs + " arguments, not " + arguments.length())
return null;
}
return _this.apply(_this, arguments);
}
}
if (releaseMode != 'debug') {
var passthrough = function () { return this; }
Function.prototype.typecheck = passthrough;
Function.prototype.withArgRange = passthrough;
}
Vec3 = function (x, y, z) {
this.x = x || 0.0f;
this.y = y || 0.0f;
this.z = z || 0.0f;
}.withArgRange(0, 3)
Vec3.prototype = {}
Vec3.prototype.type = 'Vec3'
Vec3.prototype.toString = function () {
return "Vec3(" + this.x + ", " + this.y + ", " + this.z + ")";
}
Vec3.prototype.add = function (Vec3) {
this.x += Vec3.x;
this.y += Vec3.y;
this.z += Vec3.z;
return this;
}.withTypeSignature('Vec3')
Vec3.prototype.sub = function (Vec3) {
this.x -= Vec3.x;
this.y -= Vec3.y;
this.z -= Vec3.z;
return this;
}.withTypeSignature('Vec3')
Vec3.prototype.negate = function () {
this.x = -this.x;
this.y = -this.y;
this.z = -this.z;
return this;
}.withTypeSignature()
Vec3.prototype.mul = function (scalar) {
this.x *= scalar;
this.y *= scalar;
this.y *= scalar;
return this;
}.withTypeSignature('float')
Vec3.prototype.div = function (scalar) {
this.x /= scalar;
this.y /= scalar;
this.z /= scalar;
return this;
}.withTypeSignature('float')
Vec3.prototype.dot = function (Vec3) {
return this.x * Vec3.x + this.y * Vec3.y + this.z * Vec3.z;
}.withTypeSignature('Vec3')
Vec3.prototype.cross = function (Vec3) {
return new Vec3(
this.y * Vec3.z - this.z * Vec3.y,
this.z * Vec3.x - this.x * Vec3.z,
this.x * Vec3.y - this.y * Vec3.x
);
}.withTypeSignature('Vec3')
Vec3.prototype.distance = function (Vec3) {
var dx = this.x - Vec3.x;
var dy = this.y - Vec3.y;
var dz = this.z - Vec3.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}.withTypeSignature('Vec3')
Vec3.prototype.magnitude = function () {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}
Vec3.prototype.normalize = function () {
this.div(this.magnitude());
return this;
}
Vec3.prototype.copy = function () {
return new Vec3(this.x, this.y, this.z);
}
// Returns the component of this parallel to other (projection/parallel component)
Vec3.prototype.projection = function (Vec3) {
var projection = Vec3.copy();
projection.mul(this.dot(Vec3) / Vec3.dot(Vec3));
return projection;
}
// Returns the component of this perpendicular to other (rejection/tangential component)
Vec3.prototype.rejection = function (Vec3) {
var projection = this.projection(Vec3);
return projection.negate().add(this);
}
Vec3.cosTheta = function (Vec3) {
var a = this.copy(), b = Vec3;
return a.div(a.magnitude() * b.magnitude()).dot(b);
}
Vec3.add = function (a, b) {
return a.clone().add(b);
}
Vec3.sub = function (a, b) {
return a.clone().sub(b);
}
Vec3.mul = function (a, s) {
return a.clone().mul(s);
}
Vec3.div = function (a, s) {
return a.clone().div(s);
}
Vec3.normalized = function (a) {
return a.clone().normalize();
}
Vec3.distance = function (a, b) {
return a.distance(b);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment