1/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2 3Redistribution and use in source and binary forms, with or without modification, 4are permitted provided that the following conditions are met: 5 6 * Redistributions of source code must retain the above copyright notice, this 7 list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright notice, 9 this list of conditions and the following disclaimer in the documentation 10 and/or other materials provided with the distribution. 11 12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 22 23describe("vec2", function() { 24 var out, vecA, vecB, result; 25 26 beforeEach(function() { vecA = [1, 2]; vecB = [3, 4]; out = [0, 0]; }); 27 28 describe("create", function() { 29 beforeEach(function() { result = vec2.create(); }); 30 it("should return a 2 element array initialized to 0s", function() { expect(result).toBeEqualish([0, 0]); }); 31 }); 32 33 describe("clone", function() { 34 beforeEach(function() { result = vec2.clone(vecA); }); 35 it("should return a 2 element array initialized to the values in vecA", function() { expect(result).toBeEqualish(vecA); }); 36 }); 37 38 describe("fromValues", function() { 39 beforeEach(function() { result = vec2.fromValues(1, 2); }); 40 it("should return a 2 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2]); }); 41 }); 42 43 describe("copy", function() { 44 beforeEach(function() { result = vec2.copy(out, vecA); }); 45 it("should place values into out", function() { expect(out).toBeEqualish([1, 2]); }); 46 it("should return out", function() { expect(result).toBe(out); }); 47 }); 48 49 describe("set", function() { 50 beforeEach(function() { result = vec2.set(out, 1, 2); }); 51 it("should place values into out", function() { expect(out).toBeEqualish([1, 2]); }); 52 it("should return out", function() { expect(result).toBe(out); }); 53 }); 54 55 describe("add", function() { 56 describe("with a separate output vector", function() { 57 beforeEach(function() { result = vec2.add(out, vecA, vecB); }); 58 59 it("should place values into out", function() { expect(out).toBeEqualish([4, 6]); }); 60 it("should return out", function() { expect(result).toBe(out); }); 61 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 62 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 63 }); 64 65 describe("when vecA is the output vector", function() { 66 beforeEach(function() { result = vec2.add(vecA, vecA, vecB); }); 67 68 it("should place values into vecA", function() { expect(vecA).toBeEqualish([4, 6]); }); 69 it("should return vecA", function() { expect(result).toBe(vecA); }); 70 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 71 }); 72 73 describe("when vecB is the output vector", function() { 74 beforeEach(function() { result = vec2.add(vecB, vecA, vecB); }); 75 76 it("should place values into vecB", function() { expect(vecB).toBeEqualish([4, 6]); }); 77 it("should return vecB", function() { expect(result).toBe(vecB); }); 78 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 79 }); 80 }); 81 82 describe("subtract", function() { 83 it("should have an alias called 'sub'", function() { expect(vec2.sub).toEqual(vec2.subtract); }); 84 85 describe("with a separate output vector", function() { 86 beforeEach(function() { result = vec2.subtract(out, vecA, vecB); }); 87 88 it("should place values into out", function() { expect(out).toBeEqualish([-2, -2]); }); 89 it("should return out", function() { expect(result).toBe(out); }); 90 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 91 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 92 }); 93 94 describe("when vecA is the output vector", function() { 95 beforeEach(function() { result = vec2.subtract(vecA, vecA, vecB); }); 96 97 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-2, -2]); }); 98 it("should return vecA", function() { expect(result).toBe(vecA); }); 99 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 100 }); 101 102 describe("when vecB is the output vector", function() { 103 beforeEach(function() { result = vec2.subtract(vecB, vecA, vecB); }); 104 105 it("should place values into vecB", function() { expect(vecB).toBeEqualish([-2, -2]); }); 106 it("should return vecB", function() { expect(result).toBe(vecB); }); 107 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 108 }); 109 }); 110 111 describe("multiply", function() { 112 it("should have an alias called 'mul'", function() { expect(vec2.mul).toEqual(vec2.multiply); }); 113 114 describe("with a separate output vector", function() { 115 beforeEach(function() { result = vec2.multiply(out, vecA, vecB); }); 116 117 it("should place values into out", function() { expect(out).toBeEqualish([3, 8]); }); 118 it("should return out", function() { expect(result).toBe(out); }); 119 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 120 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 121 }); 122 123 describe("when vecA is the output vector", function() { 124 beforeEach(function() { result = vec2.multiply(vecA, vecA, vecB); }); 125 126 it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 8]); }); 127 it("should return vecA", function() { expect(result).toBe(vecA); }); 128 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 129 }); 130 131 describe("when vecB is the output vector", function() { 132 beforeEach(function() { result = vec2.multiply(vecB, vecA, vecB); }); 133 134 it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 8]); }); 135 it("should return vecB", function() { expect(result).toBe(vecB); }); 136 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 137 }); 138 }); 139 140 describe("divide", function() { 141 it("should have an alias called 'div'", function() { expect(vec2.div).toEqual(vec2.divide); }); 142 143 describe("with a separate output vector", function() { 144 beforeEach(function() { result = vec2.divide(out, vecA, vecB); }); 145 146 it("should place values into out", function() { expect(out).toBeEqualish([0.3333333, 0.5]); }); 147 it("should return out", function() { expect(result).toBe(out); }); 148 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 149 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 150 }); 151 152 describe("when vecA is the output vector", function() { 153 beforeEach(function() { result = vec2.divide(vecA, vecA, vecB); }); 154 155 it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.3333333, 0.5]); }); 156 it("should return vecA", function() { expect(result).toBe(vecA); }); 157 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 158 }); 159 160 describe("when vecB is the output vector", function() { 161 beforeEach(function() { result = vec2.divide(vecB, vecA, vecB); }); 162 163 it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.3333333, 0.5]); }); 164 it("should return vecB", function() { expect(result).toBe(vecB); }); 165 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 166 }); 167 }); 168 169 describe("min", function() { 170 beforeEach(function() { vecA = [1, 4]; vecB = [3, 2]; }); 171 172 describe("with a separate output vector", function() { 173 beforeEach(function() { result = vec2.min(out, vecA, vecB); }); 174 175 it("should place values into out", function() { expect(out).toBeEqualish([1, 2]); }); 176 it("should return out", function() { expect(result).toBe(out); }); 177 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); }); 178 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); }); 179 }); 180 181 describe("when vecA is the output vector", function() { 182 beforeEach(function() { result = vec2.min(vecA, vecA, vecB); }); 183 184 it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 185 it("should return vecA", function() { expect(result).toBe(vecA); }); 186 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); }); 187 }); 188 189 describe("when vecB is the output vector", function() { 190 beforeEach(function() { result = vec2.min(vecB, vecA, vecB); }); 191 192 it("should place values into vecB", function() { expect(vecB).toBeEqualish([1, 2]); }); 193 it("should return vecB", function() { expect(result).toBe(vecB); }); 194 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); }); 195 }); 196 }); 197 198 describe("max", function() { 199 beforeEach(function() { vecA = [1, 4]; vecB = [3, 2]; }); 200 201 describe("with a separate output vector", function() { 202 beforeEach(function() { result = vec2.max(out, vecA, vecB); }); 203 204 it("should place values into out", function() { expect(out).toBeEqualish([3, 4]); }); 205 it("should return out", function() { expect(result).toBe(out); }); 206 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); }); 207 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); }); 208 }); 209 210 describe("when vecA is the output vector", function() { 211 beforeEach(function() { result = vec2.max(vecA, vecA, vecB); }); 212 213 it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 4]); }); 214 it("should return vecA", function() { expect(result).toBe(vecA); }); 215 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 2]); }); 216 }); 217 218 describe("when vecB is the output vector", function() { 219 beforeEach(function() { result = vec2.max(vecB, vecA, vecB); }); 220 221 it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 222 it("should return vecB", function() { expect(result).toBe(vecB); }); 223 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 4]); }); 224 }); 225 }); 226 227 describe("scale", function() { 228 describe("with a separate output vector", function() { 229 beforeEach(function() { result = vec2.scale(out, vecA, 2); }); 230 231 it("should place values into out", function() { expect(out).toBeEqualish([2, 4]); }); 232 it("should return out", function() { expect(result).toBe(out); }); 233 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 234 }); 235 236 describe("when vecA is the output vector", function() { 237 beforeEach(function() { result = vec2.scale(vecA, vecA, 2); }); 238 239 it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 4]); }); 240 it("should return vecA", function() { expect(result).toBe(vecA); }); 241 }); 242 }); 243 244 describe("distance", function() { 245 it("should have an alias called 'dist'", function() { expect(vec2.dist).toEqual(vec2.distance); }); 246 247 beforeEach(function() { result = vec2.distance(vecA, vecB); }); 248 249 it("should return the distance", function() { expect(result).toBeCloseTo(2.828427); }); 250 }); 251 252 describe("squaredDistance", function() { 253 it("should have an alias called 'sqrDist'", function() { expect(vec2.sqrDist).toEqual(vec2.squaredDistance); }); 254 255 beforeEach(function() { result = vec2.squaredDistance(vecA, vecB); }); 256 257 it("should return the squared distance", function() { expect(result).toEqual(8); }); 258 }); 259 260 describe("length", function() { 261 it("should have an alias called 'len'", function() { expect(vec2.len).toEqual(vec2.length); }); 262 263 beforeEach(function() { result = vec2.length(vecA); }); 264 265 it("should return the length", function() { expect(result).toBeCloseTo(2.236067); }); 266 }); 267 268 describe("squaredLength", function() { 269 it("should have an alias called 'sqrLen'", function() { expect(vec2.sqrLen).toEqual(vec2.squaredLength); }); 270 271 beforeEach(function() { result = vec2.squaredLength(vecA); }); 272 273 it("should return the squared length", function() { expect(result).toEqual(5); }); 274 }); 275 276 describe("negate", function() { 277 describe("with a separate output vector", function() { 278 beforeEach(function() { result = vec2.negate(out, vecA); }); 279 280 it("should place values into out", function() { expect(out).toBeEqualish([-1, -2]); }); 281 it("should return out", function() { expect(result).toBe(out); }); 282 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 283 }); 284 285 describe("when vecA is the output vector", function() { 286 beforeEach(function() { result = vec2.negate(vecA, vecA); }); 287 288 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-1, -2]); }); 289 it("should return vecA", function() { expect(result).toBe(vecA); }); 290 }); 291 }); 292 293 describe("normalize", function() { 294 beforeEach(function() { vecA = [5, 0]; }); 295 296 describe("with a separate output vector", function() { 297 beforeEach(function() { result = vec2.normalize(out, vecA); }); 298 299 it("should place values into out", function() { expect(out).toBeEqualish([1, 0]); }); 300 it("should return out", function() { expect(result).toBe(out); }); 301 it("should not modify vecA", function() { expect(vecA).toBeEqualish([5, 0]); }); 302 }); 303 304 describe("when vecA is the output vector", function() { 305 beforeEach(function() { result = vec2.normalize(vecA, vecA); }); 306 307 it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 0]); }); 308 it("should return vecA", function() { expect(result).toBe(vecA); }); 309 }); 310 }); 311 312 describe("dot", function() { 313 beforeEach(function() { result = vec2.dot(vecA, vecB); }); 314 315 it("should return the dot product", function() { expect(result).toEqual(11); }); 316 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 317 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 318 }); 319 320 describe("cross", function() { 321 var out3; 322 323 beforeEach(function() { 324 out3 = [0, 0, 0]; 325 result = vec2.cross(out3, vecA, vecB); 326 }); 327 328 it("should place values into out", function() { expect(out3).toBeEqualish([0, 0, -2]); }); 329 it("should return out", function() { expect(result).toBe(out3); }); 330 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 331 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 332 }); 333 334 describe("lerp", function() { 335 describe("with a separate output vector", function() { 336 beforeEach(function() { result = vec2.lerp(out, vecA, vecB, 0.5); }); 337 338 it("should place values into out", function() { expect(out).toBeEqualish([2, 3]); }); 339 it("should return out", function() { expect(result).toBe(out); }); 340 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 341 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 342 }); 343 344 describe("when vecA is the output vector", function() { 345 beforeEach(function() { result = vec2.lerp(vecA, vecA, vecB, 0.5); }); 346 347 it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 3]); }); 348 it("should return vecA", function() { expect(result).toBe(vecA); }); 349 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 4]); }); 350 }); 351 352 describe("when vecB is the output vector", function() { 353 beforeEach(function() { result = vec2.lerp(vecB, vecA, vecB, 0.5); }); 354 355 it("should place values into vecB", function() { expect(vecB).toBeEqualish([2, 3]); }); 356 it("should return vecB", function() { expect(result).toBe(vecB); }); 357 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 358 }); 359 }); 360 361 describe("transformMat2", function() { 362 var matA; 363 beforeEach(function() { matA = [1, 2, 3, 4]; }); 364 365 describe("with a separate output vector", function() { 366 beforeEach(function() { result = vec2.transformMat2(out, vecA, matA); }); 367 368 it("should place values into out", function() { expect(out).toBeEqualish([7, 10]); }); 369 it("should return out", function() { expect(result).toBe(out); }); 370 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 371 it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); }); 372 }); 373 374 describe("when vecA is the output vector", function() { 375 beforeEach(function() { result = vec2.transformMat2(vecA, vecA, matA); }); 376 377 it("should place values into vecA", function() { expect(vecA).toBeEqualish([7, 10]); }); 378 it("should return vecA", function() { expect(result).toBe(vecA); }); 379 it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); }); 380 }); 381 }); 382 383 describe("transformMat2d", function() { 384 var matA; 385 beforeEach(function() { matA = [1, 2, 3, 4, 5, 6]; }); 386 387 describe("with a separate output vector", function() { 388 beforeEach(function() { result = vec2.transformMat2d(out, vecA, matA); }); 389 390 it("should place values into out", function() { expect(out).toBeEqualish([12, 16]); }); 391 it("should return out", function() { expect(result).toBe(out); }); 392 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 393 it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4, 5, 6]); }); 394 }); 395 396 describe("when vecA is the output vector", function() { 397 beforeEach(function() { result = vec2.transformMat2d(vecA, vecA, matA); }); 398 399 it("should place values into vecA", function() { expect(vecA).toBeEqualish([12, 16]); }); 400 it("should return vecA", function() { expect(result).toBe(vecA); }); 401 it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4, 5, 6]); }); 402 }); 403 }); 404 405 describe("forEach", function() { 406 var vecArray; 407 408 beforeEach(function() { 409 vecArray = [ 410 1, 2, 411 3, 4, 412 0, 0 413 ]; 414 }); 415 416 describe("when performing operations that take no extra arguments", function() { 417 beforeEach(function() { result = vec2.forEach(vecArray, 0, 0, 0, vec2.normalize); }); 418 419 it("should update all values", function() { 420 expect(vecArray).toBeEqualish([ 421 0.447214, 0.894427, 422 0.6, 0.8, 423 0, 0 424 ]); 425 }); 426 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 427 }); 428 429 describe("when performing operations that takes one extra arguments", function() { 430 beforeEach(function() { result = vec2.forEach(vecArray, 0, 0, 0, vec2.add, vecA); }); 431 432 it("should update all values", function() { 433 expect(vecArray).toBeEqualish([ 434 2, 4, 435 4, 6, 436 1, 2 437 ]); 438 }); 439 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 440 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 441 }); 442 443 describe("when specifying an offset", function() { 444 beforeEach(function() { result = vec2.forEach(vecArray, 0, 2, 0, vec2.add, vecA); }); 445 446 it("should update all values except the first vector", function() { 447 expect(vecArray).toBeEqualish([ 448 1, 2, 449 4, 6, 450 1, 2 451 ]); 452 }); 453 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 454 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 455 }); 456 457 describe("when specifying a count", function() { 458 beforeEach(function() { result = vec2.forEach(vecArray, 0, 0, 2, vec2.add, vecA); }); 459 460 it("should update all values except the last vector", function() { 461 expect(vecArray).toBeEqualish([ 462 2, 4, 463 4, 6, 464 0, 0 465 ]); 466 }); 467 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 468 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 469 }); 470 471 describe("when specifying a stride", function() { 472 beforeEach(function() { result = vec2.forEach(vecArray, 4, 0, 0, vec2.add, vecA); }); 473 474 it("should update all values except the second vector", function() { 475 expect(vecArray).toBeEqualish([ 476 2, 4, 477 3, 4, 478 1, 2 479 ]); 480 }); 481 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 482 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2]); }); 483 }); 484 485 describe("when calling a function that does not modify the out variable", function() { 486 beforeEach(function() { 487 result = vec2.forEach(vecArray, 0, 0, 0, function(out, vec) {}); 488 }); 489 490 it("values should remain unchanged", function() { 491 expect(vecArray).toBeEqualish([ 492 1, 2, 493 3, 4, 494 0, 0, 495 ]); 496 }); 497 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 498 }); 499 }); 500 501 describe("str", function() { 502 beforeEach(function() { result = vec2.str(vecA); }); 503 504 it("should return a string representation of the vector", function() { expect(result).toEqual("vec2(1, 2)"); }); 505 }); 506}); 507