Home | History | Annotate | Download | only in gl-matrix
      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