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