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 3 Dimensional Vector
25 * @name vec3
26 */
27var vec3 = {};
28
29/**
30 * Creates a new, empty vec3
31 *
32 * @returns {vec3} a new 3D vector
33 */
34vec3.create = function() {
35    var out = new GLMAT_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 */
48vec3.clone = function(a) {
49    var out = new GLMAT_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 */
64vec3.fromValues = function(x, y, z) {
65    var out = new GLMAT_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 */
79vec3.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 */
95vec3.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 */
110vec3.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 two vec3's
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 */
125vec3.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 */
136vec3.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 */
146vec3.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 */
157vec3.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 */
167vec3.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 */
178vec3.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 */
188vec3.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 */
203vec3.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 */
218vec3.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 * Calculates the euclidian distance between two vec3's
227 *
228 * @param {vec3} a the first operand
229 * @param {vec3} b the second operand
230 * @returns {Number} distance between a and b
231 */
232vec3.distance = function(a, b) {
233    var x = b[0] - a[0],
234        y = b[1] - a[1],
235        z = b[2] - a[2];
236    return Math.sqrt(x*x + y*y + z*z);
237};
238
239/**
240 * Alias for {@link vec3.distance}
241 * @function
242 */
243vec3.dist = vec3.distance;
244
245/**
246 * Calculates the squared euclidian distance between two vec3's
247 *
248 * @param {vec3} a the first operand
249 * @param {vec3} b the second operand
250 * @returns {Number} squared distance between a and b
251 */
252vec3.squaredDistance = function(a, b) {
253    var x = b[0] - a[0],
254        y = b[1] - a[1],
255        z = b[2] - a[2];
256    return x*x + y*y + z*z;
257};
258
259/**
260 * Alias for {@link vec3.squaredDistance}
261 * @function
262 */
263vec3.sqrDist = vec3.squaredDistance;
264
265/**
266 * Calculates the length of a vec3
267 *
268 * @param {vec3} a vector to calculate length of
269 * @returns {Number} length of a
270 */
271vec3.length = function (a) {
272    var x = a[0],
273        y = a[1],
274        z = a[2];
275    return Math.sqrt(x*x + y*y + z*z);
276};
277
278/**
279 * Alias for {@link vec3.length}
280 * @function
281 */
282vec3.len = vec3.length;
283
284/**
285 * Calculates the squared length of a vec3
286 *
287 * @param {vec3} a vector to calculate squared length of
288 * @returns {Number} squared length of a
289 */
290vec3.squaredLength = function (a) {
291    var x = a[0],
292        y = a[1],
293        z = a[2];
294    return x*x + y*y + z*z;
295};
296
297/**
298 * Alias for {@link vec3.squaredLength}
299 * @function
300 */
301vec3.sqrLen = vec3.squaredLength;
302
303/**
304 * Negates the components of a vec3
305 *
306 * @param {vec3} out the receiving vector
307 * @param {vec3} a vector to negate
308 * @returns {vec3} out
309 */
310vec3.negate = function(out, a) {
311    out[0] = -a[0];
312    out[1] = -a[1];
313    out[2] = -a[2];
314    return out;
315};
316
317/**
318 * Normalize a vec3
319 *
320 * @param {vec3} out the receiving vector
321 * @param {vec3} a vector to normalize
322 * @returns {vec3} out
323 */
324vec3.normalize = function(out, a) {
325    var x = a[0],
326        y = a[1],
327        z = a[2];
328    var len = x*x + y*y + z*z;
329    if (len > 0) {
330        //TODO: evaluate use of glm_invsqrt here?
331        len = 1 / Math.sqrt(len);
332        out[0] = a[0] * len;
333        out[1] = a[1] * len;
334        out[2] = a[2] * len;
335    }
336    return out;
337};
338
339/**
340 * Calculates the dot product of two vec3's
341 *
342 * @param {vec3} a the first operand
343 * @param {vec3} b the second operand
344 * @returns {Number} dot product of a and b
345 */
346vec3.dot = function (a, b) {
347    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
348};
349
350/**
351 * Computes the cross product of two vec3's
352 *
353 * @param {vec3} out the receiving vector
354 * @param {vec3} a the first operand
355 * @param {vec3} b the second operand
356 * @returns {vec3} out
357 */
358vec3.cross = function(out, a, b) {
359    var ax = a[0], ay = a[1], az = a[2],
360        bx = b[0], by = b[1], bz = b[2];
361
362    out[0] = ay * bz - az * by;
363    out[1] = az * bx - ax * bz;
364    out[2] = ax * by - ay * bx;
365    return out;
366};
367
368/**
369 * Performs a linear interpolation between two vec3's
370 *
371 * @param {vec3} out the receiving vector
372 * @param {vec3} a the first operand
373 * @param {vec3} b the second operand
374 * @param {Number} t interpolation amount between the two inputs
375 * @returns {vec3} out
376 */
377vec3.lerp = function (out, a, b, t) {
378    var ax = a[0],
379        ay = a[1],
380        az = a[2];
381    out[0] = ax + t * (b[0] - ax);
382    out[1] = ay + t * (b[1] - ay);
383    out[2] = az + t * (b[2] - az);
384    return out;
385};
386
387/**
388 * Transforms the vec3 with a mat4.
389 * 4th vector component is implicitly '1'
390 *
391 * @param {vec3} out the receiving vector
392 * @param {vec3} a the vector to transform
393 * @param {mat4} m matrix to transform with
394 * @returns {vec3} out
395 */
396vec3.transformMat4 = function(out, a, m) {
397    var x = a[0], y = a[1], z = a[2];
398    out[0] = m[0] * x + m[4] * y + m[8] * z + m[12];
399    out[1] = m[1] * x + m[5] * y + m[9] * z + m[13];
400    out[2] = m[2] * x + m[6] * y + m[10] * z + m[14];
401    return out;
402};
403
404/**
405 * Transforms the vec3 with a quat
406 *
407 * @param {vec3} out the receiving vector
408 * @param {vec3} a the vector to transform
409 * @param {quat} q quaternion to transform with
410 * @returns {vec3} out
411 */
412vec3.transformQuat = function(out, a, q) {
413    var x = a[0], y = a[1], z = a[2],
414        qx = q[0], qy = q[1], qz = q[2], qw = q[3],
415
416        // calculate quat * vec
417        ix = qw * x + qy * z - qz * y,
418        iy = qw * y + qz * x - qx * z,
419        iz = qw * z + qx * y - qy * x,
420        iw = -qx * x - qy * y - qz * z;
421
422    // calculate result * inverse quat
423    out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
424    out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
425    out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
426    return out;
427};
428
429/**
430 * Perform some operation over an array of vec3s.
431 *
432 * @param {Array} a the array of vectors to iterate over
433 * @param {Number} stride Number of elements between the start of each vec3. 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 vec3s 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 */
441vec3.forEach = (function() {
442    var vec = vec3.create();
443
444    return function(a, stride, offset, count, fn, arg) {
445        var i, l;
446        if(!stride) {
447            stride = 3;
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]; vec[2] = a[i+2];
462            fn(vec, vec, arg);
463            a[i] = vec[0]; a[i+1] = vec[1]; a[i+2] = vec[2];
464        }
465
466        return a;
467    };
468})();
469
470/**
471 * Returns a string representation of a vector
472 *
473 * @param {vec3} vec vector to represent as a string
474 * @returns {String} string representation of the vector
475 */
476vec3.str = function (a) {
477    return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')';
478};
479
480if(typeof(exports) !== 'undefined') {
481    exports.vec3 = vec3;
482}
483