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 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 glMatrix.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 glMatrix.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 glMatrix.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 vector b from vector a 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 * Adds two vec4's after scaling the second operand by a scalar value 241 * 242 * @param {vec4} out the receiving vector 243 * @param {vec4} a the first operand 244 * @param {vec4} b the second operand 245 * @param {Number} scale the amount to scale b by before adding 246 * @returns {vec4} out 247 */ 248vec4.scaleAndAdd = function(out, a, b, scale) { 249 out[0] = a[0] + (b[0] * scale); 250 out[1] = a[1] + (b[1] * scale); 251 out[2] = a[2] + (b[2] * scale); 252 out[3] = a[3] + (b[3] * scale); 253 return out; 254}; 255 256/** 257 * Calculates the euclidian distance between two vec4's 258 * 259 * @param {vec4} a the first operand 260 * @param {vec4} b the second operand 261 * @returns {Number} distance between a and b 262 */ 263vec4.distance = function(a, b) { 264 var x = b[0] - a[0], 265 y = b[1] - a[1], 266 z = b[2] - a[2], 267 w = b[3] - a[3]; 268 return Math.sqrt(x*x + y*y + z*z + w*w); 269}; 270 271/** 272 * Alias for {@link vec4.distance} 273 * @function 274 */ 275vec4.dist = vec4.distance; 276 277/** 278 * Calculates the squared euclidian distance between two vec4's 279 * 280 * @param {vec4} a the first operand 281 * @param {vec4} b the second operand 282 * @returns {Number} squared distance between a and b 283 */ 284vec4.squaredDistance = function(a, b) { 285 var x = b[0] - a[0], 286 y = b[1] - a[1], 287 z = b[2] - a[2], 288 w = b[3] - a[3]; 289 return x*x + y*y + z*z + w*w; 290}; 291 292/** 293 * Alias for {@link vec4.squaredDistance} 294 * @function 295 */ 296vec4.sqrDist = vec4.squaredDistance; 297 298/** 299 * Calculates the length of a vec4 300 * 301 * @param {vec4} a vector to calculate length of 302 * @returns {Number} length of a 303 */ 304vec4.length = function (a) { 305 var x = a[0], 306 y = a[1], 307 z = a[2], 308 w = a[3]; 309 return Math.sqrt(x*x + y*y + z*z + w*w); 310}; 311 312/** 313 * Alias for {@link vec4.length} 314 * @function 315 */ 316vec4.len = vec4.length; 317 318/** 319 * Calculates the squared length of a vec4 320 * 321 * @param {vec4} a vector to calculate squared length of 322 * @returns {Number} squared length of a 323 */ 324vec4.squaredLength = function (a) { 325 var x = a[0], 326 y = a[1], 327 z = a[2], 328 w = a[3]; 329 return x*x + y*y + z*z + w*w; 330}; 331 332/** 333 * Alias for {@link vec4.squaredLength} 334 * @function 335 */ 336vec4.sqrLen = vec4.squaredLength; 337 338/** 339 * Negates the components of a vec4 340 * 341 * @param {vec4} out the receiving vector 342 * @param {vec4} a vector to negate 343 * @returns {vec4} out 344 */ 345vec4.negate = function(out, a) { 346 out[0] = -a[0]; 347 out[1] = -a[1]; 348 out[2] = -a[2]; 349 out[3] = -a[3]; 350 return out; 351}; 352 353/** 354 * Returns the inverse of the components of a vec4 355 * 356 * @param {vec4} out the receiving vector 357 * @param {vec4} a vector to invert 358 * @returns {vec4} out 359 */ 360vec4.inverse = function(out, a) { 361 out[0] = 1.0 / a[0]; 362 out[1] = 1.0 / a[1]; 363 out[2] = 1.0 / a[2]; 364 out[3] = 1.0 / a[3]; 365 return out; 366}; 367 368/** 369 * Normalize a vec4 370 * 371 * @param {vec4} out the receiving vector 372 * @param {vec4} a vector to normalize 373 * @returns {vec4} out 374 */ 375vec4.normalize = function(out, a) { 376 var x = a[0], 377 y = a[1], 378 z = a[2], 379 w = a[3]; 380 var len = x*x + y*y + z*z + w*w; 381 if (len > 0) { 382 len = 1 / Math.sqrt(len); 383 out[0] = x * len; 384 out[1] = y * len; 385 out[2] = z * len; 386 out[3] = w * len; 387 } 388 return out; 389}; 390 391/** 392 * Calculates the dot product of two vec4's 393 * 394 * @param {vec4} a the first operand 395 * @param {vec4} b the second operand 396 * @returns {Number} dot product of a and b 397 */ 398vec4.dot = function (a, b) { 399 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 400}; 401 402/** 403 * Performs a linear interpolation between two vec4's 404 * 405 * @param {vec4} out the receiving vector 406 * @param {vec4} a the first operand 407 * @param {vec4} b the second operand 408 * @param {Number} t interpolation amount between the two inputs 409 * @returns {vec4} out 410 */ 411vec4.lerp = function (out, a, b, t) { 412 var ax = a[0], 413 ay = a[1], 414 az = a[2], 415 aw = a[3]; 416 out[0] = ax + t * (b[0] - ax); 417 out[1] = ay + t * (b[1] - ay); 418 out[2] = az + t * (b[2] - az); 419 out[3] = aw + t * (b[3] - aw); 420 return out; 421}; 422 423/** 424 * Generates a random vector with the given scale 425 * 426 * @param {vec4} out the receiving vector 427 * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned 428 * @returns {vec4} out 429 */ 430vec4.random = function (out, scale) { 431 scale = scale || 1.0; 432 433 //TODO: This is a pretty awful way of doing this. Find something better. 434 out[0] = glMatrix.RANDOM(); 435 out[1] = glMatrix.RANDOM(); 436 out[2] = glMatrix.RANDOM(); 437 out[3] = glMatrix.RANDOM(); 438 vec4.normalize(out, out); 439 vec4.scale(out, out, scale); 440 return out; 441}; 442 443/** 444 * Transforms the vec4 with a mat4. 445 * 446 * @param {vec4} out the receiving vector 447 * @param {vec4} a the vector to transform 448 * @param {mat4} m matrix to transform with 449 * @returns {vec4} out 450 */ 451vec4.transformMat4 = function(out, a, m) { 452 var x = a[0], y = a[1], z = a[2], w = a[3]; 453 out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; 454 out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; 455 out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; 456 out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; 457 return out; 458}; 459 460/** 461 * Transforms the vec4 with a quat 462 * 463 * @param {vec4} out the receiving vector 464 * @param {vec4} a the vector to transform 465 * @param {quat} q quaternion to transform with 466 * @returns {vec4} out 467 */ 468vec4.transformQuat = function(out, a, q) { 469 var x = a[0], y = a[1], z = a[2], 470 qx = q[0], qy = q[1], qz = q[2], qw = q[3], 471 472 // calculate quat * vec 473 ix = qw * x + qy * z - qz * y, 474 iy = qw * y + qz * x - qx * z, 475 iz = qw * z + qx * y - qy * x, 476 iw = -qx * x - qy * y - qz * z; 477 478 // calculate result * inverse quat 479 out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; 480 out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; 481 out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; 482 out[3] = a[3]; 483 return out; 484}; 485 486/** 487 * Perform some operation over an array of vec4s. 488 * 489 * @param {Array} a the array of vectors to iterate over 490 * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed 491 * @param {Number} offset Number of elements to skip at the beginning of the array 492 * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array 493 * @param {Function} fn Function to call for each vector in the array 494 * @param {Object} [arg] additional argument to pass to fn 495 * @returns {Array} a 496 * @function 497 */ 498vec4.forEach = (function() { 499 var vec = vec4.create(); 500 501 return function(a, stride, offset, count, fn, arg) { 502 var i, l; 503 if(!stride) { 504 stride = 4; 505 } 506 507 if(!offset) { 508 offset = 0; 509 } 510 511 if(count) { 512 l = Math.min((count * stride) + offset, a.length); 513 } else { 514 l = a.length; 515 } 516 517 for(i = offset; i < l; i += stride) { 518 vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2]; vec[3] = a[i+3]; 519 fn(vec, vec, arg); 520 a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2]; a[i+3] = vec[3]; 521 } 522 523 return a; 524 }; 525})(); 526 527/** 528 * Returns a string representation of a vector 529 * 530 * @param {vec4} vec vector to represent as a string 531 * @returns {String} string representation of the vector 532 */ 533vec4.str = function (a) { 534 return 'vec4(' + a[0] + ', ' + a[1] + ', ' + a[2] + ', ' + a[3] + ')'; 535}; 536 537module.exports = vec4; 538