1 /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. 2 3 Redistribution and use in source and binary forms, with or without modification, 4 are 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 12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 16 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 ANY 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 21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 22 23 describe("mat4", function() { 24 var out, matA, matB, identity, result; 25 26 beforeEach(function() { 27 // Attempting to portray a semi-realistic transform matrix 28 matA = [1, 0, 0, 0, 29 0, 1, 0, 0, 30 0, 0, 1, 0, 31 1, 2, 3, 1]; 32 33 matB = [1, 0, 0, 0, 34 0, 1, 0, 0, 35 0, 0, 1, 0, 36 4, 5, 6, 1]; 37 38 out = [0, 0, 0, 0, 39 0, 0, 0, 0, 40 0, 0, 0, 0, 41 0, 0, 0, 0]; 42 43 identity = [1, 0, 0, 0, 44 0, 1, 0, 0, 45 0, 0, 1, 0, 46 0, 0, 0, 1]; 47 }); 48 49 describe("create", function() { 50 beforeEach(function() { result = mat4.create(); }); 51 it("should return a 16 element array initialized to a 4x4 identity matrix", function() { expect(result).toBeEqualish(identity); }); 52 }); 53 54 describe("clone", function() { 55 beforeEach(function() { result = mat4.clone(matA); }); 56 it("should return a 16 element array initialized to the values in matA", function() { expect(result).toBeEqualish(matA); }); 57 }); 58 59 describe("copy", function() { 60 beforeEach(function() { result = mat4.copy(out, matA); }); 61 it("should place values into out", function() { expect(out).toBeEqualish(matA); }); 62 it("should return out", function() { expect(result).toBe(out); }); 63 }); 64 65 describe("identity", function() { 66 beforeEach(function() { result = mat4.identity(out); }); 67 it("should place values into out", function() { expect(result).toBeEqualish(identity); }); 68 it("should return out", function() { expect(result).toBe(out); }); 69 }); 70 71 describe("transpose", function() { 72 describe("with a separate output matrix", function() { 73 beforeEach(function() { result = mat4.transpose(out, matA); }); 74 75 it("should place values into out", function() { 76 expect(out).toBeEqualish([ 77 1, 0, 0, 1, 78 0, 1, 0, 2, 79 0, 0, 1, 3, 80 0, 0, 0, 1 81 ]); 82 }); 83 it("should return out", function() { expect(result).toBe(out); }); 84 it("should not modify matA", function() { 85 expect(matA).toBeEqualish([ 86 1, 0, 0, 0, 87 0, 1, 0, 0, 88 0, 0, 1, 0, 89 1, 2, 3, 1 90 ]); 91 }); 92 }); 93 94 describe("when matA is the output matrix", function() { 95 beforeEach(function() { result = mat4.transpose(matA, matA); }); 96 97 it("should place values into matA", function() { 98 expect(matA).toBeEqualish([ 99 1, 0, 0, 1, 100 0, 1, 0, 2, 101 0, 0, 1, 3, 102 0, 0, 0, 1 103 ]); 104 }); 105 it("should return matA", function() { expect(result).toBe(matA); }); 106 }); 107 }); 108 109 describe("invert", function() { 110 describe("with a separate output matrix", function() { 111 beforeEach(function() { result = mat4.invert(out, matA); }); 112 113 it("should place values into out", function() { 114 expect(out).toBeEqualish([ 115 1, 0, 0, 0, 116 0, 1, 0, 0, 117 0, 0, 1, 0, 118 -1, -2, -3, 1 119 ]); 120 }); 121 it("should return out", function() { expect(result).toBe(out); }); 122 it("should not modify matA", function() { 123 expect(matA).toBeEqualish([ 124 1, 0, 0, 0, 125 0, 1, 0, 0, 126 0, 0, 1, 0, 127 1, 2, 3, 1 128 ]); 129 }); 130 }); 131 132 describe("when matA is the output matrix", function() { 133 beforeEach(function() { result = mat4.invert(matA, matA); }); 134 135 it("should place values into matA", function() { 136 expect(matA).toBeEqualish([ 137 1, 0, 0, 0, 138 0, 1, 0, 0, 139 0, 0, 1, 0, 140 -1, -2, -3, 1 141 ]); 142 }); 143 it("should return matA", function() { expect(result).toBe(matA); }); 144 }); 145 }); 146 147 describe("adjoint", function() { 148 describe("with a separate output matrix", function() { 149 beforeEach(function() { result = mat4.adjoint(out, matA); }); 150 151 it("should place values into out", function() { 152 expect(out).toBeEqualish([ 153 1, 0, 0, 0, 154 0, 1, 0, 0, 155 0, 0, 1, 0, 156 -1, -2, -3, 1 157 ]); 158 }); 159 it("should return out", function() { expect(result).toBe(out); }); 160 it("should not modify matA", function() { 161 expect(matA).toBeEqualish([ 162 1, 0, 0, 0, 163 0, 1, 0, 0, 164 0, 0, 1, 0, 165 1, 2, 3, 1 166 ]); 167 }); 168 }); 169 170 describe("when matA is the output matrix", function() { 171 beforeEach(function() { result = mat4.adjoint(matA, matA); }); 172 173 it("should place values into matA", function() { 174 expect(matA).toBeEqualish([ 175 1, 0, 0, 0, 176 0, 1, 0, 0, 177 0, 0, 1, 0, 178 -1, -2, -3, 1 179 ]); 180 }); 181 it("should return matA", function() { expect(result).toBe(matA); }); 182 }); 183 }); 184 185 describe("determinant", function() { 186 beforeEach(function() { result = mat4.determinant(matA); }); 187 188 it("should return the determinant", function() { expect(result).toEqual(1); }); 189 }); 190 191 describe("multiply", function() { 192 it("should have an alias called 'mul'", function() { expect(mat4.mul).toEqual(mat4.multiply); }); 193 194 describe("with a separate output matrix", function() { 195 beforeEach(function() { result = mat4.multiply(out, matA, matB); }); 196 197 it("should place values into out", function() { 198 expect(out).toBeEqualish([ 199 1, 0, 0, 0, 200 0, 1, 0, 0, 201 0, 0, 1, 0, 202 5, 7, 9, 1 203 ]); 204 }); 205 it("should return out", function() { expect(result).toBe(out); }); 206 it("should not modify matA", function() { 207 expect(matA).toBeEqualish([ 208 1, 0, 0, 0, 209 0, 1, 0, 0, 210 0, 0, 1, 0, 211 1, 2, 3, 1 212 ]); 213 }); 214 it("should not modify matB", function() { 215 expect(matB).toBeEqualish([ 216 1, 0, 0, 0, 217 0, 1, 0, 0, 218 0, 0, 1, 0, 219 4, 5, 6, 1 220 ]); 221 }); 222 }); 223 224 describe("when matA is the output matrix", function() { 225 beforeEach(function() { result = mat4.multiply(matA, matA, matB); }); 226 227 it("should place values into matA", function() { 228 expect(matA).toBeEqualish([ 229 1, 0, 0, 0, 230 0, 1, 0, 0, 231 0, 0, 1, 0, 232 5, 7, 9, 1 233 ]); 234 }); 235 it("should return matA", function() { expect(result).toBe(matA); }); 236 it("should not modify matB", function() { 237 expect(matB).toBeEqualish([ 238 1, 0, 0, 0, 239 0, 1, 0, 0, 240 0, 0, 1, 0, 241 4, 5, 6, 1 242 ]); 243 }); 244 }); 245 246 describe("when matB is the output matrix", function() { 247 beforeEach(function() { result = mat4.multiply(matB, matA, matB); }); 248 249 it("should place values into matB", function() { 250 expect(matB).toBeEqualish([ 251 1, 0, 0, 0, 252 0, 1, 0, 0, 253 0, 0, 1, 0, 254 5, 7, 9, 1 255 ]); 256 }); 257 it("should return matB", function() { expect(result).toBe(matB); }); 258 it("should not modify matA", function() { 259 expect(matA).toBeEqualish([ 260 1, 0, 0, 0, 261 0, 1, 0, 0, 262 0, 0, 1, 0, 263 1, 2, 3, 1 264 ]); 265 }); 266 }); 267 }); 268 269 describe("translate", function() { 270 describe("with a separate output matrix", function() { 271 beforeEach(function() { result = mat4.translate(out, matA, [4, 5, 6]); }); 272 273 it("should place values into out", function() { 274 expect(out).toBeEqualish([ 275 1, 0, 0, 0, 276 0, 1, 0, 0, 277 0, 0, 1, 0, 278 5, 7, 9, 1 279 ]); 280 }); 281 it("should return out", function() { expect(result).toBe(out); }); 282 it("should not modify matA", function() { 283 expect(matA).toBeEqualish([ 284 1, 0, 0, 0, 285 0, 1, 0, 0, 286 0, 0, 1, 0, 287 1, 2, 3, 1 288 ]); 289 }); 290 }); 291 292 describe("when matA is the output matrix", function() { 293 beforeEach(function() { result = mat4.translate(matA, matA, [4, 5, 6]); }); 294 295 it("should place values into matA", function() { 296 expect(matA).toBeEqualish([ 297 1, 0, 0, 0, 298 0, 1, 0, 0, 299 0, 0, 1, 0, 300 5, 7, 9, 1 301 ]); 302 }); 303 it("should return matA", function() { expect(result).toBe(matA); }); 304 }); 305 }); 306 307 describe("scale", function() { 308 describe("with a separate output matrix", function() { 309 beforeEach(function() { result = mat4.scale(out, matA, [4, 5, 6]); }); 310 311 it("should place values into out", function() { 312 expect(out).toBeEqualish([ 313 4, 0, 0, 0, 314 0, 5, 0, 0, 315 0, 0, 6, 0, 316 1, 2, 3, 1 317 ]); 318 }); 319 it("should return out", function() { expect(result).toBe(out); }); 320 it("should not modify matA", function() { 321 expect(matA).toBeEqualish([ 322 1, 0, 0, 0, 323 0, 1, 0, 0, 324 0, 0, 1, 0, 325 1, 2, 3, 1 326 ]); 327 }); 328 }); 329 330 describe("when matA is the output matrix", function() { 331 beforeEach(function() { result = mat4.scale(matA, matA, [4, 5, 6]); }); 332 333 it("should place values into matA", function() { 334 expect(matA).toBeEqualish([ 335 4, 0, 0, 0, 336 0, 5, 0, 0, 337 0, 0, 6, 0, 338 1, 2, 3, 1 339 ]); 340 }); 341 it("should return matA", function() { expect(result).toBe(matA); }); 342 }); 343 }); 344 345 describe("rotate", function() { 346 var rad = Math.PI * 0.5; 347 var axis = [1, 0, 0]; 348 349 describe("with a separate output matrix", function() { 350 beforeEach(function() { result = mat4.rotate(out, matA, rad, axis); }); 351 352 it("should place values into out", function() { 353 expect(out).toBeEqualish([ 354 1, 0, 0, 0, 355 0, Math.cos(rad), Math.sin(rad), 0, 356 0, -Math.sin(rad), Math.cos(rad), 0, 357 1, 2, 3, 1 358 ]); 359 }); 360 it("should return out", function() { expect(result).toBe(out); }); 361 it("should not modify matA", function() { 362 expect(matA).toBeEqualish([ 363 1, 0, 0, 0, 364 0, 1, 0, 0, 365 0, 0, 1, 0, 366 1, 2, 3, 1 367 ]); 368 }); 369 }); 370 371 describe("when matA is the output matrix", function() { 372 beforeEach(function() { result = mat4.rotate(matA, matA, rad, axis); }); 373 374 it("should place values into matA", function() { 375 expect(matA).toBeEqualish([ 376 1, 0, 0, 0, 377 0, Math.cos(rad), Math.sin(rad), 0, 378 0, -Math.sin(rad), Math.cos(rad), 0, 379 1, 2, 3, 1 380 ]); 381 }); 382 it("should return matA", function() { expect(result).toBe(matA); }); 383 }); 384 }); 385 386 describe("rotateX", function() { 387 var rad = Math.PI * 0.5; 388 389 describe("with a separate output matrix", function() { 390 beforeEach(function() { result = mat4.rotateX(out, matA, rad); }); 391 392 it("should place values into out", function() { 393 expect(out).toBeEqualish([ 394 1, 0, 0, 0, 395 0, Math.cos(rad), Math.sin(rad), 0, 396 0, -Math.sin(rad), Math.cos(rad), 0, 397 1, 2, 3, 1 398 ]); 399 }); 400 it("should return out", function() { expect(result).toBe(out); }); 401 it("should not modify matA", function() { 402 expect(matA).toBeEqualish([ 403 1, 0, 0, 0, 404 0, 1, 0, 0, 405 0, 0, 1, 0, 406 1, 2, 3, 1 407 ]); 408 }); 409 }); 410 411 describe("when matA is the output matrix", function() { 412 beforeEach(function() { result = mat4.rotateX(matA, matA, rad); }); 413 414 it("should place values into matA", function() { 415 expect(matA).toBeEqualish([ 416 1, 0, 0, 0, 417 0, Math.cos(rad), Math.sin(rad), 0, 418 0, -Math.sin(rad), Math.cos(rad), 0, 419 1, 2, 3, 1 420 ]); 421 }); 422 it("should return matA", function() { expect(result).toBe(matA); }); 423 }); 424 }); 425 426 describe("rotateY", function() { 427 var rad = Math.PI * 0.5; 428 429 describe("with a separate output matrix", function() { 430 beforeEach(function() { result = mat4.rotateY(out, matA, rad); }); 431 432 it("should place values into out", function() { 433 expect(out).toBeEqualish([ 434 Math.cos(rad), 0, -Math.sin(rad), 0, 435 0, 1, 0, 0, 436 Math.sin(rad), 0, Math.cos(rad), 0, 437 1, 2, 3, 1 438 ]); 439 }); 440 it("should return out", function() { expect(result).toBe(out); }); 441 it("should not modify matA", function() { 442 expect(matA).toBeEqualish([ 443 1, 0, 0, 0, 444 0, 1, 0, 0, 445 0, 0, 1, 0, 446 1, 2, 3, 1 447 ]); 448 }); 449 }); 450 451 describe("when matA is the output matrix", function() { 452 beforeEach(function() { result = mat4.rotateY(matA, matA, rad); }); 453 454 it("should place values into matA", function() { 455 expect(matA).toBeEqualish([ 456 Math.cos(rad), 0, -Math.sin(rad), 0, 457 0, 1, 0, 0, 458 Math.sin(rad), 0, Math.cos(rad), 0, 459 1, 2, 3, 1 460 ]); 461 }); 462 it("should return matA", function() { expect(result).toBe(matA); }); 463 }); 464 }); 465 466 describe("rotateZ", function() { 467 var rad = Math.PI * 0.5; 468 469 describe("with a separate output matrix", function() { 470 beforeEach(function() { result = mat4.rotateZ(out, matA, rad); }); 471 472 it("should place values into out", function() { 473 expect(out).toBeEqualish([ 474 Math.cos(rad), Math.sin(rad), 0, 0, 475 -Math.sin(rad), Math.cos(rad), 0, 0, 476 0, 0, 1, 0, 477 1, 2, 3, 1 478 ]); 479 }); 480 it("should return out", function() { expect(result).toBe(out); }); 481 it("should not modify matA", function() { 482 expect(matA).toBeEqualish([ 483 1, 0, 0, 0, 484 0, 1, 0, 0, 485 0, 0, 1, 0, 486 1, 2, 3, 1 487 ]); 488 }); 489 }); 490 491 describe("when matA is the output matrix", function() { 492 beforeEach(function() { result = mat4.rotateZ(matA, matA, rad); }); 493 494 it("should place values into matA", function() { 495 expect(matA).toBeEqualish([ 496 Math.cos(rad), Math.sin(rad), 0, 0, 497 -Math.sin(rad), Math.cos(rad), 0, 0, 498 0, 0, 1, 0, 499 1, 2, 3, 1 500 ]); 501 }); 502 it("should return matA", function() { expect(result).toBe(matA); }); 503 }); 504 }); 505 506 // TODO: fromRotationTranslation 507 508 describe("frustum", function() { 509 beforeEach(function() { result = mat4.frustum(out, -1, 1, -1, 1, -1, 1); }); 510 it("should place values into out", function() { expect(result).toBeEqualish([ 511 -1, 0, 0, 0, 512 0, -1, 0, 0, 513 0, 0, 0, -1, 514 0, 0, 1, 0 515 ]); 516 }); 517 it("should return out", function() { expect(result).toBe(out); }); 518 }); 519 520 describe("perspective", function() { 521 var fovy = Math.PI * 0.5; 522 beforeEach(function() { result = mat4.perspective(out, fovy, 1, 0, 1); }); 523 it("should place values into out", function() { expect(result).toBeEqualish([ 524 1, 0, 0, 0, 525 0, 1, 0, 0, 526 0, 0, -1, -1, 527 0, 0, 0, 0 528 ]); 529 }); 530 it("should return out", function() { expect(result).toBe(out); }); 531 }); 532 533 describe("ortho", function() { 534 beforeEach(function() { result = mat4.ortho(out, -1, 1, -1, 1, -1, 1); }); 535 it("should place values into out", function() { expect(result).toBeEqualish([ 536 1, 0, 0, 0, 537 0, 1, 0, 0, 538 0, 0, -1, 0, 539 0, 0, 0, 1 540 ]); 541 }); 542 it("should return out", function() { expect(result).toBe(out); }); 543 }); 544 545 describe("lookAt", function() { 546 var eye = [0, 0, 1]; 547 var center = [0, 0, -1]; 548 var up = [0, 1, 0]; 549 550 beforeEach(function() { result = mat4.lookAt(out, eye, center, up); }); 551 it("should place values into out", function() { expect(result).toBeEqualish([ 552 1, 0, 0, 0, 553 0, 1, 0, 0, 554 0, 0, 1, 0, 555 0, 0, -1, 1 556 ]); 557 }); 558 it("should return out", function() { expect(result).toBe(out); }); 559 }); 560 561 describe("str", function() { 562 beforeEach(function() { result = mat4.str(matA); }); 563 564 it("should return a string representation of the matrix", function() { expect(result).toEqual("mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1)"); }); 565 }); 566 });