• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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