1 /* Copyright (c) 2015, Brandon Jones, Colin MacKenzie IV. 2 3 Permission is hereby granted, free of charge, to any person obtaining a copy 4 of this software and associated documentation files (the "Software"), to deal 5 in the Software without restriction, including without limitation the rights 6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 copies of the Software, and to permit persons to whom the Software is 8 furnished to do so, subject to the following conditions: 9 10 The above copyright notice and this permission notice shall be included in 11 all copies or substantial portions of the Software. 12 13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 THE SOFTWARE. */ 20 21 var glMatrix = require("./common.js"); 22 23 /** 24 * @class 2 Dimensional Vector 25 * @name vec2 26 */ 27 var vec2 = {}; 28 29 /** 30 * Creates a new, empty vec2 31 * 32 * @returns {vec2} a new 2D vector 33 */ 34 vec2.create = function() { 35 var out = new glMatrix.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 */ 47 vec2.clone = function(a) { 48 var out = new glMatrix.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 */ 61 vec2.fromValues = function(x, y) { 62 var out = new glMatrix.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 */ 75 vec2.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 */ 89 vec2.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 */ 103 vec2.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 vector b from vector a 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 */ 117 vec2.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 */ 127 vec2.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 */ 137 vec2.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 */ 147 vec2.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 */ 157 vec2.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 */ 167 vec2.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 */ 177 vec2.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 */ 191 vec2.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 */ 205 vec2.scale = function(out, a, b) { 206 out[0] = a[0] * b; 207 out[1] = a[1] * b; 208 return out; 209 }; 210 211 /** 212 * Adds two vec2's after scaling the second operand by a scalar value 213 * 214 * @param {vec2} out the receiving vector 215 * @param {vec2} a the first operand 216 * @param {vec2} b the second operand 217 * @param {Number} scale the amount to scale b by before adding 218 * @returns {vec2} out 219 */ 220 vec2.scaleAndAdd = function(out, a, b, scale) { 221 out[0] = a[0] + (b[0] * scale); 222 out[1] = a[1] + (b[1] * scale); 223 return out; 224 }; 225 226 /** 227 * Calculates the euclidian distance between two vec2's 228 * 229 * @param {vec2} a the first operand 230 * @param {vec2} b the second operand 231 * @returns {Number} distance between a and b 232 */ 233 vec2.distance = function(a, b) { 234 var x = b[0] - a[0], 235 y = b[1] - a[1]; 236 return Math.sqrt(x*x + y*y); 237 }; 238 239 /** 240 * Alias for {@link vec2.distance} 241 * @function 242 */ 243 vec2.dist = vec2.distance; 244 245 /** 246 * Calculates the squared euclidian distance between two vec2's 247 * 248 * @param {vec2} a the first operand 249 * @param {vec2} b the second operand 250 * @returns {Number} squared distance between a and b 251 */ 252 vec2.squaredDistance = function(a, b) { 253 var x = b[0] - a[0], 254 y = b[1] - a[1]; 255 return x*x + y*y; 256 }; 257 258 /** 259 * Alias for {@link vec2.squaredDistance} 260 * @function 261 */ 262 vec2.sqrDist = vec2.squaredDistance; 263 264 /** 265 * Calculates the length of a vec2 266 * 267 * @param {vec2} a vector to calculate length of 268 * @returns {Number} length of a 269 */ 270 vec2.length = function (a) { 271 var x = a[0], 272 y = a[1]; 273 return Math.sqrt(x*x + y*y); 274 }; 275 276 /** 277 * Alias for {@link vec2.length} 278 * @function 279 */ 280 vec2.len = vec2.length; 281 282 /** 283 * Calculates the squared length of a vec2 284 * 285 * @param {vec2} a vector to calculate squared length of 286 * @returns {Number} squared length of a 287 */ 288 vec2.squaredLength = function (a) { 289 var x = a[0], 290 y = a[1]; 291 return x*x + y*y; 292 }; 293 294 /** 295 * Alias for {@link vec2.squaredLength} 296 * @function 297 */ 298 vec2.sqrLen = vec2.squaredLength; 299 300 /** 301 * Negates the components of a vec2 302 * 303 * @param {vec2} out the receiving vector 304 * @param {vec2} a vector to negate 305 * @returns {vec2} out 306 */ 307 vec2.negate = function(out, a) { 308 out[0] = -a[0]; 309 out[1] = -a[1]; 310 return out; 311 }; 312 313 /** 314 * Returns the inverse of the components of a vec2 315 * 316 * @param {vec2} out the receiving vector 317 * @param {vec2} a vector to invert 318 * @returns {vec2} out 319 */ 320 vec2.inverse = function(out, a) { 321 out[0] = 1.0 / a[0]; 322 out[1] = 1.0 / a[1]; 323 return out; 324 }; 325 326 /** 327 * Normalize a vec2 328 * 329 * @param {vec2} out the receiving vector 330 * @param {vec2} a vector to normalize 331 * @returns {vec2} out 332 */ 333 vec2.normalize = function(out, a) { 334 var x = a[0], 335 y = a[1]; 336 var len = x*x + y*y; 337 if (len > 0) { 338 //TODO: evaluate use of glm_invsqrt here? 339 len = 1 / Math.sqrt(len); 340 out[0] = a[0] * len; 341 out[1] = a[1] * len; 342 } 343 return out; 344 }; 345 346 /** 347 * Calculates the dot product of two vec2's 348 * 349 * @param {vec2} a the first operand 350 * @param {vec2} b the second operand 351 * @returns {Number} dot product of a and b 352 */ 353 vec2.dot = function (a, b) { 354 return a[0] * b[0] + a[1] * b[1]; 355 }; 356 357 /** 358 * Computes the cross product of two vec2's 359 * Note that the cross product must by definition produce a 3D vector 360 * 361 * @param {vec3} out the receiving vector 362 * @param {vec2} a the first operand 363 * @param {vec2} b the second operand 364 * @returns {vec3} out 365 */ 366 vec2.cross = function(out, a, b) { 367 var z = a[0] * b[1] - a[1] * b[0]; 368 out[0] = out[1] = 0; 369 out[2] = z; 370 return out; 371 }; 372 373 /** 374 * Performs a linear interpolation between two vec2's 375 * 376 * @param {vec2} out the receiving vector 377 * @param {vec2} a the first operand 378 * @param {vec2} b the second operand 379 * @param {Number} t interpolation amount between the two inputs 380 * @returns {vec2} out 381 */ 382 vec2.lerp = function (out, a, b, t) { 383 var ax = a[0], 384 ay = a[1]; 385 out[0] = ax + t * (b[0] - ax); 386 out[1] = ay + t * (b[1] - ay); 387 return out; 388 }; 389 390 /** 391 * Generates a random vector with the given scale 392 * 393 * @param {vec2} out the receiving vector 394 * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned 395 * @returns {vec2} out 396 */ 397 vec2.random = function (out, scale) { 398 scale = scale || 1.0; 399 var r = glMatrix.RANDOM() * 2.0 * Math.PI; 400 out[0] = Math.cos(r) * scale; 401 out[1] = Math.sin(r) * scale; 402 return out; 403 }; 404 405 /** 406 * Transforms the vec2 with a mat2 407 * 408 * @param {vec2} out the receiving vector 409 * @param {vec2} a the vector to transform 410 * @param {mat2} m matrix to transform with 411 * @returns {vec2} out 412 */ 413 vec2.transformMat2 = function(out, a, m) { 414 var x = a[0], 415 y = a[1]; 416 out[0] = m[0] * x + m[2] * y; 417 out[1] = m[1] * x + m[3] * y; 418 return out; 419 }; 420 421 /** 422 * Transforms the vec2 with a mat2d 423 * 424 * @param {vec2} out the receiving vector 425 * @param {vec2} a the vector to transform 426 * @param {mat2d} m matrix to transform with 427 * @returns {vec2} out 428 */ 429 vec2.transformMat2d = function(out, a, m) { 430 var x = a[0], 431 y = a[1]; 432 out[0] = m[0] * x + m[2] * y + m[4]; 433 out[1] = m[1] * x + m[3] * y + m[5]; 434 return out; 435 }; 436 437 /** 438 * Transforms the vec2 with a mat3 439 * 3rd vector component is implicitly '1' 440 * 441 * @param {vec2} out the receiving vector 442 * @param {vec2} a the vector to transform 443 * @param {mat3} m matrix to transform with 444 * @returns {vec2} out 445 */ 446 vec2.transformMat3 = function(out, a, m) { 447 var x = a[0], 448 y = a[1]; 449 out[0] = m[0] * x + m[3] * y + m[6]; 450 out[1] = m[1] * x + m[4] * y + m[7]; 451 return out; 452 }; 453 454 /** 455 * Transforms the vec2 with a mat4 456 * 3rd vector component is implicitly '0' 457 * 4th vector component is implicitly '1' 458 * 459 * @param {vec2} out the receiving vector 460 * @param {vec2} a the vector to transform 461 * @param {mat4} m matrix to transform with 462 * @returns {vec2} out 463 */ 464 vec2.transformMat4 = function(out, a, m) { 465 var x = a[0], 466 y = a[1]; 467 out[0] = m[0] * x + m[4] * y + m[12]; 468 out[1] = m[1] * x + m[5] * y + m[13]; 469 return out; 470 }; 471 472 /** 473 * Perform some operation over an array of vec2s. 474 * 475 * @param {Array} a the array of vectors to iterate over 476 * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed 477 * @param {Number} offset Number of elements to skip at the beginning of the array 478 * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array 479 * @param {Function} fn Function to call for each vector in the array 480 * @param {Object} [arg] additional argument to pass to fn 481 * @returns {Array} a 482 * @function 483 */ 484 vec2.forEach = (function() { 485 var vec = vec2.create(); 486 487 return function(a, stride, offset, count, fn, arg) { 488 var i, l; 489 if(!stride) { 490 stride = 2; 491 } 492 493 if(!offset) { 494 offset = 0; 495 } 496 497 if(count) { 498 l = Math.min((count * stride) + offset, a.length); 499 } else { 500 l = a.length; 501 } 502 503 for(i = offset; i < l; i += stride) { 504 vec[0] = a[i]; vec[1] = a[i+1]; 505 fn(vec, vec, arg); 506 a[i] = vec[0]; a[i+1] = vec[1]; 507 } 508 509 return a; 510 }; 511 })(); 512 513 /** 514 * Returns a string representation of a vector 515 * 516 * @param {vec2} vec vector to represent as a string 517 * @returns {String} string representation of the vector 518 */ 519 vec2.str = function (a) { 520 return 'vec2(' + a[0] + ', ' + a[1] + ')'; 521 }; 522 523 module.exports = vec2; 524