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("vec3", function() { 24 var out, vecA, vecB, result; 25 26 beforeEach(function() { vecA = [1, 2, 3]; vecB = [4, 5, 6]; out = [0, 0, 0]; }); 27 28 describe("create", function() { 29 beforeEach(function() { result = vec3.create(); }); 30 it("should return a 3 element array initialized to 0s", function() { expect(result).toBeEqualish([0, 0, 0]); }); 31 }); 32 33 describe("clone", function() { 34 beforeEach(function() { result = vec3.clone(vecA); }); 35 it("should return a 3 element array initialized to the values in vecA", function() { expect(result).toBeEqualish(vecA); }); 36 }); 37 38 describe("fromValues", function() { 39 beforeEach(function() { result = vec3.fromValues(1, 2, 3); }); 40 it("should return a 3 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3]); }); 41 }); 42 43 describe("copy", function() { 44 beforeEach(function() { result = vec3.copy(out, vecA); }); 45 it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3]); }); 46 it("should return out", function() { expect(result).toBe(out); }); 47 }); 48 49 describe("set", function() { 50 beforeEach(function() { result = vec3.set(out, 1, 2, 3); }); 51 it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3]); }); 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 = vec3.add(out, vecA, vecB); }); 58 59 it("should place values into out", function() { expect(out).toBeEqualish([5, 7, 9]); }); 60 it("should return out", function() { expect(result).toBe(out); }); 61 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 62 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 63 }); 64 65 describe("when vecA is the output vector", function() { 66 beforeEach(function() { result = vec3.add(vecA, vecA, vecB); }); 67 68 it("should place values into vecA", function() { expect(vecA).toBeEqualish([5, 7, 9]); }); 69 it("should return vecA", function() { expect(result).toBe(vecA); }); 70 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 71 }); 72 73 describe("when vecB is the output vector", function() { 74 beforeEach(function() { result = vec3.add(vecB, vecA, vecB); }); 75 76 it("should place values into vecB", function() { expect(vecB).toBeEqualish([5, 7, 9]); }); 77 it("should return vecB", function() { expect(result).toBe(vecB); }); 78 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 79 }); 80 }); 81 82 describe("subtract", function() { 83 it("should have an alias called 'sub'", function() { expect(vec3.sub).toEqual(vec3.subtract); }); 84 85 describe("with a separate output vector", function() { 86 beforeEach(function() { result = vec3.subtract(out, vecA, vecB); }); 87 88 it("should place values into out", function() { expect(out).toBeEqualish([-3, -3, -3]); }); 89 it("should return out", function() { expect(result).toBe(out); }); 90 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 91 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 92 }); 93 94 describe("when vecA is the output vector", function() { 95 beforeEach(function() { result = vec3.subtract(vecA, vecA, vecB); }); 96 97 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-3, -3, -3]); }); 98 it("should return vecA", function() { expect(result).toBe(vecA); }); 99 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 100 }); 101 102 describe("when vecB is the output vector", function() { 103 beforeEach(function() { result = vec3.subtract(vecB, vecA, vecB); }); 104 105 it("should place values into vecB", function() { expect(vecB).toBeEqualish([-3, -3, -3]); }); 106 it("should return vecB", function() { expect(result).toBe(vecB); }); 107 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 108 }); 109 }); 110 111 describe("multiply", function() { 112 it("should have an alias called 'mul'", function() { expect(vec3.mul).toEqual(vec3.multiply); }); 113 114 describe("with a separate output vector", function() { 115 beforeEach(function() { result = vec3.multiply(out, vecA, vecB); }); 116 117 it("should place values into out", function() { expect(out).toBeEqualish([4, 10, 18]); }); 118 it("should return out", function() { expect(result).toBe(out); }); 119 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 120 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 121 }); 122 123 describe("when vecA is the output vector", function() { 124 beforeEach(function() { result = vec3.multiply(vecA, vecA, vecB); }); 125 126 it("should place values into vecA", function() { expect(vecA).toBeEqualish([4, 10, 18]); }); 127 it("should return vecA", function() { expect(result).toBe(vecA); }); 128 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 129 }); 130 131 describe("when vecB is the output vector", function() { 132 beforeEach(function() { result = vec3.multiply(vecB, vecA, vecB); }); 133 134 it("should place values into vecB", function() { expect(vecB).toBeEqualish([4, 10, 18]); }); 135 it("should return vecB", function() { expect(result).toBe(vecB); }); 136 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 137 }); 138 }); 139 140 describe("divide", function() { 141 it("should have an alias called 'div'", function() { expect(vec3.div).toEqual(vec3.divide); }); 142 143 describe("with a separate output vector", function() { 144 beforeEach(function() { result = vec3.divide(out, vecA, vecB); }); 145 146 it("should place values into out", function() { expect(out).toBeEqualish([0.25, 0.4, 0.5]); }); 147 it("should return out", function() { expect(result).toBe(out); }); 148 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 149 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 150 }); 151 152 describe("when vecA is the output vector", function() { 153 beforeEach(function() { result = vec3.divide(vecA, vecA, vecB); }); 154 155 it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.25, 0.4, 0.5]); }); 156 it("should return vecA", function() { expect(result).toBe(vecA); }); 157 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 158 }); 159 160 describe("when vecB is the output vector", function() { 161 beforeEach(function() { result = vec3.divide(vecB, vecA, vecB); }); 162 163 it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.25, 0.4, 0.5]); }); 164 it("should return vecB", function() { expect(result).toBe(vecB); }); 165 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 166 }); 167 }); 168 169 describe("min", function() { 170 beforeEach(function() { vecA = [1, 3, 1]; vecB = [3, 1, 3]; }); 171 172 describe("with a separate output vector", function() { 173 beforeEach(function() { result = vec3.min(out, vecA, vecB); }); 174 175 it("should place values into out", function() { expect(out).toBeEqualish([1, 1, 1]); }); 176 it("should return out", function() { expect(result).toBe(out); }); 177 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); }); 178 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); }); 179 }); 180 181 describe("when vecA is the output vector", function() { 182 beforeEach(function() { result = vec3.min(vecA, vecA, vecB); }); 183 184 it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 1, 1]); }); 185 it("should return vecA", function() { expect(result).toBe(vecA); }); 186 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); }); 187 }); 188 189 describe("when vecB is the output vector", function() { 190 beforeEach(function() { result = vec3.min(vecB, vecA, vecB); }); 191 192 it("should place values into vecB", function() { expect(vecB).toBeEqualish([1, 1, 1]); }); 193 it("should return vecB", function() { expect(result).toBe(vecB); }); 194 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); }); 195 }); 196 }); 197 198 describe("max", function() { 199 beforeEach(function() { vecA = [1, 3, 1]; vecB = [3, 1, 3]; }); 200 201 describe("with a separate output vector", function() { 202 beforeEach(function() { result = vec3.max(out, vecA, vecB); }); 203 204 it("should place values into out", function() { expect(out).toBeEqualish([3, 3, 3]); }); 205 it("should return out", function() { expect(result).toBe(out); }); 206 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); }); 207 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); }); 208 }); 209 210 describe("when vecA is the output vector", function() { 211 beforeEach(function() { result = vec3.max(vecA, vecA, vecB); }); 212 213 it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 3, 3]); }); 214 it("should return vecA", function() { expect(result).toBe(vecA); }); 215 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3]); }); 216 }); 217 218 describe("when vecB is the output vector", function() { 219 beforeEach(function() { result = vec3.max(vecB, vecA, vecB); }); 220 221 it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 3, 3]); }); 222 it("should return vecB", function() { expect(result).toBe(vecB); }); 223 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1]); }); 224 }); 225 }); 226 227 describe("scale", function() { 228 describe("with a separate output vector", function() { 229 beforeEach(function() { result = vec3.scale(out, vecA, 2); }); 230 231 it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6]); }); 232 it("should return out", function() { expect(result).toBe(out); }); 233 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 234 }); 235 236 describe("when vecA is the output vector", function() { 237 beforeEach(function() { result = vec3.scale(vecA, vecA, 2); }); 238 239 it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 4, 6]); }); 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(vec3.dist).toEqual(vec3.distance); }); 246 247 beforeEach(function() { result = vec3.distance(vecA, vecB); }); 248 249 it("should return the distance", function() { expect(result).toBeCloseTo(5.196152); }); 250 }); 251 252 describe("squaredDistance", function() { 253 it("should have an alias called 'sqrDist'", function() { expect(vec3.sqrDist).toEqual(vec3.squaredDistance); }); 254 255 beforeEach(function() { result = vec3.squaredDistance(vecA, vecB); }); 256 257 it("should return the squared distance", function() { expect(result).toEqual(27); }); 258 }); 259 260 describe("length", function() { 261 it("should have an alias called 'len'", function() { expect(vec3.len).toEqual(vec3.length); }); 262 263 beforeEach(function() { result = vec3.length(vecA); }); 264 265 it("should return the length", function() { expect(result).toBeCloseTo(3.741657); }); 266 }); 267 268 describe("squaredLength", function() { 269 it("should have an alias called 'sqrLen'", function() { expect(vec3.sqrLen).toEqual(vec3.squaredLength); }); 270 271 beforeEach(function() { result = vec3.squaredLength(vecA); }); 272 273 it("should return the squared length", function() { expect(result).toEqual(14); }); 274 }); 275 276 describe("negate", function() { 277 describe("with a separate output vector", function() { 278 beforeEach(function() { result = vec3.negate(out, vecA); }); 279 280 it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3]); }); 281 it("should return out", function() { expect(result).toBe(out); }); 282 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 283 }); 284 285 describe("when vecA is the output vector", function() { 286 beforeEach(function() { result = vec3.negate(vecA, vecA); }); 287 288 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-1, -2, -3]); }); 289 it("should return vecA", function() { expect(result).toBe(vecA); }); 290 }); 291 }); 292 293 describe("normalize", function() { 294 beforeEach(function() { vecA = [5, 0, 0]; }); 295 296 describe("with a separate output vector", function() { 297 beforeEach(function() { result = vec3.normalize(out, vecA); }); 298 299 it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0]); }); 300 it("should return out", function() { expect(result).toBe(out); }); 301 it("should not modify vecA", function() { expect(vecA).toBeEqualish([5, 0, 0]); }); 302 }); 303 304 describe("when vecA is the output vector", function() { 305 beforeEach(function() { result = vec3.normalize(vecA, vecA); }); 306 307 it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 0, 0]); }); 308 it("should return vecA", function() { expect(result).toBe(vecA); }); 309 }); 310 }); 311 312 describe("dot", function() { 313 beforeEach(function() { result = vec3.dot(vecA, vecB); }); 314 315 it("should return the dot product", function() { expect(result).toEqual(32); }); 316 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 317 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 318 }); 319 320 describe("cross", function() { 321 describe("with a separate output vector", function() { 322 beforeEach(function() { result = vec3.cross(out, vecA, vecB); }); 323 324 it("should place values into out", function() { expect(out).toBeEqualish([-3, 6, -3]); }); 325 it("should return out", function() { expect(result).toBe(out); }); 326 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 327 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 328 }); 329 330 describe("when vecA is the output vector", function() { 331 beforeEach(function() { result = vec3.cross(vecA, vecA, vecB); }); 332 333 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-3, 6, -3]); }); 334 it("should return vecA", function() { expect(result).toBe(vecA); }); 335 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 336 }); 337 338 describe("when vecB is the output vector", function() { 339 beforeEach(function() { result = vec3.cross(vecB, vecA, vecB); }); 340 341 it("should place values into vecB", function() { expect(vecB).toBeEqualish([-3, 6, -3]); }); 342 it("should return vecB", function() { expect(result).toBe(vecB); }); 343 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 344 }); 345 }); 346 347 describe("lerp", function() { 348 describe("with a separate output vector", function() { 349 beforeEach(function() { result = vec3.lerp(out, vecA, vecB, 0.5); }); 350 351 it("should place values into out", function() { expect(out).toBeEqualish([2.5, 3.5, 4.5]); }); 352 it("should return out", function() { expect(result).toBe(out); }); 353 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 354 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 355 }); 356 357 describe("when vecA is the output vector", function() { 358 beforeEach(function() { result = vec3.lerp(vecA, vecA, vecB, 0.5); }); 359 360 it("should place values into vecA", function() { expect(vecA).toBeEqualish([2.5, 3.5, 4.5]); }); 361 it("should return vecA", function() { expect(result).toBe(vecA); }); 362 it("should not modify vecB", function() { expect(vecB).toBeEqualish([4, 5, 6]); }); 363 }); 364 365 describe("when vecB is the output vector", function() { 366 beforeEach(function() { result = vec3.lerp(vecB, vecA, vecB, 0.5); }); 367 368 it("should place values into vecB", function() { expect(vecB).toBeEqualish([2.5, 3.5, 4.5]); }); 369 it("should return vecB", function() { expect(result).toBe(vecB); }); 370 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 371 }); 372 }); 373 374 describe("forEach", function() { 375 var vecArray; 376 377 beforeEach(function() { 378 vecArray = [ 379 1, 2, 3, 380 4, 5, 6, 381 0, 0, 0 382 ]; 383 }); 384 385 describe("when performing operations that take no extra arguments", function() { 386 beforeEach(function() { result = vec3.forEach(vecArray, 0, 0, 0, vec3.normalize); }); 387 388 it("should update all values", function() { 389 expect(vecArray).toBeEqualish([ 390 0.267261, 0.534522, 0.801783, 391 0.455842, 0.569802, 0.683763, 392 0, 0, 0 393 ]); 394 }); 395 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 396 }); 397 398 describe("when performing operations that takes one extra arguments", function() { 399 beforeEach(function() { result = vec3.forEach(vecArray, 0, 0, 0, vec3.add, vecA); }); 400 401 it("should update all values", function() { 402 expect(vecArray).toBeEqualish([ 403 2, 4, 6, 404 5, 7, 9, 405 1, 2, 3 406 ]); 407 }); 408 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 409 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 410 }); 411 412 describe("when specifying an offset", function() { 413 beforeEach(function() { result = vec3.forEach(vecArray, 0, 3, 0, vec3.add, vecA); }); 414 415 it("should update all values except the first vector", function() { 416 expect(vecArray).toBeEqualish([ 417 1, 2, 3, 418 5, 7, 9, 419 1, 2, 3 420 ]); 421 }); 422 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 423 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 424 }); 425 426 describe("when specifying a count", function() { 427 beforeEach(function() { result = vec3.forEach(vecArray, 0, 0, 2, vec3.add, vecA); }); 428 429 it("should update all values except the last vector", function() { 430 expect(vecArray).toBeEqualish([ 431 2, 4, 6, 432 5, 7, 9, 433 0, 0, 0 434 ]); 435 }); 436 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 437 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 438 }); 439 440 describe("when specifying a stride", function() { 441 beforeEach(function() { result = vec3.forEach(vecArray, 6, 0, 0, vec3.add, vecA); }); 442 443 it("should update all values except the second vector", function() { 444 expect(vecArray).toBeEqualish([ 445 2, 4, 6, 446 4, 5, 6, 447 1, 2, 3 448 ]); 449 }); 450 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 451 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3]); }); 452 }); 453 454 describe("when calling a function that does not modify the out variable", function() { 455 beforeEach(function() { 456 result = vec3.forEach(vecArray, 0, 0, 0, function(out, vec) {}); 457 }); 458 459 it("values should remain unchanged", function() { 460 expect(vecArray).toBeEqualish([ 461 1, 2, 3, 462 4, 5, 6, 463 0, 0, 0 464 ]); 465 }); 466 it("should return vecArray", function() { expect(result).toBe(vecArray); }); 467 }); 468 }); 469 470 describe("str", function() { 471 beforeEach(function() { result = vec3.str(vecA); }); 472 473 it("should return a string representation of the vector", function() { expect(result).toEqual("vec3(1, 2, 3)"); }); 474 }); 475}); 476