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 4 Dimensional Vector 25 * @name vec4 26 */ 27var vec4 = {}; 28 29/** 30 * Creates a new, empty vec4 31 * 32 * @returns {vec4} a new 4D vector 33 */ 34vec4.create = function() { 35 var out = new GLMAT_ARRAY_TYPE(4); 36 out[0] = 0; 37 out[1] = 0; 38 out[2] = 0; 39 out[3] = 0; 40 return out; 41}; 42 43/** 44 * Creates a new vec4 initialized with values from an existing vector 45 * 46 * @param {vec4} a vector to clone 47 * @returns {vec4} a new 4D vector 48 */ 49vec4.clone = function(a) { 50 var out = new GLMAT_ARRAY_TYPE(4); 51 out[0] = a[0]; 52 out[1] = a[1]; 53 out[2] = a[2]; 54 out[3] = a[3]; 55 return out; 56}; 57 58/** 59 * Creates a new vec4 initialized with the given values 60 * 61 * @param {Number} x X component 62 * @param {Number} y Y component 63 * @param {Number} z Z component 64 * @param {Number} w W component 65 * @returns {vec4} a new 4D vector 66 */ 67vec4.fromValues = function(x, y, z, w) { 68 var out = new GLMAT_ARRAY_TYPE(4); 69 out[0] = x; 70 out[1] = y; 71 out[2] = z; 72 out[3] = w; 73 return out; 74}; 75 76/** 77 * Copy the values from one vec4 to another 78 * 79 * @param {vec4} out the receiving vector 80 * @param {vec4} a the source vector 81 * @returns {vec4} out 82 */ 83vec4.copy = function(out, a) { 84 out[0] = a[0]; 85 out[1] = a[1]; 86 out[2] = a[2]; 87 out[3] = a[3]; 88 return out; 89}; 90 91/** 92 * Set the components of a vec4 to the given values 93 * 94 * @param {vec4} out the receiving vector 95 * @param {Number} x X component 96 * @param {Number} y Y component 97 * @param {Number} z Z component 98 * @param {Number} w W component 99 * @returns {vec4} out 100 */ 101vec4.set = function(out, x, y, z, w) { 102 out[0] = x; 103 out[1] = y; 104 out[2] = z; 105 out[3] = w; 106 return out; 107}; 108 109/** 110 * Adds two vec4's 111 * 112 * @param {vec4} out the receiving vector 113 * @param {vec4} a the first operand 114 * @param {vec4} b the second operand 115 * @returns {vec4} out 116 */ 117vec4.add = function(out, a, b) { 118 out[0] = a[0] + b[0]; 119 out[1] = a[1] + b[1]; 120 out[2] = a[2] + b[2]; 121 out[3] = a[3] + b[3]; 122 return out; 123}; 124 125/** 126 * Subtracts two vec4's 127 * 128 * @param {vec4} out the receiving vector 129 * @param {vec4} a the first operand 130 * @param {vec4} b the second operand 131 * @returns {vec4} out 132 */ 133vec4.subtract = function(out, a, b) { 134 out[0] = a[0] - b[0]; 135 out[1] = a[1] - b[1]; 136 out[2] = a[2] - b[2]; 137 out[3] = a[3] - b[3]; 138 return out; 139}; 140 141/** 142 * Alias for {@link vec4.subtract} 143 * @function 144 */ 145vec4.sub = vec4.subtract; 146 147/** 148 * Multiplies two vec4's 149 * 150 * @param {vec4} out the receiving vector 151 * @param {vec4} a the first operand 152 * @param {vec4} b the second operand 153 * @returns {vec4} out 154 */ 155vec4.multiply = function(out, a, b) { 156 out[0] = a[0] * b[0]; 157 out[1] = a[1] * b[1]; 158 out[2] = a[2] * b[2]; 159 out[3] = a[3] * b[3]; 160 return out; 161}; 162 163/** 164 * Alias for {@link vec4.multiply} 165 * @function 166 */ 167vec4.mul = vec4.multiply; 168 169/** 170 * Divides two vec4's 171 * 172 * @param {vec4} out the receiving vector 173 * @param {vec4} a the first operand 174 * @param {vec4} b the second operand 175 * @returns {vec4} out 176 */ 177vec4.divide = function(out, a, b) { 178 out[0] = a[0] / b[0]; 179 out[1] = a[1] / b[1]; 180 out[2] = a[2] / b[2]; 181 out[3] = a[3] / b[3]; 182 return out; 183}; 184 185/** 186 * Alias for {@link vec4.divide} 187 * @function 188 */ 189vec4.div = vec4.divide; 190 191/** 192 * Returns the minimum of two vec4's 193 * 194 * @param {vec4} out the receiving vector 195 * @param {vec4} a the first operand 196 * @param {vec4} b the second operand 197 * @returns {vec4} out 198 */ 199vec4.min = function(out, a, b) { 200 out[0] = Math.min(a[0], b[0]); 201 out[1] = Math.min(a[1], b[1]); 202 out[2] = Math.min(a[2], b[2]); 203 out[3] = Math.min(a[3], b[3]); 204 return out; 205}; 206 207/** 208 * Returns the maximum of two vec4's 209 * 210 * @param {vec4} out the receiving vector 211 * @param {vec4} a the first operand 212 * @param {vec4} b the second operand 213 * @returns {vec4} out 214 */ 215vec4.max = function(out, a, b) { 216 out[0] = Math.max(a[0], b[0]); 217 out[1] = Math.max(a[1], b[1]); 218 out[2] = Math.max(a[2], b[2]); 219 out[3] = Math.max(a[3], b[3]); 220 return out; 221}; 222 223/** 224 * Scales a vec4 by a scalar number 225 * 226 * @param {vec4} out the receiving vector 227 * @param {vec4} a the vector to scale 228 * @param {Number} b amount to scale the vector by 229 * @returns {vec4} out 230 */ 231vec4.scale = function(out, a, b) { 232 out[0] = a[0] * b; 233 out[1] = a[1] * b; 234 out[2] = a[2] * b; 235 out[3] = a[3] * b; 236 return out; 237}; 238 239/** 240 * Calculates the euclidian distance between two vec4's 241 * 242 * @param {vec4} a the first operand 243 * @param {vec4} b the second operand 244 * @returns {Number} distance between a and b 245 */ 246vec4.distance = function(a, b) { 247 var x = b[0] - a[0], 248 y = b[1] - a[1], 249 z = b[2] - a[2], 250 w = b[3] - a[3]; 251 return Math.sqrt(x*x + y*y + z*z + w*w); 252}; 253 254/** 255 * Alias for {@link vec4.distance} 256 * @function 257 */ 258vec4.dist = vec4.distance; 259 260/** 261 * Calculates the squared euclidian distance between two vec4's 262 * 263 * @param {vec4} a the first operand 264 * @param {vec4} b the second operand 265 * @returns {Number} squared distance between a and b 266 */ 267vec4.squaredDistance = function(a, b) { 268 var x = b[0] - a[0], 269 y = b[1] - a[1], 270 z = b[2] - a[2], 271 w = b[3] - a[3]; 272 return x*x + y*y + z*z + w*w; 273}; 274 275/** 276 * Alias for {@link vec4.squaredDistance} 277 * @function 278 */ 279vec4.sqrDist = vec4.squaredDistance; 280 281/** 282 * Calculates the length of a vec4 283 * 284 * @param {vec4} a vector to calculate length of 285 * @returns {Number} length of a 286 */ 287vec4.length = function (a) { 288 var x = a[0], 289 y = a[1], 290 z = a[2], 291 w = a[3]; 292 return Math.sqrt(x*x + y*y + z*z + w*w); 293}; 294 295/** 296 * Alias for {@link vec4.length} 297 * @function 298 */ 299vec4.len = vec4.length; 300 301/** 302 * Calculates the squared length of a vec4 303 * 304 * @param {vec4} a vector to calculate squared length of 305 * @returns {Number} squared length of a 306 */ 307vec4.squaredLength = function (a) { 308 var x = a[0], 309 y = a[1], 310 z = a[2], 311 w = a[3]; 312 return x*x + y*y + z*z + w*w; 313}; 314 315/** 316 * Alias for {@link vec4.squaredLength} 317 * @function 318 */ 319vec4.sqrLen = vec4.squaredLength; 320 321/** 322 * Negates the components of a vec4 323 * 324 * @param {vec4} out the receiving vector 325 * @param {vec4} a vector to negate 326 * @returns {vec4} out 327 */ 328vec4.negate = function(out, a) { 329 out[0] = -a[0]; 330 out[1] = -a[1]; 331 out[2] = -a[2]; 332 out[3] = -a[3]; 333 return out; 334}; 335 336/** 337 * Normalize a vec4 338 * 339 * @param {vec4} out the receiving vector 340 * @param {vec4} a vector to normalize 341 * @returns {vec4} out 342 */ 343vec4.normalize = function(out, a) { 344 var x = a[0], 345 y = a[1], 346 z = a[2], 347 w = a[3]; 348 var len = x*x + y*y + z*z + w*w; 349 if (len > 0) { 350 len = 1 / Math.sqrt(len); 351 out[0] = a[0] * len; 352 out[1] = a[1] * len; 353 out[2] = a[2] * len; 354 out[3] = a[3] * len; 355 } 356 return out; 357}; 358 359/** 360 * Calculates the dot product of two vec4's 361 * 362 * @param {vec4} a the first operand 363 * @param {vec4} b the second operand 364 * @returns {Number} dot product of a and b 365 */ 366vec4.dot = function (a, b) { 367 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 368}; 369 370/** 371 * Performs a linear interpolation between two vec4's 372 * 373 * @param {vec4} out the receiving vector 374 * @param {vec4} a the first operand 375 * @param {vec4} b the second operand 376 * @param {Number} t interpolation amount between the two inputs 377 * @returns {vec4} out 378 */ 379vec4.lerp = function (out, a, b, t) { 380 var ax = a[0], 381 ay = a[1], 382 az = a[2], 383 aw = a[3]; 384 out[0] = ax + t * (b[0] - ax); 385 out[1] = ay + t * (b[1] - ay); 386 out[2] = az + t * (b[2] - az); 387 out[3] = aw + t * (b[3] - aw); 388 return out; 389}; 390 391/** 392 * Transforms the vec4 with a mat4. 393 * 394 * @param {vec4} out the receiving vector 395 * @param {vec4} a the vector to transform 396 * @param {mat4} m matrix to transform with 397 * @returns {vec4} out 398 */ 399vec4.transformMat4 = function(out, a, m) { 400 var x = a[0], y = a[1], z = a[2], w = a[3]; 401 out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; 402 out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; 403 out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; 404 out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; 405 return out; 406}; 407 408/** 409 * Transforms the vec4 with a quat 410 * 411 * @param {vec4} out the receiving vector 412 * @param {vec4} a the vector to transform 413 * @param {quat} q quaternion to transform with 414 * @returns {vec4} out 415 */ 416vec4.transformQuat = function(out, a, q) { 417 var x = a[0], y = a[1], z = a[2], 418 qx = q[0], qy = q[1], qz = q[2], qw = q[3], 419 420 // calculate quat * vec 421 ix = qw * x + qy * z - qz * y, 422 iy = qw * y + qz * x - qx * z, 423 iz = qw * z + qx * y - qy * x, 424 iw = -qx * x - qy * y - qz * z; 425 426 // calculate result * inverse quat 427 out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 428 out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 429 out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 430 return out; 431}; 432 433/** 434 * Perform some operation over an array of vec4s. 435 * 436 * @param {Array} a the array of vectors to iterate over 437 * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed 438 * @param {Number} offset Number of elements to skip at the beginning of the array 439 * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array 440 * @param {Function} fn Function to call for each vector in the array 441 * @param {Object} [arg] additional argument to pass to fn 442 * @returns {Array} a 443 * @function 444 */ 445vec4.forEach = (function() { 446 var vec = vec4.create(); 447 448 return function(a, stride, offset, count, fn, arg) { 449 var i, l; 450 if(!stride) { 451 stride = 4; 452 } 453 454 if(!offset) { 455 offset = 0; 456 } 457 458 if(count) { 459 l = Math.min((count * stride) + offset, a.length); 460 } else { 461 l = a.length; 462 } 463 464 for(i = offset; i < l; i += stride) { 465 vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; 466 fn(vec, vec, arg); 467 a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; 468 } 469 470 return a; 471 }; 472})(); 473 474/** 475 * Returns a string representation of a vector 476 * 477 * @param {vec4} vec vector to represent as a string 478 * @returns {String} string representation of the vector 479 */ 480vec4.str = function (a) { 481 return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; 482}; 483 484if(typeof(exports) !== 'undefined') { 485 exports.vec4 = vec4; 486} 487