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 3 Dimensional Vector
     25  * @name vec3
     26  */
     27 var vec3 = {};
     28 
     29 /**
     30  * Creates a new, empty vec3
     31  *
     32  * @returns {vec3} a new 3D vector
     33  */
     34 vec3.create = function() {
     35     var out = new glMatrix.ARRAY_TYPE(3);
     36     out[0] = 0;
     37     out[1] = 0;
     38     out[2] = 0;
     39     return out;
     40 };
     41 
     42 /**
     43  * Creates a new vec3 initialized with values from an existing vector
     44  *
     45  * @param {vec3} a vector to clone
     46  * @returns {vec3} a new 3D vector
     47  */
     48 vec3.clone = function(a) {
     49     var out = new glMatrix.ARRAY_TYPE(3);
     50     out[0] = a[0];
     51     out[1] = a[1];
     52     out[2] = a[2];
     53     return out;
     54 };
     55 
     56 /**
     57  * Creates a new vec3 initialized with the given values
     58  *
     59  * @param {Number} x X component
     60  * @param {Number} y Y component
     61  * @param {Number} z Z component
     62  * @returns {vec3} a new 3D vector
     63  */
     64 vec3.fromValues = function(x, y, z) {
     65     var out = new glMatrix.ARRAY_TYPE(3);
     66     out[0] = x;
     67     out[1] = y;
     68     out[2] = z;
     69     return out;
     70 };
     71 
     72 /**
     73  * Copy the values from one vec3 to another
     74  *
     75  * @param {vec3} out the receiving vector
     76  * @param {vec3} a the source vector
     77  * @returns {vec3} out
     78  */
     79 vec3.copy = function(out, a) {
     80     out[0] = a[0];
     81     out[1] = a[1];
     82     out[2] = a[2];
     83     return out;
     84 };
     85 
     86 /**
     87  * Set the components of a vec3 to the given values
     88  *
     89  * @param {vec3} out the receiving vector
     90  * @param {Number} x X component
     91  * @param {Number} y Y component
     92  * @param {Number} z Z component
     93  * @returns {vec3} out
     94  */
     95 vec3.set = function(out, x, y, z) {
     96     out[0] = x;
     97     out[1] = y;
     98     out[2] = z;
     99     return out;
    100 };
    101 
    102 /**
    103  * Adds two vec3's
    104  *
    105  * @param {vec3} out the receiving vector
    106  * @param {vec3} a the first operand
    107  * @param {vec3} b the second operand
    108  * @returns {vec3} out
    109  */
    110 vec3.add = function(out, a, b) {
    111     out[0] = a[0] + b[0];
    112     out[1] = a[1] + b[1];
    113     out[2] = a[2] + b[2];
    114     return out;
    115 };
    116 
    117 /**
    118  * Subtracts vector b from vector a
    119  *
    120  * @param {vec3} out the receiving vector
    121  * @param {vec3} a the first operand
    122  * @param {vec3} b the second operand
    123  * @returns {vec3} out
    124  */
    125 vec3.subtract = function(out, a, b) {
    126     out[0] = a[0] - b[0];
    127     out[1] = a[1] - b[1];
    128     out[2] = a[2] - b[2];
    129     return out;
    130 };
    131 
    132 /**
    133  * Alias for {@link vec3.subtract}
    134  * @function
    135  */
    136 vec3.sub = vec3.subtract;
    137 
    138 /**
    139  * Multiplies two vec3's
    140  *
    141  * @param {vec3} out the receiving vector
    142  * @param {vec3} a the first operand
    143  * @param {vec3} b the second operand
    144  * @returns {vec3} out
    145  */
    146 vec3.multiply = function(out, a, b) {
    147     out[0] = a[0] * b[0];
    148     out[1] = a[1] * b[1];
    149     out[2] = a[2] * b[2];
    150     return out;
    151 };
    152 
    153 /**
    154  * Alias for {@link vec3.multiply}
    155  * @function
    156  */
    157 vec3.mul = vec3.multiply;
    158 
    159 /**
    160  * Divides two vec3's
    161  *
    162  * @param {vec3} out the receiving vector
    163  * @param {vec3} a the first operand
    164  * @param {vec3} b the second operand
    165  * @returns {vec3} out
    166  */
    167 vec3.divide = function(out, a, b) {
    168     out[0] = a[0] / b[0];
    169     out[1] = a[1] / b[1];
    170     out[2] = a[2] / b[2];
    171     return out;
    172 };
    173 
    174 /**
    175  * Alias for {@link vec3.divide}
    176  * @function
    177  */
    178 vec3.div = vec3.divide;
    179 
    180 /**
    181  * Returns the minimum of two vec3's
    182  *
    183  * @param {vec3} out the receiving vector
    184  * @param {vec3} a the first operand
    185  * @param {vec3} b the second operand
    186  * @returns {vec3} out
    187  */
    188 vec3.min = function(out, a, b) {
    189     out[0] = Math.min(a[0], b[0]);
    190     out[1] = Math.min(a[1], b[1]);
    191     out[2] = Math.min(a[2], b[2]);
    192     return out;
    193 };
    194 
    195 /**
    196  * Returns the maximum of two vec3's
    197  *
    198  * @param {vec3} out the receiving vector
    199  * @param {vec3} a the first operand
    200  * @param {vec3} b the second operand
    201  * @returns {vec3} out
    202  */
    203 vec3.max = function(out, a, b) {
    204     out[0] = Math.max(a[0], b[0]);
    205     out[1] = Math.max(a[1], b[1]);
    206     out[2] = Math.max(a[2], b[2]);
    207     return out;
    208 };
    209 
    210 /**
    211  * Scales a vec3 by a scalar number
    212  *
    213  * @param {vec3} out the receiving vector
    214  * @param {vec3} a the vector to scale
    215  * @param {Number} b amount to scale the vector by
    216  * @returns {vec3} out
    217  */
    218 vec3.scale = function(out, a, b) {
    219     out[0] = a[0] * b;
    220     out[1] = a[1] * b;
    221     out[2] = a[2] * b;
    222     return out;
    223 };
    224 
    225 /**
    226  * Adds two vec3's after scaling the second operand by a scalar value
    227  *
    228  * @param {vec3} out the receiving vector
    229  * @param {vec3} a the first operand
    230  * @param {vec3} b the second operand
    231  * @param {Number} scale the amount to scale b by before adding
    232  * @returns {vec3} out
    233  */
    234 vec3.scaleAndAdd = function(out, a, b, scale) {
    235     out[0] = a[0] + (b[0] * scale);
    236     out[1] = a[1] + (b[1] * scale);
    237     out[2] = a[2] + (b[2] * scale);
    238     return out;
    239 };
    240 
    241 /**
    242  * Calculates the euclidian distance between two vec3's
    243  *
    244  * @param {vec3} a the first operand
    245  * @param {vec3} b the second operand
    246  * @returns {Number} distance between a and b
    247  */
    248 vec3.distance = function(a, b) {
    249     var x = b[0] - a[0],
    250         y = b[1] - a[1],
    251         z = b[2] - a[2];
    252     return Math.sqrt(x*x + y*y + z*z);
    253 };
    254 
    255 /**
    256  * Alias for {@link vec3.distance}
    257  * @function
    258  */
    259 vec3.dist = vec3.distance;
    260 
    261 /**
    262  * Calculates the squared euclidian distance between two vec3's
    263  *
    264  * @param {vec3} a the first operand
    265  * @param {vec3} b the second operand
    266  * @returns {Number} squared distance between a and b
    267  */
    268 vec3.squaredDistance = function(a, b) {
    269     var x = b[0] - a[0],
    270         y = b[1] - a[1],
    271         z = b[2] - a[2];
    272     return x*x + y*y + z*z;
    273 };
    274 
    275 /**
    276  * Alias for {@link vec3.squaredDistance}
    277  * @function
    278  */
    279 vec3.sqrDist = vec3.squaredDistance;
    280 
    281 /**
    282  * Calculates the length of a vec3
    283  *
    284  * @param {vec3} a vector to calculate length of
    285  * @returns {Number} length of a
    286  */
    287 vec3.length = function (a) {
    288     var x = a[0],
    289         y = a[1],
    290         z = a[2];
    291     return Math.sqrt(x*x + y*y + z*z);
    292 };
    293 
    294 /**
    295  * Alias for {@link vec3.length}
    296  * @function
    297  */
    298 vec3.len = vec3.length;
    299 
    300 /**
    301  * Calculates the squared length of a vec3
    302  *
    303  * @param {vec3} a vector to calculate squared length of
    304  * @returns {Number} squared length of a
    305  */
    306 vec3.squaredLength = function (a) {
    307     var x = a[0],
    308         y = a[1],
    309         z = a[2];
    310     return x*x + y*y + z*z;
    311 };
    312 
    313 /**
    314  * Alias for {@link vec3.squaredLength}
    315  * @function
    316  */
    317 vec3.sqrLen = vec3.squaredLength;
    318 
    319 /**
    320  * Negates the components of a vec3
    321  *
    322  * @param {vec3} out the receiving vector
    323  * @param {vec3} a vector to negate
    324  * @returns {vec3} out
    325  */
    326 vec3.negate = function(out, a) {
    327     out[0] = -a[0];
    328     out[1] = -a[1];
    329     out[2] = -a[2];
    330     return out;
    331 };
    332 
    333 /**
    334  * Returns the inverse of the components of a vec3
    335  *
    336  * @param {vec3} out the receiving vector
    337  * @param {vec3} a vector to invert
    338  * @returns {vec3} out
    339  */
    340 vec3.inverse = function(out, a) {
    341   out[0] = 1.0 / a[0];
    342   out[1] = 1.0 / a[1];
    343   out[2] = 1.0 / a[2];
    344   return out;
    345 };
    346 
    347 /**
    348  * Normalize a vec3
    349  *
    350  * @param {vec3} out the receiving vector
    351  * @param {vec3} a vector to normalize
    352  * @returns {vec3} out
    353  */
    354 vec3.normalize = function(out, a) {
    355     var x = a[0],
    356         y = a[1],
    357         z = a[2];
    358     var len = x*x + y*y + z*z;
    359     if (len > 0) {
    360         //TODO: evaluate use of glm_invsqrt here?
    361         len = 1 / Math.sqrt(len);
    362         out[0] = a[0] * len;
    363         out[1] = a[1] * len;
    364         out[2] = a[2] * len;
    365     }
    366     return out;
    367 };
    368 
    369 /**
    370  * Calculates the dot product of two vec3's
    371  *
    372  * @param {vec3} a the first operand
    373  * @param {vec3} b the second operand
    374  * @returns {Number} dot product of a and b
    375  */
    376 vec3.dot = function (a, b) {
    377     return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
    378 };
    379 
    380 /**
    381  * Computes the cross product of two vec3's
    382  *
    383  * @param {vec3} out the receiving vector
    384  * @param {vec3} a the first operand
    385  * @param {vec3} b the second operand
    386  * @returns {vec3} out
    387  */
    388 vec3.cross = function(out, a, b) {
    389     var ax = a[0], ay = a[1], az = a[2],
    390         bx = b[0], by = b[1], bz = b[2];
    391 
    392     out[0] = ay * bz - az * by;
    393     out[1] = az * bx - ax * bz;
    394     out[2] = ax * by - ay * bx;
    395     return out;
    396 };
    397 
    398 /**
    399  * Performs a linear interpolation between two vec3's
    400  *
    401  * @param {vec3} out the receiving vector
    402  * @param {vec3} a the first operand
    403  * @param {vec3} b the second operand
    404  * @param {Number} t interpolation amount between the two inputs
    405  * @returns {vec3} out
    406  */
    407 vec3.lerp = function (out, a, b, t) {
    408     var ax = a[0],
    409         ay = a[1],
    410         az = a[2];
    411     out[0] = ax + t * (b[0] - ax);
    412     out[1] = ay + t * (b[1] - ay);
    413     out[2] = az + t * (b[2] - az);
    414     return out;
    415 };
    416 
    417 /**
    418  * Performs a hermite interpolation with two control points
    419  *
    420  * @param {vec3} out the receiving vector
    421  * @param {vec3} a the first operand
    422  * @param {vec3} b the second operand
    423  * @param {vec3} c the third operand
    424  * @param {vec3} d the fourth operand
    425  * @param {Number} t interpolation amount between the two inputs
    426  * @returns {vec3} out
    427  */
    428 vec3.hermite = function (out, a, b, c, d, t) {
    429   var factorTimes2 = t * t,
    430       factor1 = factorTimes2 * (2 * t - 3) + 1,
    431       factor2 = factorTimes2 * (t - 2) + t,
    432       factor3 = factorTimes2 * (t - 1),
    433       factor4 = factorTimes2 * (3 - 2 * t);
    434 
    435   out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
    436   out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
    437   out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
    438 
    439   return out;
    440 };
    441 
    442 /**
    443  * Performs a bezier interpolation with two control points
    444  *
    445  * @param {vec3} out the receiving vector
    446  * @param {vec3} a the first operand
    447  * @param {vec3} b the second operand
    448  * @param {vec3} c the third operand
    449  * @param {vec3} d the fourth operand
    450  * @param {Number} t interpolation amount between the two inputs
    451  * @returns {vec3} out
    452  */
    453 vec3.bezier = function (out, a, b, c, d, t) {
    454   var inverseFactor = 1 - t,
    455       inverseFactorTimesTwo = inverseFactor * inverseFactor,
    456       factorTimes2 = t * t,
    457       factor1 = inverseFactorTimesTwo * inverseFactor,
    458       factor2 = 3 * t * inverseFactorTimesTwo,
    459       factor3 = 3 * factorTimes2 * inverseFactor,
    460       factor4 = factorTimes2 * t;
    461 
    462   out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;
    463   out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;
    464   out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;
    465 
    466   return out;
    467 };
    468 
    469 /**
    470  * Generates a random vector with the given scale
    471  *
    472  * @param {vec3} out the receiving vector
    473  * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned
    474  * @returns {vec3} out
    475  */
    476 vec3.random = function (out, scale) {
    477     scale = scale || 1.0;
    478 
    479     var r = glMatrix.RANDOM() * 2.0 * Math.PI;
    480     var z = (glMatrix.RANDOM() * 2.0) - 1.0;
    481     var zScale = Math.sqrt(1.0-z*z) * scale;
    482 
    483     out[0] = Math.cos(r) * zScale;
    484     out[1] = Math.sin(r) * zScale;
    485     out[2] = z * scale;
    486     return out;
    487 };
    488 
    489 /**
    490  * Transforms the vec3 with a mat4.
    491  * 4th vector component is implicitly '1'
    492  *
    493  * @param {vec3} out the receiving vector
    494  * @param {vec3} a the vector to transform
    495  * @param {mat4} m matrix to transform with
    496  * @returns {vec3} out
    497  */
    498 vec3.transformMat4 = function(out, a, m) {
    499     var x = a[0], y = a[1], z = a[2],
    500         w = m[3] * x + m[7] * y + m[11] * z + m[15];
    501     w = w || 1.0;
    502     out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
    503     out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
    504     out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
    505     return out;
    506 };
    507 
    508 /**
    509  * Transforms the vec3 with a mat3.
    510  *
    511  * @param {vec3} out the receiving vector
    512  * @param {vec3} a the vector to transform
    513  * @param {mat4} m the 3x3 matrix to transform with
    514  * @returns {vec3} out
    515  */
    516 vec3.transformMat3 = function(out, a, m) {
    517     var x = a[0], y = a[1], z = a[2];
    518     out[0] = x * m[0] + y * m[3] + z * m[6];
    519     out[1] = x * m[1] + y * m[4] + z * m[7];
    520     out[2] = x * m[2] + y * m[5] + z * m[8];
    521     return out;
    522 };
    523 
    524 /**
    525  * Transforms the vec3 with a quat
    526  *
    527  * @param {vec3} out the receiving vector
    528  * @param {vec3} a the vector to transform
    529  * @param {quat} q quaternion to transform with
    530  * @returns {vec3} out
    531  */
    532 vec3.transformQuat = function(out, a, q) {
    533     // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
    534 
    535     var x = a[0], y = a[1], z = a[2],
    536         qx = q[0], qy = q[1], qz = q[2], qw = q[3],
    537 
    538         // calculate quat * vec
    539         ix = qw * x + qy * z - qz * y,
    540         iy = qw * y + qz * x - qx * z,
    541         iz = qw * z + qx * y - qy * x,
    542         iw = -qx * x - qy * y - qz * z;
    543 
    544     // calculate result * inverse quat
    545     out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
    546     out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
    547     out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
    548     return out;
    549 };
    550 
    551 /**
    552  * Rotate a 3D vector around the x-axis
    553  * @param {vec3} out The receiving vec3
    554  * @param {vec3} a The vec3 point to rotate
    555  * @param {vec3} b The origin of the rotation
    556  * @param {Number} c The angle of rotation
    557  * @returns {vec3} out
    558  */
    559 vec3.rotateX = function(out, a, b, c){
    560    var p = [], r=[];
    561 	  //Translate point to the origin
    562 	  p[0] = a[0] - b[0];
    563 	  p[1] = a[1] - b[1];
    564   	p[2] = a[2] - b[2];
    565 
    566 	  //perform rotation
    567 	  r[0] = p[0];
    568 	  r[1] = p[1]*Math.cos(c) - p[2]*Math.sin(c);
    569 	  r[2] = p[1]*Math.sin(c) + p[2]*Math.cos(c);
    570 
    571 	  //translate to correct position
    572 	  out[0] = r[0] + b[0];
    573 	  out[1] = r[1] + b[1];
    574 	  out[2] = r[2] + b[2];
    575 
    576   	return out;
    577 };
    578 
    579 /**
    580  * Rotate a 3D vector around the y-axis
    581  * @param {vec3} out The receiving vec3
    582  * @param {vec3} a The vec3 point to rotate
    583  * @param {vec3} b The origin of the rotation
    584  * @param {Number} c The angle of rotation
    585  * @returns {vec3} out
    586  */
    587 vec3.rotateY = function(out, a, b, c){
    588   	var p = [], r=[];
    589   	//Translate point to the origin
    590   	p[0] = a[0] - b[0];
    591   	p[1] = a[1] - b[1];
    592   	p[2] = a[2] - b[2];
    593 
    594   	//perform rotation
    595   	r[0] = p[2]*Math.sin(c) + p[0]*Math.cos(c);
    596   	r[1] = p[1];
    597   	r[2] = p[2]*Math.cos(c) - p[0]*Math.sin(c);
    598 
    599   	//translate to correct position
    600   	out[0] = r[0] + b[0];
    601   	out[1] = r[1] + b[1];
    602   	out[2] = r[2] + b[2];
    603 
    604   	return out;
    605 };
    606 
    607 /**
    608  * Rotate a 3D vector around the z-axis
    609  * @param {vec3} out The receiving vec3
    610  * @param {vec3} a The vec3 point to rotate
    611  * @param {vec3} b The origin of the rotation
    612  * @param {Number} c The angle of rotation
    613  * @returns {vec3} out
    614  */
    615 vec3.rotateZ = function(out, a, b, c){
    616   	var p = [], r=[];
    617   	//Translate point to the origin
    618   	p[0] = a[0] - b[0];
    619   	p[1] = a[1] - b[1];
    620   	p[2] = a[2] - b[2];
    621 
    622   	//perform rotation
    623   	r[0] = p[0]*Math.cos(c) - p[1]*Math.sin(c);
    624   	r[1] = p[0]*Math.sin(c) + p[1]*Math.cos(c);
    625   	r[2] = p[2];
    626 
    627   	//translate to correct position
    628   	out[0] = r[0] + b[0];
    629   	out[1] = r[1] + b[1];
    630   	out[2] = r[2] + b[2];
    631 
    632   	return out;
    633 };
    634 
    635 /**
    636  * Perform some operation over an array of vec3s.
    637  *
    638  * @param {Array} a the array of vectors to iterate over
    639  * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
    640  * @param {Number} offset Number of elements to skip at the beginning of the array
    641  * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
    642  * @param {Function} fn Function to call for each vector in the array
    643  * @param {Object} [arg] additional argument to pass to fn
    644  * @returns {Array} a
    645  * @function
    646  */
    647 vec3.forEach = (function() {
    648     var vec = vec3.create();
    649 
    650     return function(a, stride, offset, count, fn, arg) {
    651         var i, l;
    652         if(!stride) {
    653             stride = 3;
    654         }
    655 
    656         if(!offset) {
    657             offset = 0;
    658         }
    659 
    660         if(count) {
    661             l = Math.min((count * stride) + offset, a.length);
    662         } else {
    663             l = a.length;
    664         }
    665 
    666         for(i = offset; i < l; i += stride) {
    667             vec[0] = a[i]; vec[1] = a[i+1]; vec[2] = a[i+2];
    668             fn(vec, vec, arg);
    669             a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
    670         }
    671 
    672         return a;
    673     };
    674 })();
    675 
    676 /**
    677  * Get the angle between two 3D vectors
    678  * @param {vec3} a The first operand
    679  * @param {vec3} b The second operand
    680  * @returns {Number} The angle in radians
    681  */
    682 vec3.angle = function(a, b) {
    683 
    684     var tempA = vec3.fromValues(a[0], a[1], a[2]);
    685     var tempB = vec3.fromValues(b[0], b[1], b[2]);
    686 
    687     vec3.normalize(tempA, tempA);
    688     vec3.normalize(tempB, tempB);
    689 
    690     var cosine = vec3.dot(tempA, tempB);
    691 
    692     if(cosine > 1.0){
    693         return 0;
    694     } else {
    695         return Math.acos(cosine);
    696     }
    697 };
    698 
    699 /**
    700  * Returns a string representation of a vector
    701  *
    702  * @param {vec3} vec vector to represent as a string
    703  * @returns {String} string representation of the vector
    704  */
    705 vec3.str = function (a) {
    706     return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
    707 };
    708 
    709 module.exports = vec3;
    710