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 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 GLMAT_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 GLMAT_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 GLMAT_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 two vec3's 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 * Calculates the euclidian distance between two vec3's 227 * 228 * @param {vec3} a the first operand 229 * @param {vec3} b the second operand 230 * @returns {Number} distance between a and b 231 */ 232vec3.distance = function(a, b) { 233 var x = b[0] - a[0], 234 y = b[1] - a[1], 235 z = b[2] - a[2]; 236 return Math.sqrt(x*x + y*y + z*z); 237}; 238 239/** 240 * Alias for {@link vec3.distance} 241 * @function 242 */ 243vec3.dist = vec3.distance; 244 245/** 246 * Calculates the squared euclidian distance between two vec3's 247 * 248 * @param {vec3} a the first operand 249 * @param {vec3} b the second operand 250 * @returns {Number} squared distance between a and b 251 */ 252vec3.squaredDistance = function(a, b) { 253 var x = b[0] - a[0], 254 y = b[1] - a[1], 255 z = b[2] - a[2]; 256 return x*x + y*y + z*z; 257}; 258 259/** 260 * Alias for {@link vec3.squaredDistance} 261 * @function 262 */ 263vec3.sqrDist = vec3.squaredDistance; 264 265/** 266 * Calculates the length of a vec3 267 * 268 * @param {vec3} a vector to calculate length of 269 * @returns {Number} length of a 270 */ 271vec3.length = function (a) { 272 var x = a[0], 273 y = a[1], 274 z = a[2]; 275 return Math.sqrt(x*x + y*y + z*z); 276}; 277 278/** 279 * Alias for {@link vec3.length} 280 * @function 281 */ 282vec3.len = vec3.length; 283 284/** 285 * Calculates the squared length of a vec3 286 * 287 * @param {vec3} a vector to calculate squared length of 288 * @returns {Number} squared length of a 289 */ 290vec3.squaredLength = function (a) { 291 var x = a[0], 292 y = a[1], 293 z = a[2]; 294 return x*x + y*y + z*z; 295}; 296 297/** 298 * Alias for {@link vec3.squaredLength} 299 * @function 300 */ 301vec3.sqrLen = vec3.squaredLength; 302 303/** 304 * Negates the components of a vec3 305 * 306 * @param {vec3} out the receiving vector 307 * @param {vec3} a vector to negate 308 * @returns {vec3} out 309 */ 310vec3.negate = function(out, a) { 311 out[0] = -a[0]; 312 out[1] = -a[1]; 313 out[2] = -a[2]; 314 return out; 315}; 316 317/** 318 * Normalize a vec3 319 * 320 * @param {vec3} out the receiving vector 321 * @param {vec3} a vector to normalize 322 * @returns {vec3} out 323 */ 324vec3.normalize = function(out, a) { 325 var x = a[0], 326 y = a[1], 327 z = a[2]; 328 var len = x*x + y*y + z*z; 329 if (len > 0) { 330 //TODO: evaluate use of glm_invsqrt here? 331 len = 1 / Math.sqrt(len); 332 out[0] = a[0] * len; 333 out[1] = a[1] * len; 334 out[2] = a[2] * len; 335 } 336 return out; 337}; 338 339/** 340 * Calculates the dot product of two vec3's 341 * 342 * @param {vec3} a the first operand 343 * @param {vec3} b the second operand 344 * @returns {Number} dot product of a and b 345 */ 346vec3.dot = function (a, b) { 347 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 348}; 349 350/** 351 * Computes the cross product of two vec3's 352 * 353 * @param {vec3} out the receiving vector 354 * @param {vec3} a the first operand 355 * @param {vec3} b the second operand 356 * @returns {vec3} out 357 */ 358vec3.cross = function(out, a, b) { 359 var ax = a[0], ay = a[1], az = a[2], 360 bx = b[0], by = b[1], bz = b[2]; 361 362 out[0] = ay * bz - az * by; 363 out[1] = az * bx - ax * bz; 364 out[2] = ax * by - ay * bx; 365 return out; 366}; 367 368/** 369 * Performs a linear interpolation between two vec3's 370 * 371 * @param {vec3} out the receiving vector 372 * @param {vec3} a the first operand 373 * @param {vec3} b the second operand 374 * @param {Number} t interpolation amount between the two inputs 375 * @returns {vec3} out 376 */ 377vec3.lerp = function (out, a, b, t) { 378 var ax = a[0], 379 ay = a[1], 380 az = a[2]; 381 out[0] = ax + t * (b[0] - ax); 382 out[1] = ay + t * (b[1] - ay); 383 out[2] = az + t * (b[2] - az); 384 return out; 385}; 386 387/** 388 * Transforms the vec3 with a mat4. 389 * 4th vector component is implicitly '1' 390 * 391 * @param {vec3} out the receiving vector 392 * @param {vec3} a the vector to transform 393 * @param {mat4} m matrix to transform with 394 * @returns {vec3} out 395 */ 396vec3.transformMat4 = function(out, a, m) { 397 var x = a[0], y = a[1], z = a[2]; 398 out[0] = m[0] * x + m[4] * y + m[8] * z + m[12]; 399 out[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; 400 out[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; 401 return out; 402}; 403 404/** 405 * Transforms the vec3 with a quat 406 * 407 * @param {vec3} out the receiving vector 408 * @param {vec3} a the vector to transform 409 * @param {quat} q quaternion to transform with 410 * @returns {vec3} out 411 */ 412vec3.transformQuat = function(out, a, q) { 413 var x = a[0], y = a[1], z = a[2], 414 qx = q[0], qy = q[1], qz = q[2], qw = q[3], 415 416 // calculate quat * vec 417 ix = qw * x + qy * z - qz * y, 418 iy = qw * y + qz * x - qx * z, 419 iz = qw * z + qx * y - qy * x, 420 iw = -qx * x - qy * y - qz * z; 421 422 // calculate result * inverse quat 423 out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 424 out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 425 out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 426 return out; 427}; 428 429/** 430 * Perform some operation over an array of vec3s. 431 * 432 * @param {Array} a the array of vectors to iterate over 433 * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed 434 * @param {Number} offset Number of elements to skip at the beginning of the array 435 * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array 436 * @param {Function} fn Function to call for each vector in the array 437 * @param {Object} [arg] additional argument to pass to fn 438 * @returns {Array} a 439 * @function 440 */ 441vec3.forEach = (function() { 442 var vec = vec3.create(); 443 444 return function(a, stride, offset, count, fn, arg) { 445 var i, l; 446 if(!stride) { 447 stride = 3; 448 } 449 450 if(!offset) { 451 offset = 0; 452 } 453 454 if(count) { 455 l = Math.min((count * stride) + offset, a.length); 456 } else { 457 l = a.length; 458 } 459 460 for(i = offset; i < l; i += stride) { 461 vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; 462 fn(vec, vec, arg); 463 a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; 464 } 465 466 return a; 467 }; 468})(); 469 470/** 471 * Returns a string representation of a vector 472 * 473 * @param {vec3} vec vector to represent as a string 474 * @returns {String} string representation of the vector 475 */ 476vec3.str = function (a) { 477 return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; 478}; 479 480if(typeof(exports) !== 'undefined') { 481 exports.vec3 = vec3; 482} 483