1/* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 2 3Permission is hereby granted, free of charge, to any person obtaining a copy 4of this software and associated documentation files (the "Software"), to deal 5in the Software without restriction, including without limitation the rights 6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7copies of the Software, and to permit persons to whom the Software is 8furnished to do so, subject to the following conditions: 9 10The above copyright notice and this permission notice shall be included in 11all copies or substantial portions of the Software. 12 13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19THE SOFTWARE. */ 20 21var glMatrix = require("./common.js"); 22 23/** 24 * @class 3 Dimensional Vector 25 * @name vec3 26 */ 27var vec3 = {}; 28 29/** 30 * Creates a new, empty vec3 31 * 32 * @returns {vec3} a new 3D vector 33 */ 34vec3.create = function() { 35 var out = new glMatrix.ARRAY_TYPE(3); 36 out[0] = 0; 37 out[1] = 0; 38 out[2] = 0; 39 return out; 40}; 41 42/** 43 * Creates a new vec3 initialized with values from an existing vector 44 * 45 * @param {vec3} a vector to clone 46 * @returns {vec3} a new 3D vector 47 */ 48vec3.clone = function(a) { 49 var out = new glMatrix.ARRAY_TYPE(3); 50 out[0] = a[0]; 51 out[1] = a[1]; 52 out[2] = a[2]; 53 return out; 54}; 55 56/** 57 * Creates a new vec3 initialized with the given values 58 * 59 * @param {Number} x X component 60 * @param {Number} y Y component 61 * @param {Number} z Z component 62 * @returns {vec3} a new 3D vector 63 */ 64vec3.fromValues = function(x, y, z) { 65 var out = new glMatrix.ARRAY_TYPE(3); 66 out[0] = x; 67 out[1] = y; 68 out[2] = z; 69 return out; 70}; 71 72/** 73 * Copy the values from one vec3 to another 74 * 75 * @param {vec3} out the receiving vector 76 * @param {vec3} a the source vector 77 * @returns {vec3} out 78 */ 79vec3.copy = function(out, a) { 80 out[0] = a[0]; 81 out[1] = a[1]; 82 out[2] = a[2]; 83 return out; 84}; 85 86/** 87 * Set the components of a vec3 to the given values 88 * 89 * @param {vec3} out the receiving vector 90 * @param {Number} x X component 91 * @param {Number} y Y component 92 * @param {Number} z Z component 93 * @returns {vec3} out 94 */ 95vec3.set = function(out, x, y, z) { 96 out[0] = x; 97 out[1] = y; 98 out[2] = z; 99 return out; 100}; 101 102/** 103 * Adds two vec3's 104 * 105 * @param {vec3} out the receiving vector 106 * @param {vec3} a the first operand 107 * @param {vec3} b the second operand 108 * @returns {vec3} out 109 */ 110vec3.add = function(out, a, b) { 111 out[0] = a[0] + b[0]; 112 out[1] = a[1] + b[1]; 113 out[2] = a[2] + b[2]; 114 return out; 115}; 116 117/** 118 * Subtracts vector b from vector a 119 * 120 * @param {vec3} out the receiving vector 121 * @param {vec3} a the first operand 122 * @param {vec3} b the second operand 123 * @returns {vec3} out 124 */ 125vec3.subtract = function(out, a, b) { 126 out[0] = a[0] - b[0]; 127 out[1] = a[1] - b[1]; 128 out[2] = a[2] - b[2]; 129 return out; 130}; 131 132/** 133 * Alias for {@link vec3.subtract} 134 * @function 135 */ 136vec3.sub = vec3.subtract; 137 138/** 139 * Multiplies two vec3's 140 * 141 * @param {vec3} out the receiving vector 142 * @param {vec3} a the first operand 143 * @param {vec3} b the second operand 144 * @returns {vec3} out 145 */ 146vec3.multiply = function(out, a, b) { 147 out[0] = a[0] * b[0]; 148 out[1] = a[1] * b[1]; 149 out[2] = a[2] * b[2]; 150 return out; 151}; 152 153/** 154 * Alias for {@link vec3.multiply} 155 * @function 156 */ 157vec3.mul = vec3.multiply; 158 159/** 160 * Divides two vec3's 161 * 162 * @param {vec3} out the receiving vector 163 * @param {vec3} a the first operand 164 * @param {vec3} b the second operand 165 * @returns {vec3} out 166 */ 167vec3.divide = function(out, a, b) { 168 out[0] = a[0] / b[0]; 169 out[1] = a[1] / b[1]; 170 out[2] = a[2] / b[2]; 171 return out; 172}; 173 174/** 175 * Alias for {@link vec3.divide} 176 * @function 177 */ 178vec3.div = vec3.divide; 179 180/** 181 * Returns the minimum of two vec3's 182 * 183 * @param {vec3} out the receiving vector 184 * @param {vec3} a the first operand 185 * @param {vec3} b the second operand 186 * @returns {vec3} out 187 */ 188vec3.min = function(out, a, b) { 189 out[0] = Math.min(a[0], b[0]); 190 out[1] = Math.min(a[1], b[1]); 191 out[2] = Math.min(a[2], b[2]); 192 return out; 193}; 194 195/** 196 * Returns the maximum of two vec3's 197 * 198 * @param {vec3} out the receiving vector 199 * @param {vec3} a the first operand 200 * @param {vec3} b the second operand 201 * @returns {vec3} out 202 */ 203vec3.max = function(out, a, b) { 204 out[0] = Math.max(a[0], b[0]); 205 out[1] = Math.max(a[1], b[1]); 206 out[2] = Math.max(a[2], b[2]); 207 return out; 208}; 209 210/** 211 * Scales a vec3 by a scalar number 212 * 213 * @param {vec3} out the receiving vector 214 * @param {vec3} a the vector to scale 215 * @param {Number} b amount to scale the vector by 216 * @returns {vec3} out 217 */ 218vec3.scale = function(out, a, b) { 219 out[0] = a[0] * b; 220 out[1] = a[1] * b; 221 out[2] = a[2] * b; 222 return out; 223}; 224 225/** 226 * Adds two vec3's after scaling the second operand by a scalar value 227 * 228 * @param {vec3} out the receiving vector 229 * @param {vec3} a the first operand 230 * @param {vec3} b the second operand 231 * @param {Number} scale the amount to scale b by before adding 232 * @returns {vec3} out 233 */ 234vec3.scaleAndAdd = function(out, a, b, scale) { 235 out[0] = a[0] + (b[0] * scale); 236 out[1] = a[1] + (b[1] * scale); 237 out[2] = a[2] + (b[2] * scale); 238 return out; 239}; 240 241/** 242 * Calculates the euclidian distance between two vec3's 243 * 244 * @param {vec3} a the first operand 245 * @param {vec3} b the second operand 246 * @returns {Number} distance between a and b 247 */ 248vec3.distance = function(a, b) { 249 var x = b[0] - a[0], 250 y = b[1] - a[1], 251 z = b[2] - a[2]; 252 return Math.sqrt(x*x + y*y + z*z); 253}; 254 255/** 256 * Alias for {@link vec3.distance} 257 * @function 258 */ 259vec3.dist = vec3.distance; 260 261/** 262 * Calculates the squared euclidian distance between two vec3's 263 * 264 * @param {vec3} a the first operand 265 * @param {vec3} b the second operand 266 * @returns {Number} squared distance between a and b 267 */ 268vec3.squaredDistance = function(a, b) { 269 var x = b[0] - a[0], 270 y = b[1] - a[1], 271 z = b[2] - a[2]; 272 return x*x + y*y + z*z; 273}; 274 275/** 276 * Alias for {@link vec3.squaredDistance} 277 * @function 278 */ 279vec3.sqrDist = vec3.squaredDistance; 280 281/** 282 * Calculates the length of a vec3 283 * 284 * @param {vec3} a vector to calculate length of 285 * @returns {Number} length of a 286 */ 287vec3.length = function (a) { 288 var x = a[0], 289 y = a[1], 290 z = a[2]; 291 return Math.sqrt(x*x + y*y + z*z); 292}; 293 294/** 295 * Alias for {@link vec3.length} 296 * @function 297 */ 298vec3.len = vec3.length; 299 300/** 301 * Calculates the squared length of a vec3 302 * 303 * @param {vec3} a vector to calculate squared length of 304 * @returns {Number} squared length of a 305 */ 306vec3.squaredLength = function (a) { 307 var x = a[0], 308 y = a[1], 309 z = a[2]; 310 return x*x + y*y + z*z; 311}; 312 313/** 314 * Alias for {@link vec3.squaredLength} 315 * @function 316 */ 317vec3.sqrLen = vec3.squaredLength; 318 319/** 320 * Negates the components of a vec3 321 * 322 * @param {vec3} out the receiving vector 323 * @param {vec3} a vector to negate 324 * @returns {vec3} out 325 */ 326vec3.negate = function(out, a) { 327 out[0] = -a[0]; 328 out[1] = -a[1]; 329 out[2] = -a[2]; 330 return out; 331}; 332 333/** 334 * Returns the inverse of the components of a vec3 335 * 336 * @param {vec3} out the receiving vector 337 * @param {vec3} a vector to invert 338 * @returns {vec3} out 339 */ 340vec3.inverse = function(out, a) { 341 out[0] = 1.0 / a[0]; 342 out[1] = 1.0 / a[1]; 343 out[2] = 1.0 / a[2]; 344 return out; 345}; 346 347/** 348 * Normalize a vec3 349 * 350 * @param {vec3} out the receiving vector 351 * @param {vec3} a vector to normalize 352 * @returns {vec3} out 353 */ 354vec3.normalize = function(out, a) { 355 var x = a[0], 356 y = a[1], 357 z = a[2]; 358 var len = x*x + y*y + z*z; 359 if (len > 0) { 360 //TODO: evaluate use of glm_invsqrt here? 361 len = 1 / Math.sqrt(len); 362 out[0] = a[0] * len; 363 out[1] = a[1] * len; 364 out[2] = a[2] * len; 365 } 366 return out; 367}; 368 369/** 370 * Calculates the dot product of two vec3's 371 * 372 * @param {vec3} a the first operand 373 * @param {vec3} b the second operand 374 * @returns {Number} dot product of a and b 375 */ 376vec3.dot = function (a, b) { 377 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 378}; 379 380/** 381 * Computes the cross product of two vec3's 382 * 383 * @param {vec3} out the receiving vector 384 * @param {vec3} a the first operand 385 * @param {vec3} b the second operand 386 * @returns {vec3} out 387 */ 388vec3.cross = function(out, a, b) { 389 var ax = a[0], ay = a[1], az = a[2], 390 bx = b[0], by = b[1], bz = b[2]; 391 392 out[0] = ay * bz - az * by; 393 out[1] = az * bx - ax * bz; 394 out[2] = ax * by - ay * bx; 395 return out; 396}; 397 398/** 399 * Performs a linear interpolation between two vec3's 400 * 401 * @param {vec3} out the receiving vector 402 * @param {vec3} a the first operand 403 * @param {vec3} b the second operand 404 * @param {Number} t interpolation amount between the two inputs 405 * @returns {vec3} out 406 */ 407vec3.lerp = function (out, a, b, t) { 408 var ax = a[0], 409 ay = a[1], 410 az = a[2]; 411 out[0] = ax + t * (b[0] - ax); 412 out[1] = ay + t * (b[1] - ay); 413 out[2] = az + t * (b[2] - az); 414 return out; 415}; 416 417/** 418 * Performs a hermite interpolation with two control points 419 * 420 * @param {vec3} out the receiving vector 421 * @param {vec3} a the first operand 422 * @param {vec3} b the second operand 423 * @param {vec3} c the third operand 424 * @param {vec3} d the fourth operand 425 * @param {Number} t interpolation amount between the two inputs 426 * @returns {vec3} out 427 */ 428vec3.hermite = function (out, a, b, c, d, t) { 429 var factorTimes2 = t * t, 430 factor1 = factorTimes2 * (2 * t - 3) + 1, 431 factor2 = factorTimes2 * (t - 2) + t, 432 factor3 = factorTimes2 * (t - 1), 433 factor4 = factorTimes2 * (3 - 2 * t); 434 435 out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4; 436 out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4; 437 out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4; 438 439 return out; 440}; 441 442/** 443 * Performs a bezier interpolation with two control points 444 * 445 * @param {vec3} out the receiving vector 446 * @param {vec3} a the first operand 447 * @param {vec3} b the second operand 448 * @param {vec3} c the third operand 449 * @param {vec3} d the fourth operand 450 * @param {Number} t interpolation amount between the two inputs 451 * @returns {vec3} out 452 */ 453vec3.bezier = function (out, a, b, c, d, t) { 454 var inverseFactor = 1 - t, 455 inverseFactorTimesTwo = inverseFactor * inverseFactor, 456 factorTimes2 = t * t, 457 factor1 = inverseFactorTimesTwo * inverseFactor, 458 factor2 = 3 * t * inverseFactorTimesTwo, 459 factor3 = 3 * factorTimes2 * inverseFactor, 460 factor4 = factorTimes2 * t; 461 462 out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4; 463 out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4; 464 out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4; 465 466 return out; 467}; 468 469/** 470 * Generates a random vector with the given scale 471 * 472 * @param {vec3} out the receiving vector 473 * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned 474 * @returns {vec3} out 475 */ 476vec3.random = function (out, scale) { 477 scale = scale || 1.0; 478 479 var r = glMatrix.RANDOM() * 2.0 * Math.PI; 480 var z = (glMatrix.RANDOM() * 2.0) - 1.0; 481 var zScale = Math.sqrt(1.0-z*z) * scale; 482 483 out[0] = Math.cos(r) * zScale; 484 out[1] = Math.sin(r) * zScale; 485 out[2] = z * scale; 486 return out; 487}; 488 489/** 490 * Transforms the vec3 with a mat4. 491 * 4th vector component is implicitly '1' 492 * 493 * @param {vec3} out the receiving vector 494 * @param {vec3} a the vector to transform 495 * @param {mat4} m matrix to transform with 496 * @returns {vec3} out 497 */ 498vec3.transformMat4 = function(out, a, m) { 499 var x = a[0], y = a[1], z = a[2], 500 w = m[3] * x + m[7] * y + m[11] * z + m[15]; 501 w = w || 1.0; 502 out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w; 503 out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w; 504 out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w; 505 return out; 506}; 507 508/** 509 * Transforms the vec3 with a mat3. 510 * 511 * @param {vec3} out the receiving vector 512 * @param {vec3} a the vector to transform 513 * @param {mat4} m the 3x3 matrix to transform with 514 * @returns {vec3} out 515 */ 516vec3.transformMat3 = function(out, a, m) { 517 var x = a[0], y = a[1], z = a[2]; 518 out[0] = x * m[0] + y * m[3] + z * m[6]; 519 out[1] = x * m[1] + y * m[4] + z * m[7]; 520 out[2] = x * m[2] + y * m[5] + z * m[8]; 521 return out; 522}; 523 524/** 525 * Transforms the vec3 with a quat 526 * 527 * @param {vec3} out the receiving vector 528 * @param {vec3} a the vector to transform 529 * @param {quat} q quaternion to transform with 530 * @returns {vec3} out 531 */ 532vec3.transformQuat = function(out, a, q) { 533 // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations 534 535 var x = a[0], y = a[1], z = a[2], 536 qx = q[0], qy = q[1], qz = q[2], qw = q[3], 537 538 // calculate quat * vec 539 ix = qw * x + qy * z - qz * y, 540 iy = qw * y + qz * x - qx * z, 541 iz = qw * z + qx * y - qy * x, 542 iw = -qx * x - qy * y - qz * z; 543 544 // calculate result * inverse quat 545 out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 546 out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 547 out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 548 return out; 549}; 550 551/** 552 * Rotate a 3D vector around the x-axis 553 * @param {vec3} out The receiving vec3 554 * @param {vec3} a The vec3 point to rotate 555 * @param {vec3} b The origin of the rotation 556 * @param {Number} c The angle of rotation 557 * @returns {vec3} out 558 */ 559vec3.rotateX = function(out, a, b, c){ 560 var p = [], r=[]; 561 //Translate point to the origin 562 p[0] = a[0] - b[0]; 563 p[1] = a[1] - b[1]; 564 p[2] = a[2] - b[2]; 565 566 //perform rotation 567 r[0] = p[0]; 568 r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c); 569 r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c); 570 571 //translate to correct position 572 out[0] = r[0] + b[0]; 573 out[1] = r[1] + b[1]; 574 out[2] = r[2] + b[2]; 575 576 return out; 577}; 578 579/** 580 * Rotate a 3D vector around the y-axis 581 * @param {vec3} out The receiving vec3 582 * @param {vec3} a The vec3 point to rotate 583 * @param {vec3} b The origin of the rotation 584 * @param {Number} c The angle of rotation 585 * @returns {vec3} out 586 */ 587vec3.rotateY = function(out, a, b, c){ 588 var p = [], r=[]; 589 //Translate point to the origin 590 p[0] = a[0] - b[0]; 591 p[1] = a[1] - b[1]; 592 p[2] = a[2] - b[2]; 593 594 //perform rotation 595 r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c); 596 r[1] = p[1]; 597 r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c); 598 599 //translate to correct position 600 out[0] = r[0] + b[0]; 601 out[1] = r[1] + b[1]; 602 out[2] = r[2] + b[2]; 603 604 return out; 605}; 606 607/** 608 * Rotate a 3D vector around the z-axis 609 * @param {vec3} out The receiving vec3 610 * @param {vec3} a The vec3 point to rotate 611 * @param {vec3} b The origin of the rotation 612 * @param {Number} c The angle of rotation 613 * @returns {vec3} out 614 */ 615vec3.rotateZ = function(out, a, b, c){ 616 var p = [], r=[]; 617 //Translate point to the origin 618 p[0] = a[0] - b[0]; 619 p[1] = a[1] - b[1]; 620 p[2] = a[2] - b[2]; 621 622 //perform rotation 623 r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c); 624 r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c); 625 r[2] = p[2]; 626 627 //translate to correct position 628 out[0] = r[0] + b[0]; 629 out[1] = r[1] + b[1]; 630 out[2] = r[2] + b[2]; 631 632 return out; 633}; 634 635/** 636 * Perform some operation over an array of vec3s. 637 * 638 * @param {Array} a the array of vectors to iterate over 639 * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed 640 * @param {Number} offset Number of elements to skip at the beginning of the array 641 * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array 642 * @param {Function} fn Function to call for each vector in the array 643 * @param {Object} [arg] additional argument to pass to fn 644 * @returns {Array} a 645 * @function 646 */ 647vec3.forEach = (function() { 648 var vec = vec3.create(); 649 650 return function(a, stride, offset, count, fn, arg) { 651 var i, l; 652 if(!stride) { 653 stride = 3; 654 } 655 656 if(!offset) { 657 offset = 0; 658 } 659 660 if(count) { 661 l = Math.min((count * stride) + offset, a.length); 662 } else { 663 l = a.length; 664 } 665 666 for(i = offset; i < l; i += stride) { 667 vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; 668 fn(vec, vec, arg); 669 a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; 670 } 671 672 return a; 673 }; 674})(); 675 676/** 677 * Get the angle between two 3D vectors 678 * @param {vec3} a The first operand 679 * @param {vec3} b The second operand 680 * @returns {Number} The angle in radians 681 */ 682vec3.angle = function(a, b) { 683 684 var tempA = vec3.fromValues(a[0], a[1], a[2]); 685 var tempB = vec3.fromValues(b[0], b[1], b[2]); 686 687 vec3.normalize(tempA, tempA); 688 vec3.normalize(tempB, tempB); 689 690 var cosine = vec3.dot(tempA, tempB); 691 692 if(cosine > 1.0){ 693 return 0; 694 } else { 695 return Math.acos(cosine); 696 } 697}; 698 699/** 700 * Returns a string representation of a vector 701 * 702 * @param {vec3} vec vector to represent as a string 703 * @returns {String} string representation of the vector 704 */ 705vec3.str = function (a) { 706 return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; 707}; 708 709module.exports = vec3; 710