diff --git a/README.md b/README.md index 5097349..efcabdc 100644 --- a/README.md +++ b/README.md @@ -26,28 +26,41 @@ var scale = require('gl-vec4/scale') ## API - [add()](#addoutvec4-avec4-bvec4) + - [ceil()](#ceiloutvec4-avec4) - [clone()](#cloneavec4) - [copy()](#copyoutvec4-avec4) - [create()](#create) - [distance()](#distanceavec4-bvec4) + - [dist()](#distanceavec4-bvec4) - [divide()](#divideoutvec4-avec4-bvec4) + - [div()](#divideoutvec4-avec4-bvec4) - [dot()](#dotavec4-bvec4) + - [equals()](#equalsavec4-bvec4) + - [exactEquals()](#exactequalsavec4-bvec4) + - [floor()](#flooroutvec4-avec4) + - [forEach()](#foreachaarraystridenumberoffsetnumbercountnumberfnfunctionargobject) - [fromValues()](#fromvaluesxnumber-ynumber-znumber-wnumber) - [inverse()](#inverseoutvec4-avec4) - [length()](#lengthavec4) + - [len()](#lengthavec4) - [lerp()](#lerpoutvec4-avec4-bvec4-tnumber) - [max()](#maxoutvec4-avec4-bvec4) - [min()](#minoutvec4-avec4-bvec4) - [multiply()](#multiplyoutvec4-avec4-bvec4) + - [mul()](#multiplyoutvec4-avec4-bvec4) - [negate()](#negateoutvec4-avec4) - [normalize()](#normalizeoutvec4-avec4) - [random()](#randomoutvec4-scalenumber) + - [round()](#roundoutvec4-avec4) - [scale()](#scaleoutvec4-avec4-bnumber) - [scaleAndAdd()](#scaleandaddoutvec4-avec4-bvec4-scalenumber) - [set()](#setoutvec4-xnumber-ynumber-znumber-wnumber) - [squaredDistance()](#squareddistanceavec4-bvec4) + - [sqrDist()](#squareddistanceavec4-bvec4) - [squaredLength()](#squaredlengthavec4) + - [sqrLen()](#squaredlengthavec4) - [subtract()](#subtractoutvec4-avec4-bvec4) + - [sub()](#subtractoutvec4-avec4-bvec4) - [transformMat4()](#transformmat4outvec4-avec4-mmat4) - [transformQuat()](#transformquatoutvec4-avec4-qquat) @@ -55,6 +68,10 @@ var scale = require('gl-vec4/scale') Adds two vec4's +## ceil(out:vec4, a:vec4) + + `Math.ceil` the components of a vec4 + ## clone(a:vec4) Creates a new vec4 initialized with values from an existing vector @@ -73,12 +90,24 @@ var scale = require('gl-vec4/scale') ## divide(out:vec4, a:vec4, b:vec4) - Divides two vec4's + Divides two vec4's. Aliased as `div`. ## dot(a:vec4, b:vec4) Calculates the dot product of two vec4's +## equals(a:vec4, b:vec4) + + Returns whether or not the vectors have approximately the same elements in the same position. + +## exactEquals(a:vec4, b:vec4) + + Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) + +## floor(out:vec4, a:vec4) + + `Math.floor` the components of a vec4 + ## fromValues(x:Number, y:Number, z:Number, w:Number) Creates a new vec4 initialized with the given values @@ -89,7 +118,7 @@ var scale = require('gl-vec4/scale') ## length(a:vec4) - Calculates the length of a vec4 + Calculates the length of a vec4. Aliased as `len`. ## lerp(out:vec4, a:vec4, b:vec4, t:Number) @@ -105,7 +134,7 @@ var scale = require('gl-vec4/scale') ## multiply(out:vec4, a:vec4, b:vec4) - Multiplies two vec4's + Multiplies two vec4's. Aliased as `mul`. ## negate(out:vec4, a:vec4) @@ -119,6 +148,10 @@ var scale = require('gl-vec4/scale') Generates a random vector with the given scale +## round(out:vec4, a:vec4) + + `Math.round` the components of a vec4 + ## scale(out:vec4, a:vec4, b:Number) Scales a vec4 by a scalar number @@ -133,15 +166,15 @@ var scale = require('gl-vec4/scale') ## squaredDistance(a:vec4, b:vec4) - Calculates the squared euclidian distance between two vec4's + Calculates the squared euclidian distance between two vec4's. Aliased as `sqrDist`. ## squaredLength(a:vec4) - Calculates the squared length of a vec4 + Calculates the squared length of a vec4. Aliased as `sqrLen`. ## subtract(out:vec4, a:vec4, b:vec4) - Subtracts vector b from vector a + Subtracts vector b from vector a. Aliased as `sub` ## transformMat4(out:vec4, a:vec4, m:mat4) diff --git a/ceil.js b/ceil.js new file mode 100644 index 0000000..0a309d7 --- /dev/null +++ b/ceil.js @@ -0,0 +1,16 @@ +module.exports = ceil + +/** + * Math.ceil the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to ceil + * @returns {vec4} out + */ +function ceil(out, a) { + out[0] = Math.ceil(a[0]) + out[1] = Math.ceil(a[1]) + out[2] = Math.ceil(a[2]) + out[3] = Math.ceil(a[3]) + return out +} diff --git a/dist.js b/dist.js new file mode 100644 index 0000000..fc548d9 --- /dev/null +++ b/dist.js @@ -0,0 +1 @@ +module.exports = require('./distance') diff --git a/div.js b/div.js new file mode 100644 index 0000000..ffdd25e --- /dev/null +++ b/div.js @@ -0,0 +1 @@ +module.exports = require('./divide') diff --git a/epsilon.js b/epsilon.js new file mode 100644 index 0000000..9bf3227 --- /dev/null +++ b/epsilon.js @@ -0,0 +1 @@ +module.exports = 0.000001 diff --git a/equals.js b/equals.js new file mode 100644 index 0000000..cc7e574 --- /dev/null +++ b/equals.js @@ -0,0 +1,25 @@ +module.exports = equals + +var EPSILON = require('./epsilon') + +/** + * Returns whether or not the vectors have approximately the same elements in the same position. + * + * @param {vec4} a The first vector. + * @param {vec4} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function equals(a, b) { + var a0 = a[0] + var a1 = a[1] + var a2 = a[2] + var a3 = a[3] + var b0 = b[0] + var b1 = b[1] + var b2 = b[2] + var b3 = b[3] + return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && + Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3))) +} diff --git a/exactEquals.js b/exactEquals.js new file mode 100644 index 0000000..e272879 --- /dev/null +++ b/exactEquals.js @@ -0,0 +1,12 @@ +module.exports = exactEquals + +/** + * Returns whether or not the vectors exactly have the same elements in the same position (when compared with ===) + * + * @param {vec4} a The first vector. + * @param {vec4} b The second vector. + * @returns {Boolean} True if the vectors are equal, false otherwise. + */ +function exactEquals(a, b) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] +} diff --git a/floor.js b/floor.js new file mode 100644 index 0000000..cfefe0f --- /dev/null +++ b/floor.js @@ -0,0 +1,16 @@ +module.exports = floor + +/** + * Math.floor the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to floor + * @returns {vec4} out + */ +function floor(out, a) { + out[0] = Math.floor(a[0]) + out[1] = Math.floor(a[1]) + out[2] = Math.floor(a[2]) + out[3] = Math.floor(a[3]) + return out +} diff --git a/forEach.js b/forEach.js new file mode 100644 index 0000000..300e690 --- /dev/null +++ b/forEach.js @@ -0,0 +1,46 @@ +module.exports = forEach; + +var vec = require('./create')() + +/** + * Perform some operation over an array of vec4. + * + * @param {Array} a the array of vectors to iterate over + * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed + * @param {Number} offset Number of elements to skip at the beginning of the array + * @param {Number} count Number of vec4 to iterate over. If 0 iterates over entire array + * @param {Function} fn Function to call for each vector in the array + * @param {Object} [arg] additional argument to pass to fn + * @returns {Array} a + * @function + */ +function forEach(a, stride, offset, count, fn, arg) { + var i, l + if(!stride) { + stride = 4 + } + + if(!offset) { + offset = 0 + } + + if(count) { + l = Math.min((count * stride) + offset, a.length) + } else { + l = a.length + } + + for(i = offset; i < l; i += stride) { + vec[0] = a[i] + vec[1] = a[i+1] + vec[2] = a[i+2] + vec[3] = a[i+3] + fn(vec, vec, arg) + a[i] = vec[0] + a[i+1] = vec[1] + a[i+2] = vec[2] + a[i+3] = vec[3] + } + + return a +} diff --git a/index.js b/index.js index 5ce6a40..cbd67be 100644 --- a/index.js +++ b/index.js @@ -1,21 +1,35 @@ module.exports = { + epsilon: require('./epsilon'), create: require('./create'), clone: require('./clone'), fromValues: require('./fromValues'), copy: require('./copy'), set: require('./set'), + equals: require('./equals'), + exactEquals: require('./exactEquals'), add: require('./add'), subtract: require('./subtract'), + sub: require('./sub'), multiply: require('./multiply'), + mul: require('./mul'), divide: require('./divide'), + div: require('./div'), min: require('./min'), max: require('./max'), + floor: require('./floor'), + ceil: require('./ceil'), + round: require('./round'), + forEach: require('./forEach'), scale: require('./scale'), scaleAndAdd: require('./scaleAndAdd'), distance: require('./distance'), + dist: require('./dist'), squaredDistance: require('./squaredDistance'), + sqrDist: require('./sqrDist'), length: require('./length'), + len: require('./len'), squaredLength: require('./squaredLength'), + sqrLen: require('./sqrLen'), negate: require('./negate'), inverse: require('./inverse'), normalize: require('./normalize'), diff --git a/len.js b/len.js new file mode 100644 index 0000000..fbebab2 --- /dev/null +++ b/len.js @@ -0,0 +1 @@ +module.exports = require('./length') diff --git a/mul.js b/mul.js new file mode 100644 index 0000000..ed63273 --- /dev/null +++ b/mul.js @@ -0,0 +1 @@ +module.exports = require('./multiply') diff --git a/package.json b/package.json index b27a02e..01d994d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "gl-matrix's vec4, split into smaller pieces", "main": "index.js", "scripts": { - "get-docs": "cat *.js | dox --api" + "get-docs": "cat *.js | dox --api", + "test": "node test/index.js" }, "dependencies": {}, "devDependencies": { diff --git a/round.js b/round.js new file mode 100644 index 0000000..40c0934 --- /dev/null +++ b/round.js @@ -0,0 +1,16 @@ +module.exports = round + +/** + * Math.round the components of a vec4 + * + * @param {vec4} out the receiving vector + * @param {vec4} a vector to round + * @returns {vec4} out + */ +function round(out, a) { + out[0] = Math.round(a[0]) + out[1] = Math.round(a[1]) + out[2] = Math.round(a[2]) + out[3] = Math.round(a[3]) + return out +} diff --git a/sqrDist.js b/sqrDist.js new file mode 100644 index 0000000..4040002 --- /dev/null +++ b/sqrDist.js @@ -0,0 +1 @@ +module.exports = require('./squaredDistance') diff --git a/sqrLen.js b/sqrLen.js new file mode 100644 index 0000000..ae5f355 --- /dev/null +++ b/sqrLen.js @@ -0,0 +1 @@ +module.exports = require('./squaredLength') diff --git a/sub.js b/sub.js new file mode 100644 index 0000000..71deea1 --- /dev/null +++ b/sub.js @@ -0,0 +1 @@ +module.exports = require('./subtract') diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..cc3163a --- /dev/null +++ b/test/index.js @@ -0,0 +1,256 @@ +var test = require('tape') +var vec4 = require('../') +var EPSILON = require('../epsilon') + +test('add', function (t) { + var result = vec4.add([], [0, 1, 2, 3], [4, 5, 6, 7]) + t.deepEqual(result, [4, 6, 8, 10]) + t.end() +}) + +test('ceil', function (t) { + var result = vec4.ceil([], [5.2, 6.5, 7.9, 9.1]) + t.deepEqual(result, [6, 7, 8, 10]) + t.end() +}) + +test('clone', function (t) { + var result = vec4.clone([5, 6, 7, 8]) + t.deepEqual(result, [5, 6, 7, 8]) + t.end() +}) + +test('copy', function (t) { + var result = vec4.copy([], [5, 6, 7, 8]) + t.deepEqual(result, [5, 6, 7, 8]) + t.end() +}) + +test('create', function (t) { + var result = vec4.create() + t.deepEqual(result, [0, 0, 0, 0]) + t.end() +}) + +test('distance', function (t) { + var result = vec4.distance([1, 2, 3, 4], [5, 6, 7, 8]) + t.equal(result, 8) + t.end() +}) + +test('divide', function (t) { + var result = vec4.divide([], [8, 4, 2, 1], [2, 1, 0.5, 0.25]) + t.deepEqual(result, [4, 4, 4, 4]) + t.end() +}) + +test('div', function (t) { + var result = vec4.div([], [8, 4, 2, 1], [2, 1, 0.5, 0.25]) + t.deepEqual(result, [4, 4, 4, 4]) + t.end() +}) + +test('dot', function (t) { + var result = vec4.dot([3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, 158) + t.end() +}) + +test('equals', function (t) { + t.ok(vec4.equals([3 + EPSILON, 5 - EPSILON, 4 + EPSILON, 6 + EPSILON], [3, 5, 4, 6])) + t.notOk(vec4.equals([3 + EPSILON * 10, 5, 4, 6], [3, 5, 4, 6])) + t.notOk(vec4.equals([3, 5 - EPSILON * 10, 4, 6], [3, 5, 4, 6])) + t.notOk(vec4.equals([3, 5, 4 + EPSILON * 10, 6], [3, 5, 4, 6])) + t.notOk(vec4.equals([3, 5, 4, 6 + EPSILON * 10], [3, 5, 4, 6])) + t.end() +}) + +test('exactEquals', function (t) { + t.ok(vec4.exactEquals([3, 5, 4, 6], [3, 5, 4, 6])) + t.notOk(vec4.exactEquals([3 + EPSILON, 5, 4, 6], [3, 5, 4, 6])) + t.notOk(vec4.exactEquals([3, 5 + EPSILON, 4, 6], [3, 5, 4, 6])) + t.notOk(vec4.exactEquals([3, 5, 4 + EPSILON, 6], [3, 5, 4, 6])) + t.notOk(vec4.exactEquals([3, 5, 4, 6 + EPSILON], [3, 5, 4, 6])) + t.end() +}) + +test('floor', function (t) { + var result = vec4.floor([], [5.2, 6.6, 7.9, 9.1]) + t.deepEqual(result, [5, 6, 7, 9]) + t.end() +}) + +test('forEach', function (t) { + var a = [null, + 0, 1, 2, 3, null, + 4, 5, 6, 7, null + ] + + function addConstant (out, a, val) { + out[0] = a[0] + val + out[1] = a[1] + val + out[2] = a[2] + val + out[3] = a[3] + val + return out + } + + vec4.forEach(a, 5, 1, 2, addConstant, 7) + + t.deepEqual(a, [null, 7, 8, 9, 10, null, 11, 12, 13, 14, null]) + t.end() +}) + +test('fromValues', function (t) { + var result = vec4.fromValues(2, 3, 4, 5) + t.deepEqual(result, [2, 3, 4, 5]) + t.end() +}) + +test('inverse', function (t) { + var result = vec4.inverse([], [2, 4, 8, 16]) + t.deepEqual(result, [0.5, 0.25, 0.125, 0.0625]) + t.end() +}) + +test('length', function (t) { + var result = vec4.length([3, 4, 5, 6]) + t.ok(Math.abs(result - 9.273618495495704) < EPSILON) + t.end() +}) + +test('len', function (t) { + var result = vec4.len([3, 4, 5, 6]) + t.ok(Math.abs(result - 9.273618495495704) < EPSILON) + t.end() +}) + +test('lerp', function (t) { + var result = vec4.lerp([], [3, 4, 5, 6], [7, 8, 9, 10], 0.25) + t.deepEqual(result, [4, 5, 6, 7]) + t.end() +}) + +test('max', function (t) { + var result = vec4.max([], [3, 7, 2, 1], [5, 6, 4, 4]) + t.deepEqual(result, [5, 7, 4, 4]) + t.end() +}) + +test('min', function (t) { + var result = vec4.min([], [3, 7, 8, 1], [5, 6, 2, 4]) + t.deepEqual(result, [3, 6, 2, 1]) + t.end() +}) + +test('multiply', function (t) { + var result = vec4.multiply([], [3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, [21, 32, 45, 60]) + t.end() +}) + +test('mul', function (t) { + var result = vec4.mul([], [3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, [21, 32, 45, 60]) + t.end() +}) + +test('negate', function (t) { + var result = vec4.negate([], [3, 4, 5, 6]) + t.deepEqual(result, [-3, -4, -5, -6]) + t.end() +}) + +test('normalize', function (t) { + var result = vec4.normalize([], [3, 4, 5, 6]) + t.ok(Math.abs(result[0] - 0.3234983196103152) < EPSILON) + t.ok(Math.abs(result[1] - 0.43133109281375365) < EPSILON) + t.ok(Math.abs(result[2] - 0.539163866017192) < EPSILON) + t.ok(Math.abs(result[3] - 0.6469966392206304) < EPSILON) + t.end() +}) + +test('random', function (t) { + var result = vec4.random([], 5) + for (var i = 0; i < 10; i++) { + var len = Math.sqrt(result[0] * result[0] + result[1] * result[1] + result[2] * result[2] + result[3] * result[3]) + t.ok(Math.abs(5 - len) <= EPSILON) + } + t.end() +}) + +test('scale', function (t) { + var result = vec4.scale([], [3, 4, 5, 6], 2) + t.deepEqual(result, [6, 8, 10, 12]) + t.end() +}) + +test('scaleAndAdd', function (t) { + var result = vec4.scaleAndAdd([], [3, 4, 5, 6], [7, 8, 9, 10], 2) + t.deepEqual(result, [17, 20, 23, 26]) + t.end() +}) + +test('round', function (t) { + var result = vec4.round([], [5.2, 6.6, 8.5, 9.1]) + t.deepEqual(result, [5, 7, 9, 9]) + t.end() +}) + +test('set', function (t) { + var result = vec4.set([], 3, 4, 5, 6) + t.deepEqual(result, [3, 4, 5, 6]) + t.end() +}) + +test('squaredDistance', function (t) { + var result = vec4.squaredDistance([3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, 64) + t.end() +}) + +test('sqrDist', function (t) { + var result = vec4.sqrDist([3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, 64) + t.end() +}) + +test('squaredLength', function (t) { + var result = vec4.squaredLength([3, 4, 5, 6]) + t.deepEqual(result, 86) + t.end() +}) + +test('sqrLen', function (t) { + var result = vec4.sqrLen([3, 4, 5, 6]) + t.deepEqual(result, 86) + t.end() +}) + +test('subtract', function (t) { + var result = vec4.subtract([], [3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, [-4, -4, -4, -4]) + t.end() +}) + +test('sub', function (t) { + var result = vec4.sub([], [3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, [-4, -4, -4, -4]) + t.end() +}) + +test('transformMat4', function (t) { + var result = vec4.transformMat4([], [3, 4, 5, 6], [ + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, 20 + ]) + t.deepEqual(result, [218, 236, 254, 272]) + t.end() +}) + +test('transformQuat', function (t) { + var result = vec4.transformQuat([], [3, 4, 5, 6], [7, 8, 9, 10]) + t.deepEqual(result, [1170, 1032, 1374, 6]) + t.end() +})