Browse files

Merge pull request #27 from sinisterchipmunk/vec2-and-mat2

vec2 and mat2
  • Loading branch information...
2 parents 7671a6d + 9b2699f commit 9c117cb92545951fbb65279ec170931ada2395b5 @toji committed May 3, 2012
Showing with 932 additions and 3 deletions.
  1. +516 −0 gl-matrix.js
  2. +164 −0 spec/javascripts/mat2_spec.js
  3. +19 −3 spec/javascripts/mat3_spec.js
  4. +233 −0 spec/javascripts/vec2_spec.js
View
516 gl-matrix.js
@@ -530,6 +530,23 @@
};
/**
+ * Transforms the vec2 according to the given 3x3 matrix.
+ *
+ * @param {mat3} matrix the 3x3 matrix to multiply against
+ * @param {vec2} vec the vector to multiply
+ * @param {vec2} [dest] an optional receiving vector. If not given, vec is used.
+ *
+ * @returns {vec2} The multiplication result
+ **/
+ mat3.multiplyVec2 = function(matrix, vec, dest) {
+ if (!dest) dest = vec;
+ var x = vec[0], y = vec[1];
+ dest[0] = x * matrix[0] + y * matrix[3] + matrix[6];
+ dest[1] = x * matrix[1] + y * matrix[4] + matrix[7];
+ return dest;
+ };
+
+ /**
* Transforms the vec3 according to this rotation matrix.
*
* @param {mat3} matrix the 3x3 matrix to multiply against
@@ -2247,6 +2264,501 @@
quat4.str = function (quat) {
return '[' + quat[0] + ', ' + quat[1] + ', ' + quat[2] + ', ' + quat[3] + ']';
};
+
+ /**
+ * @class 2 Dimensional Vector
+ * @name vec2
+ */
+ var vec2 = {};
+
+ /**
+ * Creates a new vec2, initializing it from vec if vec
+ * is given.
+ *
+ * @param {vec2} [vec] the vector's initial contents
+ * @returns {vec2} a new 2D vector
+ */
+ vec2.create = function(vec) {
+ var dest = new MatrixArray(2);
+ if (vec) {
+ dest[0] = vec[0];
+ dest[1] = vec[1];
+ } else {
+ dest[0] = 0;
+ dest[1] = 0;
+ }
+ return dest;
+ };
+
+ /**
+ * Adds the vec2's together. If dest is given, the result
+ * is stored there. Otherwise, the result is stored in vecB.
+ *
+ * @param {vec2} vecA the first operand
+ * @param {vec2} vecB the second operand
+ * @param {vec2} [dest] the optional receiving vector
+ * @returns {vec2} dest
+ */
+ vec2.add = function(vecA, vecB, dest) {
+ if (!dest) dest = vecB;
+ dest[0] = vecA[0] + vecB[0];
+ dest[1] = vecA[1] + vecB[1];
+ return dest;
+ };
+
+ /**
+ * Subtracts vecB from vecA. If dest is given, the result
+ * is stored there. Otherwise, the result is stored in vecB.
+ *
+ * @param {vec2} vecA the first operand
+ * @param {vec2} vecB the second operand
+ * @param {vec2} [dest] the optional receiving vector
+ * @returns {vec2} dest
+ */
+ vec2.subtract = function(vecA, vecB, dest) {
+ if (!dest) dest = vecB;
+ dest[0] = vecA[0] - vecB[0];
+ dest[1] = vecA[1] - vecB[1];
+ return dest;
+ };
+
+ /**
+ * Multiplies vecA with vecB. If dest is given, the result
+ * is stored there. Otherwise, the result is stored in vecB.
+ *
+ * @param {vec2} vecA the first operand
+ * @param {vec2} vecB the second operand
+ * @param {vec2} [dest] the optional receiving vector
+ * @returns {vec2} dest
+ */
+ vec2.multiply = function(vecA, vecB, dest) {
+ if (!dest) dest = vecB;
+ dest[0] = vecA[0] * vecB[0];
+ dest[1] = vecA[1] * vecB[1];
+ return dest;
+ };
+
+ /**
+ * Divides vecA by vecB. If dest is given, the result
+ * is stored there. Otherwise, the result is stored in vecB.
+ *
+ * @param {vec2} vecA the first operand
+ * @param {vec2} vecB the second operand
+ * @param {vec2} [dest] the optional receiving vector
+ * @returns {vec2} dest
+ */
+ vec2.divide = function(vecA, vecB, dest) {
+ if (!dest) dest = vecB;
+ dest[0] = vecA[0] / vecB[0];
+ dest[1] = vecA[1] / vecB[1];
+ return dest;
+ };
+
+ /**
+ * Scales vecA by some scalar number. If dest is given, the result
+ * is stored there. Otherwise, the result is stored in vecA.
+ *
+ * This is the same as multiplying each component of vecA
+ * by the given scalar.
+ *
+ * @param {vec2} vecA the vector to be scaled
+ * @param {Number} scalar the amount to scale the vector by
+ * @param {vec2} [dest] the optional receiving vector
+ * @returns {vec2} dest
+ */
+ vec2.scale = function(vecA, scalar, dest) {
+ if (!dest) dest = vecA;
+ dest[0] = vecA[0] * scalar;
+ dest[1] = vecA[1] * scalar;
+ return dest;
+ };
+
+ /**
+ * Calculates the euclidian distance between two vec2
+ *
+ * Params:
+ * @param {vec2} vecA First vector
+ * @param {vec2} vecB Second vector
+ *
+ * @returns {number} Distance between vecA and vecB
+ */
+ vec2.dist = function (vecA, vecB) {
+ var x = vecB[0] - vecA[0],
+ y = vecB[1] - vecA[1];
+ return Math.sqrt(x*x + y*y);
+ };
+
+ /**
+ * Copies the values of one vec2 to another
+ *
+ * @param {vec2} vec vec2 containing values to copy
+ * @param {vec2} dest vec2 receiving copied values
+ *
+ * @returns {vec2} dest
+ */
+ vec2.set = function (vec, dest) {
+ dest[0] = vec[0];
+ dest[1] = vec[1];
+ return dest;
+ };
+
+ /**
+ * Negates the components of a vec2
+ *
+ * @param {vec2} vec vec2 to negate
+ * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec2} dest if specified, vec otherwise
+ */
+ vec2.negate = function (vec, dest) {
+ if (!dest) { dest = vec; }
+ dest[0] = -vec[0];
+ dest[1] = -vec[1];
+ return dest;
+ };
+
+ /**
+ * Normlize a vec2
+ *
+ * @param {vec2} vec vec2 to normalize
+ * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vec
+ *
+ * @returns {vec2} dest if specified, vec otherwise
+ */
+ vec2.normalize = function (vec, dest) {
+ if (!dest) { dest = vec; }
+ var mag = vec[0] * vec[0] + vec[1] * vec[1];
+ if (mag > 0) {
+ mag = Math.sqrt(mag);
+ dest[0] = vec[0] / mag;
+ dest[1] = vec[1] / mag;
+ } else {
+ dest[0] = dest[1] = 0;
+ }
+ return dest;
+ };
+
+ /**
+ * Computes the cross product of two vec2's. Note that the cross product must by definition
+ * produce a 3D vector. If a dest vector is given, it will contain the resultant 3D vector.
+ * Otherwise, a scalar number will be returned, representing the vector's Z coordinate, since
+ * its X and Y must always equal 0.
+ *
+ * Examples:
+ * var crossResult = vec3.create();
+ * vec2.cross([1, 2], [3, 4], crossResult);
+ * //=> [0, 0, -2]
+ *
+ * vec2.cross([1, 2], [3, 4]);
+ * //=> -2
+ *
+ * See http://stackoverflow.com/questions/243945/calculating-a-2d-vectors-cross-product
+ * for some interesting facts.
+ *
+ * @param {vec2} vecA left operand
+ * @param {vec2} vecB right operand
+ * @param {vec2} [dest] optional vec2 receiving result. If not specified a scalar is returned
+ *
+ */
+ vec2.cross = function (vecA, vecB, dest) {
+ var z = vecA[0] * vecB[1] - vecA[1] * vecB[0];
+ if (!dest) return z;
+ dest[0] = dest[1] = 0;
+ dest[2] = z;
+ return dest;
+ };
+
+ /**
+ * Caclulates the length of a vec2
+ *
+ * @param {vec2} vec vec2 to calculate length of
+ *
+ * @returns {Number} Length of vec
+ */
+ vec2.length = function (vec) {
+ var x = vec[0], y = vec[1];
+ return Math.sqrt(x * x + y * y);
+ };
+
+ /**
+ * Caclulates the dot product of two vec2s
+ *
+ * @param {vec3} vecA First operand
+ * @param {vec3} vecB Second operand
+ *
+ * @returns {Number} Dot product of vecA and vecB
+ */
+ vec2.dot = function (vecA, vecB) {
+ return vecA[0] * vecB[0] + vecA[1] * vecB[1];
+ };
+
+ /**
+ * Generates a 2D unit vector pointing from one vector to another
+ *
+ * @param {vec2} vecA Origin vec2
+ * @param {vec2} vecB vec2 to point to
+ * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vecA
+ *
+ * @returns {vec2} dest if specified, vecA otherwise
+ */
+ vec2.direction = function (vecA, vecB, dest) {
+ if (!dest) { dest = vecA; }
+
+ var x = vecA[0] - vecB[0],
+ y = vecA[1] - vecB[1],
+ len = x * x + y * y;
+
+ if (!len) {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+ return dest;
+ }
+
+ len = 1 / Math.sqrt(len);
+ dest[0] = x * len;
+ dest[1] = y * len;
+ return dest;
+ };
+
+ /**
+ * Performs a linear interpolation between two vec2
+ *
+ * @param {vec2} vecA First vector
+ * @param {vec2} vecB Second vector
+ * @param {Number} lerp Interpolation amount between the two inputs
+ * @param {vec2} [dest] vec2 receiving operation result. If not specified result is written to vecA
+ *
+ * @returns {vec2} dest if specified, vecA otherwise
+ */
+ vec2.lerp = function (vecA, vecB, lerp, dest) {
+ if (!dest) { dest = vecA; }
+ dest[0] = vecA[0] + lerp * (vecB[0] - vecA[0]);
+ dest[1] = vecA[1] + lerp * (vecB[1] - vecA[1]);
+ return dest;
+ };
+
+ /**
+ * Returns a string representation of a vector
+ *
+ * @param {vec2} vec Vector to represent as a string
+ *
+ * @returns {String} String representation of vec
+ */
+ vec2.str = function (vec) {
+ return '[' + vec[0] + ', ' + vec[1] + ']';
+ };
+
+ /**
+ * @class 2x2 Matrix
+ * @name mat2
+ */
+ var mat2 = {};
+
+ /**
+ * Creates a new 2x2 matrix. If src is given, the new matrix
+ * is initialized to those values.
+ *
+ * @param {mat2} [src] the seed values for the new matrix, if any
+ * @returns {mat2} a new matrix
+ */
+ mat2.create = function(src) {
+ var dest = new MatrixArray(4);
+ if (src) {
+ dest[0] = src[0];
+ dest[1] = src[1];
+ dest[2] = src[2];
+ dest[3] = src[3];
+ }
+ return dest;
+ };
+
+ /**
+ * Copies the values of one mat2 to another
+ *
+ * @param {mat2} mat mat2 containing values to copy
+ * @param {mat2} dest mat2 receiving copied values
+ *
+ * @returns {mat2} dest
+ */
+ mat2.set = function (mat, dest) {
+ dest[0] = mat[0];
+ dest[1] = mat[1];
+ dest[2] = mat[2];
+ dest[3] = mat[3];
+ return dest;
+ };
+
+ /**
+ * Sets a mat2 to an identity matrix
+ *
+ * @param {mat2} [dest] mat2 to set. If omitted a new one will be created.
+ *
+ * @returns {mat2} dest
+ */
+ mat2.identity = function (dest) {
+ if (!dest) { dest = mat2.create(); }
+ dest[0] = 1;
+ dest[1] = 0;
+ dest[2] = 0;
+ dest[3] = 1;
+ return dest;
+ };
+
+ /**
+ * Transposes a mat2 (flips the values over the diagonal)
+ *
+ * @param {mat2} mat mat2 to transpose
+ * @param {mat2} [dest] mat2 receiving transposed values. If not specified result is written to mat
+ *
+ * @param {mat2} dest if specified, mat otherwise
+ */
+ mat2.transpose = function (mat, dest) {
+ // If we are transposing ourselves we can skip a few steps but have to cache some values
+ if (!dest || mat === dest) {
+ var a00 = mat[1];
+ mat[1] = mat[2];
+ mat[2] = a00;
+ return mat;
+ }
+
+ dest[0] = mat[0];
+ dest[1] = mat[2];
+ dest[2] = mat[1];
+ dest[3] = mat[3];
+ return dest;
+ };
+
+ /**
+ * Calculates the determinant of a mat2
+ *
+ * @param {mat2} mat mat2 to calculate determinant of
+ *
+ * @returns {Number} determinant of mat
+ */
+ mat2.determinant = function (mat) {
+ return mat[0] * mat[3] - mat[2] * mat[1];
+ };
+
+ /**
+ * Calculates the inverse matrix of a mat2
+ *
+ * @param {mat2} mat mat2 to calculate inverse of
+ * @param {mat2} [dest] mat2 receiving inverse matrix. If not specified result is written to mat
+ *
+ * @param {mat2} dest is specified, mat otherwise, null if matrix cannot be inverted
+ */
+ mat2.inverse = function (mat, dest) {
+ if (!dest) { dest = mat; }
+ var a0 = mat[0], a1 = mat[1], a2 = mat[2], a3 = mat[3];
+ var det = a0 * a3 - a2 * a1;
+ if (!det) return null;
+
+ det = 1.0 / det;
+ dest[0] = a3 * det;
+ dest[1] = -a1 * det;
+ dest[2] = -a2 * det;
+ dest[3] = a0 * det;
+ return dest;
+ };
+
+ /**
+ * Performs a matrix multiplication
+ *
+ * @param {mat2} matA First operand
+ * @param {mat2} matB Second operand
+ * @param {mat2} [dest] mat2 receiving operation result. If not specified result is written to matA
+ *
+ * @returns {mat2} dest if specified, matA otherwise
+ */
+ mat2.multiply = function (matA, matB, dest) {
+ if (!dest) { dest = matA; }
+ var a11 = matA[0],
+ a12 = matA[1],
+ a21 = matA[2],
+ a22 = matA[3];
+ dest[0] = a11 * matB[0] + a12 * matB[2];
+ dest[1] = a11 * matB[1] + a12 * matB[3];
+ dest[2] = a21 * matB[0] + a22 * matB[2];
+ dest[3] = a21 * matB[1] + a22 * matB[3];
+ return dest;
+ };
+
+ /**
+ * Rotates a 2x2 matrix by an angle
+ *
+ * @param {mat2} mat The matrix to rotate
+ * @param {Number} angle The angle in radians
+ * @param {mat2} [dest] Optional mat2 receiving the result. If omitted mat will be used.
+ *
+ * @returns {mat2} dest if specified, mat otherwise
+ */
+ mat2.rotate = function (mat, angle, dest) {
+ if (!dest) { dest = mat; }
+ var a11 = mat[0],
+ a12 = mat[1],
+ a21 = mat[2],
+ a22 = mat[3],
+ s = Math.sin(angle),
+ c = Math.cos(angle);
+ dest[0] = a11 * c + a12 * s;
+ dest[1] = a11 * -s + a12 * c;
+ dest[2] = a21 * c + a22 * s;
+ dest[3] = a21 * -s + a22 * c;
+ return dest;
+ };
+
+ /**
+ * Multiplies the vec2 by the given 2x2 matrix
+ *
+ * @param {mat2} matrix the 2x2 matrix to multiply against
+ * @param {vec2} vec the vector to multiply
+ * @param {vec2} [dest] an optional receiving vector. If not given, vec is used.
+ *
+ * @returns {vec2} The multiplication result
+ **/
+ mat2.multiplyVec2 = function(matrix, vec, dest) {
+ if (!dest) dest = vec;
+ var x = vec[0], y = vec[1];
+ dest[0] = x * matrix[0] + y * matrix[1];
+ dest[1] = x * matrix[2] + y * matrix[3];
+ return dest;
+ };
+
+ /**
+ * Scales the mat2 by the dimensions in the given vec2
+ *
+ * @param {mat2} matrix the 2x2 matrix to scale
+ * @param {vec2} vec the vector containing the dimensions to scale by
+ * @param {vec2} [dest] an optional receiving mat2. If not given, matrix is used.
+ *
+ * @returns {mat2} dest if specified, matrix otherwise
+ **/
+ mat2.scale = function(matrix, vec, dest) {
+ if (!dest) { dest = matrix; }
+ var a11 = matrix[0],
+ a12 = matrix[1],
+ a21 = matrix[2],
+ a22 = matrix[3],
+ b11 = vec[0],
+ b22 = vec[1];
+ dest[0] = a11 * b11;
+ dest[1] = a12 * b22;
+ dest[2] = a21 * b11;
+ dest[3] = a22 * b22;
+ return dest;
+ };
+
+ /**
+ * Returns a string representation of a mat2
+ *
+ * @param {mat2} mat mat2 to represent as a string
+ *
+ * @param {String} String representation of mat
+ */
+ mat2.str = function (mat) {
+ return '[' + mat[0] + ', ' + mat[1] + ', ' + mat[2] + ', ' + mat[3] + ']';
+ };
/*
* Exports
@@ -2258,7 +2770,9 @@
root.setMatrixArrayType = setMatrixArrayType;
root.determineMatrixArrayType = determineMatrixArrayType;
root.glMath = glMath;
+ root.vec2 = vec2;
root.vec3 = vec3;
+ root.mat2 = mat2;
root.mat3 = mat3;
root.mat4 = mat4;
root.quat4 = quat4;
@@ -2270,7 +2784,9 @@
setMatrixArrayType: setMatrixArrayType,
determineMatrixArrayType: determineMatrixArrayType,
glMath: glMath,
+ vec2: vec2,
vec3: vec3,
+ mat2: mat2,
mat3: mat3,
mat4: mat4,
quat4: quat4
View
164 spec/javascripts/mat2_spec.js
@@ -0,0 +1,164 @@
+describe("mat2", function() {
+ var result, a, b, dest;
+
+ beforeEach(function() {
+ a = [1, 2, 3, 4];
+ b = [5, 6, 7, 8];
+ dest = [0, 0, 0, 0];
+ });
+
+ describe("create", function() {
+ describe("with src", function() {
+ beforeEach(function() { result = mat2.create(a); });
+ it("should set result", function() { expect(result).toBeEqualish([1, 2, 3, 4]); });
+ it("should not return a", function() { expect(result).not.toBe(a); });
+ it("should not change a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("with no src", function() {
+ it("should set to 0", function() { expect(mat2.create()).toBeEqualish([0, 0, 0, 0]); });
+ });
+ });
+
+ describe("set", function() {
+ it("should set values in dest to values from src", function() {
+ mat2.set(a, b);
+ expect(b).toBeEqualish(a);
+ });
+
+ it("should return b", function() {
+ expect(mat2.set(a, b)).toBe(b);
+ });
+ });
+
+ describe("identity", function() {
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.identity(dest); });
+ it("should set dest to identity", function() { expect(dest).toBeEqualish([1, 0, 0, 1]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.identity(); });
+ it("should set result to identity", function() { expect(result).toBeEqualish([1, 0, 0, 1]); });
+ });
+ });
+
+ describe("transpose", function() {
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.transpose(a, dest); });
+ it("should set dest to transpose", function() { expect(dest).toBeEqualish([1, 3, 2, 4]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not alter a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.transpose(a); });
+ it("should set a to transpose", function() { expect(a).toBeEqualish([1, 3, 2, 4]); });
+ it("should return a", function() { expect(result).toBe(a); });
+ });
+ });
+
+ describe("determinant", function() {
+ it("should produce the correct result", function() {
+ expect(mat2.determinant(a)).toBeEqualish(-2);
+ });
+ });
+
+ describe("inverse", function() {
+ describe("when no inverse exists", function() {
+ it("should be null", function() {
+ expect(mat2.inverse([3, 4, 6, 8])).toBeNull();
+ });
+ });
+
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.inverse(a = [4, 7, 2, 6], dest); });
+ it("should set dest", function() { expect(dest).toBeEqualish([0.6, -0.7, -0.2, 0.4]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify a", function() { expect(a).toBeEqualish([4, 7, 2, 6]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.inverse(a = [4, 7, 2, 6]); });
+ it("should set a", function() { expect(a).toBeEqualish([0.6, -0.7, -0.2, 0.4]); });
+ it("should return a", function() { expect(result).toBe(a); });
+ });
+ });
+
+ describe("multiply", function() {
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.multiply(a, b, dest); });
+ it("should set dest", function() { expect(dest).toBeEqualish([19, 22, 43, 50]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify b", function() { expect(b).toBeEqualish([5, 6, 7, 8]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.multiply(a, b); });
+ it("should set a", function() { expect(a).toBeEqualish([19, 22, 43, 50]); });
+ it("should not change b", function() { expect(b).toBeEqualish([5, 6, 7, 8]); });
+ it("should return a", function() { expect(result).toBe(a); });
+ });
+ });
+
+ describe("multiplyVec2", function() {
+ beforeEach(function() { b = [5, 6]; dest = [0, 0]; });
+
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.multiplyVec2(a, b, dest); });
+ it("should set dest", function() { expect(dest).toBeEqualish([17, 39]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify b", function() { expect(b).toBeEqualish([5, 6]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.multiplyVec2(a, b); });
+ it("should not change a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ it("should change b", function() { expect(b).toBeEqualish([17, 39]); });
+ it("should return b", function() { expect(result).toBe(b); });
+ });
+ });
+
+ describe("rotate", function() {
+ beforeEach(function() { b = Math.PI/2; });
+
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.rotate(a, b, dest); });
+ it("should set dest", function() { expect(dest).toBeEqualish([2, -1, 4, -3]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.rotate(a, b); });
+ it("should modify a", function() { expect(a).toBeEqualish([2, -1, 4, -3]); });
+ it("should return a", function() { expect(result).toBe(a); });
+ });
+ });
+
+ describe("scale", function() {
+ beforeEach(function() { b = [2, 2] });
+
+ describe("with dest", function() {
+ beforeEach(function() { result = mat2.scale(a, b, dest); });
+ it("should set dest", function() { expect(dest).toBeEqualish([2, 4, 6, 8]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify a", function() { expect(a).toBeEqualish([1, 2, 3, 4]); });
+ it("should not modify b", function() { expect(b).toBeEqualish([2, 2]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat2.scale(a, b); });
+ it("should set a", function() { expect(a).toBeEqualish([2, 4, 6, 8]); });
+ it("should return a", function() { expect(result).toBe(a); });
+ it("should not modify b", function() { expect(b).toBeEqualish([2, 2]); });
+ });
+ });
+
+ describe("str", function() {
+ it("should produce pretty string", function() { expect(mat2.str(a)).toEqual("[1, 2, 3, 4]"); });
+ });
+});
View
22 spec/javascripts/mat3_spec.js
@@ -1,11 +1,29 @@
describe("mat3", function() {
- var mat, vec, dest;
+ var mat, vec, dest, result;
beforeEach(function() {
+ mat = mat3.create([-1, 0, 1, 0, -1, 0, 1, 0, -1]);
vec = vec3.create([1, 2, 3]);
dest = vec3.create();
});
+ describe("multiplyVec2", function() {
+ beforeEach(function() { vec = [1, 2]; dest = vec2.create() });
+
+ describe("with dest", function() {
+ beforeEach(function() { result = mat3.multiplyVec2(mat, vec, dest); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not alter vec", function() { expect(vec).toBeEqualish([1, 2]); });
+ it("should set dest", function() { expect(dest).toBeEqualish([0, -2]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = mat3.multiplyVec2(mat, vec); });
+ it("should return vec", function() { expect(result).toBe(vec); });
+ it("should set vec", function() { expect(vec).toBeEqualish([0, -2]); });
+ });
+ });
+
describe("multiplyVec3", function() {
describe("when set to identity", function() {
beforeEach(function() { mat = mat3.identity(mat3.create()); });
@@ -16,8 +34,6 @@ describe("mat3", function() {
});
describe("with an arbitrary mat3", function() {
- beforeEach(function() { mat = mat3.create([-1, 0, 1, 0, -1, 0, 1, 0, -1]); });
-
describe("given a dest vec3", function() {
it("should not modify incoming vec3", function() {
mat3.multiplyVec3(mat, vec, vec3.create());
View
233 spec/javascripts/vec2_spec.js
@@ -0,0 +1,233 @@
+describe("vec2", function() {
+ var vec, dest;
+ var vecA, vecB, result;
+ beforeEach(function() { vecA = [1, 2]; vecB = [3, 4]; dest = [0, 0]; });
+
+ describe("when Float32Array is not supported", function() {
+ beforeEach(function() { setMatrixArrayType(Array); });
+
+ it("should initialize to 0", function() {
+ vec = vec2.create();
+ expect(vec[0]).toEqual(0);
+ expect(vec[1]).toEqual(0);
+ });
+ });
+
+ describe("str", function() {
+ it("should produce pretty string", function() { expect(vec2.str(vecA)).toEqual("[1, 2]"); });
+ });
+
+ describe("lerp", function() {
+ describe("with dest", function() {
+ beforeEach(function() { result = vec2.lerp(vecA, vecB, 0.5, dest); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should set dest to correct value", function() { expect(dest).toBeEqualish([2, 3]); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = vec2.lerp(vecA, vecB); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should modify vecA", function() { expect(vecA).toBeEqualish([2, 3]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+ });
+
+ describe("direction", function() {
+ describe("with dest", function() {
+ beforeEach(function() { result = vec2.direction(vecA, vecB, dest); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should set dest to correct value", function() { expect(dest).toBeEqualish([ -0.707106, -0.707106 ]); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("without dest", function() {
+ beforeEach(function() { result = vec2.direction(vecA, vecB); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should modify vecA", function() { expect(vecA).toBeEqualish([-0.707106, -0.707106]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+ });
+
+ describe("dot", function() {
+ it("should return dot product", function() { expect(vec2.dot(vecA, vecB)).toBeEqualish(11); });
+ });
+
+ describe("length", function() {
+ it("should return the correct value", function() { expect(vec2.length(vecA)).toBeEqualish(2.236067); });
+ });
+
+ describe("cross", function() {
+ describe("with dest given", function() {
+ beforeEach(function() { result = vec2.cross(vecA, vecB, dest); });
+ it("should store the cross in dest", function() { expect(dest).toBeEqualish([0, 0, -2]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not alter vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not alter vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("with no dest given", function() {
+ beforeEach(function() { result = vec2.cross(vecA, vecB); });
+ it("should return the scalar Z value", function() { expect(result).toBeEqualish(-2); });
+ it("should not alter vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not alter vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+ });
+
+ describe("normalize", function() {
+ describe("with dest given", function() {
+ beforeEach(function() { result = vec2.normalize(vecA, dest); });
+ it("should store normal in dest", function() { expect(dest).toBeEqualish([ 0.4472135954999579, 0.8944271909999159 ]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not alter vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("with dest not given", function() {
+ beforeEach(function() { result = vec2.normalize(vecA); });
+ it("should store normal in vecA", function() { expect(vecA).toBeEqualish([ 0.4472135954999579, 0.8944271909999159 ]); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ });
+ });
+
+ describe("negate", function() {
+ describe("with dest given", function() {
+ beforeEach(function() { result = vec2.negate(vecA, dest); });
+ it("should store negation in dest", function() { expect(dest).toBeEqualish([-1, -2]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not alter vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("with dest not given", function() {
+ beforeEach(function() { result = vec2.negate(vecA); });
+ it("should return vecA", function() { expect(result).toBe(vecA); });
+ it("should alter vecA", function() { expect(vecA).toBeEqualish([-1, -2]); });
+ });
+ });
+
+ describe("set", function() {
+ beforeEach(function() { result = vec2.set(vecA, dest); });
+ it("should assign values", function() { expect(dest).toBeEqualish([1, 2]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ });
+
+ describe("dist", function() {
+ beforeEach(function() { result = vec2.dist(vecA, vecB); });
+
+ it("should return dest", function() { expect(result).toBeEqualish(2.828427); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("scale", function() {
+ describe("with dest vec2", function() {
+ beforeEach(function() { result = vec2.scale(vecA, 0.5, dest); });
+
+ it("should place values into dest", function() { expect(dest).toBeEqualish([0.5, 1]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+
+ describe("without dest vec2", function() {
+ beforeEach(function() { result = vec2.scale(vecA, vecB); });
+
+ it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.5, 1]); });
+ });
+ });
+
+ describe("add", function() {
+ describe("with dest vec2", function() {
+ beforeEach(function() { result = vec2.add(vecA, vecB, dest); });
+
+ it("should place values into dest", function() { expect(dest).toBeEqualish([4, 6]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("without dest vec2", function() {
+ beforeEach(function() { result = vec2.add(vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([4, 6]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("subtract", function() {
+ describe("with dest vec2", function() {
+ beforeEach(function() { result = vec2.subtract(vecA, vecB, dest); });
+
+ it("should place values into dest", function() { expect(dest).toBeEqualish([-2, -2]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("without dest vec2", function() {
+ beforeEach(function() { result = vec2.subtract(vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([-2, -2]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("multiply", function() {
+ describe("with dest vec2", function() {
+ beforeEach(function() { result = vec2.multiply(vecA, vecB, dest); });
+
+ it("should place values into dest", function() { expect(dest).toBeEqualish([3, 8]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("without dest vec2", function() {
+ beforeEach(function() { result = vec2.multiply(vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 8]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("divide", function() {
+ describe("with dest vec2", function() {
+ beforeEach(function() { result = vec2.divide(vecA, vecB, dest); });
+
+ it("should place values into dest", function() { expect(dest).toBeEqualish([0.333333, 0.5]); });
+ it("should return dest", function() { expect(result).toBe(dest); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); });
+ });
+
+ describe("without dest vec2", function() {
+ beforeEach(function() { result = vec2.divide(vecA, vecB); });
+
+ it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.333333, 0.5]); });
+ it("should return vecB", function() { expect(result).toBe(vecB); });
+ it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); });
+ });
+ });
+
+ describe("create", function() {
+ describe("with vec", function() {
+ it("should clone vec's contents", function() {
+ expect(vec2.create([1, 2])).toBeEqualish([1, 2]);
+ });
+
+ it("should not return vec", function() {
+ vec = [1, 2];
+ expect(vec2.create(vec)).not.toBe(vec);
+ });
+ });
+
+ describe("without vec", function() {
+ it("should initialize components to 0", function() {
+ expect(vec2.create()).toBeEqualish([0, 0]);
+ });
+ });
+ });
+});

0 comments on commit 9c117cb

Please sign in to comment.