Skip to content

Instantly share code, notes, and snippets.

@Maksims
Last active January 3, 2016 12:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Maksims/8464888 to your computer and use it in GitHub Desktop.
Save Maksims/8464888 to your computer and use it in GitHub Desktop.
"rude" extension to Float32Array, implementing 2D Vector Math.
// degree to radians constant
var rd = Math.PI / 180.0;
// 2d vector [x, y] library
var Vec2 = {
cacheSize: 64,
cache: [ ],
clear: function() {
this.cache = [ ];
},
new: function(x, y) {
if (this.cache.length) {
return this.cache.pop().setXY(x, y);
} else {
return new Float32Array([ x || 0, y || 0 ]);
}
},
alpha: null,
charlie: null,
bet: null
};
Vec2.alpha = Vec2.new();
Vec2.charlie = Vec2.new();
Vec2.beta = Vec2.new();
// push vector into cache stack for reusability
Float32Array.prototype.delete = function() {
if (Vec2.cache.length >= Vec2.cacheSize) return;
Vec2.cache.push(this);
};
// clone
Float32Array.prototype.clone = function() {
return Vec2.new(this[0], this[1]);
};
// compare for equal
Float32Array.prototype.equal = function(v) {
return this[0] == v[0] && this[1] == v[1];
};
Float32Array.prototype.equalS = function(s) {
return this[0] == s && this[1] == s;
};
Float32Array.prototype.equalXY = function(x, y) {
return this[0] == x && this[1] == y;
};
// clear
Float32Array.prototype.set = function(v) {
this[0] = v && v[0] || 0;
this[1] = v && v[1] || 0;
return this;
};
Float32Array.prototype.setS = function(s) {
this[0] = s || 0;
this[1] = s || 0;
return this;
};
Float32Array.prototype.setR = function(r) {
this[0] = Math.cos(r);
this[1] = Math.sin(r);
return this;
};
Float32Array.prototype.setXY = function(x, y) {
this[0] = x || 0;
this[1] = y || 0;
return this;
};
// add
Float32Array.prototype.add = function(v) {
this[0] += v[0];
this[1] += v[1];
return this;
};
Float32Array.prototype.addS = function(s) {
this[0] += s;
this[1] += s;
return this;
};
Float32Array.prototype.addXY = function(x, y) {
this[0] += x;
this[1] += y;
return this;
};
// linear interpolation
Float32Array.prototype.lerp = function(v, f) {
this[0] += f * (v[0] - this[0]);
this[1] += f * (v[1] - this[1]);
return this;
};
Float32Array.prototype.lerpS = function(s, f) {
this[0] += f * (s - this[0]);
this[1] += f * (s - this[1]);
return this;
};
Float32Array.prototype.lerpXY = function(x, y, f) {
this[0] += f * (x - this[0]);
this[1] += f * (y - this[1]);
return this;
};
// subtract
Float32Array.prototype.sub = function(v) {
this[0] -= v[0];
this[1] -= v[1];
return this;
};
Float32Array.prototype.subS = function(s) {
this[0] -= s;
this[1] -= s;
return this;
};
Float32Array.prototype.subXY = function(x, y) {
this[0] -= x;
this[1] -= y;
return this;
};
// multiply
Float32Array.prototype.mul = function(v) {
this[0] *= v[0];
this[1] *= v[1];
return this;
};
Float32Array.prototype.mulS = function(s) {
this[0] *= s;
this[1] *= s;
return this;
};
Float32Array.prototype.mulXY = function(x, y) {
this[0] *= x;
this[1] *= y;
return this;
};
// divide
Float32Array.prototype.div = function(v) {
this[0] /= v[0];
this[1] /= v[1];
return this;
};
Float32Array.prototype.divS = function(s) {
this[0] /= s;
this[1] /= s;
return this;
};
Float32Array.prototype.divXY = function(x, y) {
this[0] /= x;
this[1] /= y;
return this;
};
// length
Float32Array.prototype.len = function() {
return Math.sqrt((this[0] * this[0]) + (this[1] * this[1]));
};
// distance
Float32Array.prototype.dist = function(v) {
var x = this[0] - v[0];
var y = this[1] - v[1];
return Math.sqrt(x * x + y * y);
};
Float32Array.prototype.distXY = function(x, y) {
return Math.sqrt(this[0] * x + this[1] * y);
};
// dot
Float32Array.prototype.dot = function(v) {
return this[0] * v[0] + this[1] * v[1];
};
Float32Array.prototype.dotXY = function(x, y) {
return this[0] * x + this[1] * y;
};
// normal
Float32Array.prototype.norm = function() {
var l = 1.0 / Math.sqrt((this[0] * this[0]) + (this[1] * this[1]));
this[0] *= l;
this[1] *= l;
return this;
};
// radians
Float32Array.prototype.radians = function() {
return Math.atan2(this[1], this[0]);
};
// rotate
Float32Array.prototype.rot = function(v) {
Vec2.charlie.set(v).norm();
var t = this[0] * Vec2.charlie[0] - this[1] * Vec2.charlie[1];
this[1] = this[1] * Vec2.charlie[0] + this[0] * Vec2.charlie[1];
this[0] = t;
return this;
};
Float32Array.prototype.rotR = function(r) {
return this.rot(Vec2.charlie.setR(r));
};
Float32Array.prototype.rotXY = function(x, y) {
return this.rot(Vec2.charlie.setXY(x, y).norm());
};
// saturate 0.0 .. 1.0
Float32Array.prototype.sat = function() {
if (this.len() > 1.0) {
this.norm();
}
return this;
}
// floor
Float32Array.prototype.floor = function() {
this[0] = Math.floor(this[0]);
this[1] = Math.floor(this[1]);
return this;
};
// round
Float32Array.prototype.round = function() {
this[0] = Math.round(this[0]);
this[1] = Math.round(this[1]);
return this;
};
// ceil
Float32Array.prototype.ceil = function() {
this[0] = Math.ceil(this[0]);
this[1] = Math.ceil(this[1]);
return this;
};
@Maksims
Copy link
Author

Maksims commented Jan 16, 2014

Example of 2D camera maths for pick (using screen coordinates, transform to world space).
Particular camera supports movement, rotation and zooming:

Camera.prototype.pick = function(viewport, v) {
    return v.clone()                    // make a copy of touch/click point
        .sub(viewport.middle)           // centralise to middle of viewport
        .rotS(-this.rotation.radians()) // rotate
        .divS(this.zoom)                // zoom
        .mulXY(1, -1)                   // reverse Y coordinate
        .add(this.position)             // position
};

// ...

var pointInWorld = camera.pick(Vec2.new(mouseX, mouseY));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment