1 /*
2  * Copyright (c), Recep Aslantas.
3  *
4  * MIT License (MIT), http://opensource.org/licenses/MIT
5  * Full license can be found in the LICENSE file
6  */
7 
8 /*
9  Macros:
10    GLM_VEC2_ONE_INIT
11    GLM_VEC2_ZERO_INIT
12    GLM_VEC2_ONE
13    GLM_VEC2_ZERO
14 
15  Functions:
16    CGLM_INLINE void  glm_vec2(float * __restrict v, vec2 dest)
17    CGLM_INLINE void  glm_vec2_copy(vec2 a, vec2 dest)
18    CGLM_INLINE void  glm_vec2_zero(vec2 v)
19    CGLM_INLINE void  glm_vec2_one(vec2 v)
20    CGLM_INLINE float glm_vec2_dot(vec2 a, vec2 b)
21    CGLM_INLINE float glm_vec2_cross(vec2 a, vec2 b)
22    CGLM_INLINE float glm_vec2_norm2(vec2 v)
23    CGLM_INLINE float glm_vec2_norm(vec2 vec)
24    CGLM_INLINE void  glm_vec2_add(vec2 a, vec2 b, vec2 dest)
25    CGLM_INLINE void  glm_vec2_adds(vec2 v, float s, vec2 dest)
26    CGLM_INLINE void  glm_vec2_sub(vec2 a, vec2 b, vec2 dest)
27    CGLM_INLINE void  glm_vec2_subs(vec2 v, float s, vec2 dest)
28    CGLM_INLINE void  glm_vec2_mul(vec2 a, vec2 b, vec2 d)
29    CGLM_INLINE void  glm_vec2_scale(vec2 v, float s, vec2 dest)
30    CGLM_INLINE void  glm_vec2_scale_as(vec2 v, float s, vec2 dest)
31    CGLM_INLINE void  glm_vec2_div(vec2 a, vec2 b, vec2 dest)
32    CGLM_INLINE void  glm_vec2_divs(vec2 v, float s, vec2 dest)
33    CGLM_INLINE void  glm_vec2_addadd(vec2 a, vec2 b, vec2 dest)
34    CGLM_INLINE void  glm_vec2_subadd(vec2 a, vec2 b, vec2 dest)
35    CGLM_INLINE void  glm_vec2_muladd(vec2 a, vec2 b, vec2 dest)
36    CGLM_INLINE void  glm_vec2_muladds(vec2 a, float s, vec2 dest)
37    CGLM_INLINE void  glm_vec2_maxadd(vec2 a, vec2 b, vec2 dest)
38    CGLM_INLINE void  glm_vec2_minadd(vec2 a, vec2 b, vec2 dest)
39    CGLM_INLINE void  glm_vec2_negate_to(vec2 v, vec2 dest)
40    CGLM_INLINE void  glm_vec2_negate(vec2 v)
41    CGLM_INLINE void  glm_vec2_normalize(vec2 v)
42    CGLM_INLINE void  glm_vec2_normalize_to(vec2 vec, vec2 dest)
43    CGLM_INLINE void  glm_vec2_rotate(vec2 v, float angle, vec2 dest)
44    CGLM_INLINE float glm_vec2_distance2(vec2 a, vec2 b)
45    CGLM_INLINE float glm_vec2_distance(vec2 a, vec2 b)
46    CGLM_INLINE void  glm_vec2_maxv(vec2 v1, vec2 v2, vec2 dest)
47    CGLM_INLINE void  glm_vec2_minv(vec2 v1, vec2 v2, vec2 dest)
48    CGLM_INLINE void  glm_vec2_clamp(vec2 v, float minVal, float maxVal)
49    CGLM_INLINE void  glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest)
50 
51  */
52 
53 #ifndef cglm_vec2_h
54 #define cglm_vec2_h
55 
56 #include "common.h"
57 #include "util.h"
58 #include "vec2-ext.h"
59 
60 #define GLM_VEC2_ONE_INIT   {1.0f, 1.0f}
61 #define GLM_VEC2_ZERO_INIT  {0.0f, 0.0f}
62 
63 #define GLM_VEC2_ONE  ((vec2)GLM_VEC2_ONE_INIT)
64 #define GLM_VEC2_ZERO ((vec2)GLM_VEC2_ZERO_INIT)
65 
66 /*!
67  * @brief init vec2 using another vector
68  *
69  * @param[in]  v    a vector
70  * @param[out] dest destination
71  */
72 CGLM_INLINE
73 void
glm_vec2(float * __restrict v,vec2 dest)74 glm_vec2(float * __restrict v, vec2 dest) {
75   dest[0] = v[0];
76   dest[1] = v[1];
77 }
78 
79 /*!
80  * @brief copy all members of [a] to [dest]
81  *
82  * @param[in]  a    source
83  * @param[out] dest destination
84  */
85 CGLM_INLINE
86 void
glm_vec2_copy(vec2 a,vec2 dest)87 glm_vec2_copy(vec2 a, vec2 dest) {
88   dest[0] = a[0];
89   dest[1] = a[1];
90 }
91 
92 /*!
93  * @brief make vector zero
94  *
95  * @param[in, out]  v vector
96  */
97 CGLM_INLINE
98 void
glm_vec2_zero(vec2 v)99 glm_vec2_zero(vec2 v) {
100   v[0] = v[1] = 0.0f;
101 }
102 
103 /*!
104  * @brief make vector one
105  *
106  * @param[in, out]  v vector
107  */
108 CGLM_INLINE
109 void
glm_vec2_one(vec2 v)110 glm_vec2_one(vec2 v) {
111   v[0] = v[1] = 1.0f;
112 }
113 
114 /*!
115  * @brief vec2 dot product
116  *
117  * @param[in] a vector1
118  * @param[in] b vector2
119  *
120  * @return dot product
121  */
122 CGLM_INLINE
123 float
glm_vec2_dot(vec2 a,vec2 b)124 glm_vec2_dot(vec2 a, vec2 b) {
125   return a[0] * b[0] + a[1] * b[1];
126 }
127 
128 /*!
129  * @brief vec2 cross product
130  *
131  * REF: http://allenchou.net/2013/07/cross-product-of-2d-vectors/
132  *
133  * @param[in]  a vector1
134  * @param[in]  b vector2
135  *
136  * @return Z component of cross product
137  */
138 CGLM_INLINE
139 float
glm_vec2_cross(vec2 a,vec2 b)140 glm_vec2_cross(vec2 a, vec2 b) {
141   /* just calculate the z-component */
142   return a[0] * b[1] - a[1] * b[0];
143 }
144 
145 /*!
146  * @brief norm * norm (magnitude) of vec
147  *
148  * we can use this func instead of calling norm * norm, because it would call
149  * sqrtf fuction twice but with this func we can avoid func call, maybe this is
150  * not good name for this func
151  *
152  * @param[in] v vector
153  *
154  * @return norm * norm
155  */
156 CGLM_INLINE
157 float
glm_vec2_norm2(vec2 v)158 glm_vec2_norm2(vec2 v) {
159   return glm_vec2_dot(v, v);
160 }
161 
162 /*!
163  * @brief norm (magnitude) of vec2
164  *
165  * @param[in] vec vector
166  *
167  * @return norm
168  */
169 CGLM_INLINE
170 float
glm_vec2_norm(vec2 vec)171 glm_vec2_norm(vec2 vec) {
172   return sqrtf(glm_vec2_norm2(vec));
173 }
174 
175 /*!
176  * @brief add a vector to b vector store result in dest
177  *
178  * @param[in]  a    vector1
179  * @param[in]  b    vector2
180  * @param[out] dest destination vector
181  */
182 CGLM_INLINE
183 void
glm_vec2_add(vec2 a,vec2 b,vec2 dest)184 glm_vec2_add(vec2 a, vec2 b, vec2 dest) {
185   dest[0] = a[0] + b[0];
186   dest[1] = a[1] + b[1];
187 }
188 
189 /*!
190  * @brief add scalar to v vector store result in dest (d = v + s)
191  *
192  * @param[in]  v    vector
193  * @param[in]  s    scalar
194  * @param[out] dest destination vector
195  */
196 CGLM_INLINE
197 void
glm_vec2_adds(vec2 v,float s,vec2 dest)198 glm_vec2_adds(vec2 v, float s, vec2 dest) {
199   dest[0] = v[0] + s;
200   dest[1] = v[1] + s;
201 }
202 
203 /*!
204  * @brief subtract b vector from a vector store result in dest
205  *
206  * @param[in]  a    vector1
207  * @param[in]  b    vector2
208  * @param[out] dest destination vector
209  */
210 CGLM_INLINE
211 void
glm_vec2_sub(vec2 a,vec2 b,vec2 dest)212 glm_vec2_sub(vec2 a, vec2 b, vec2 dest) {
213   dest[0] = a[0] - b[0];
214   dest[1] = a[1] - b[1];
215 }
216 
217 /*!
218  * @brief subtract scalar from v vector store result in dest (d = v - s)
219  *
220  * @param[in]  v    vector
221  * @param[in]  s    scalar
222  * @param[out] dest destination vector
223  */
224 CGLM_INLINE
225 void
glm_vec2_subs(vec2 v,float s,vec2 dest)226 glm_vec2_subs(vec2 v, float s, vec2 dest) {
227   dest[0] = v[0] - s;
228   dest[1] = v[1] - s;
229 }
230 
231 /*!
232  * @brief multiply two vector (component-wise multiplication)
233  *
234  * @param a    v1
235  * @param b    v2
236  * @param dest v3 = (a[0] * b[0], a[1] * b[1])
237  */
238 CGLM_INLINE
239 void
glm_vec2_mul(vec2 a,vec2 b,vec2 dest)240 glm_vec2_mul(vec2 a, vec2 b, vec2 dest) {
241   dest[0] = a[0] * b[0];
242   dest[1] = a[1] * b[1];
243 }
244 
245 /*!
246  * @brief multiply/scale vector with scalar: result = v * s
247  *
248  * @param[in]  v    vector
249  * @param[in]  s    scalar
250  * @param[out] dest destination vector
251  */
252 CGLM_INLINE
253 void
glm_vec2_scale(vec2 v,float s,vec2 dest)254 glm_vec2_scale(vec2 v, float s, vec2 dest) {
255   dest[0] = v[0] * s;
256   dest[1] = v[1] * s;
257 }
258 
259 /*!
260  * @brief scale as vector specified: result = unit(v) * s
261  *
262  * @param[in]  v    vector
263  * @param[in]  s    scalar
264  * @param[out] dest destination vector
265  */
266 CGLM_INLINE
267 void
glm_vec2_scale_as(vec2 v,float s,vec2 dest)268 glm_vec2_scale_as(vec2 v, float s, vec2 dest) {
269   float norm;
270   norm = glm_vec2_norm(v);
271 
272   if (norm == 0.0f) {
273     glm_vec2_zero(dest);
274     return;
275   }
276 
277   glm_vec2_scale(v, s / norm, dest);
278 }
279 
280 /*!
281  * @brief div vector with another component-wise division: d = a / b
282  *
283  * @param[in]  a    vector 1
284  * @param[in]  b    vector 2
285  * @param[out] dest result = (a[0]/b[0], a[1]/b[1])
286  */
287 CGLM_INLINE
288 void
glm_vec2_div(vec2 a,vec2 b,vec2 dest)289 glm_vec2_div(vec2 a, vec2 b, vec2 dest) {
290   dest[0] = a[0] / b[0];
291   dest[1] = a[1] / b[1];
292 }
293 
294 /*!
295  * @brief div vector with scalar: d = v / s
296  *
297  * @param[in]  v    vector
298  * @param[in]  s    scalar
299  * @param[out] dest result = (a[0]/s, a[1]/s)
300  */
301 CGLM_INLINE
302 void
glm_vec2_divs(vec2 v,float s,vec2 dest)303 glm_vec2_divs(vec2 v, float s, vec2 dest) {
304   dest[0] = v[0] / s;
305   dest[1] = v[1] / s;
306 }
307 
308 /*!
309  * @brief add two vectors and add result to sum
310  *
311  * it applies += operator so dest must be initialized
312  *
313  * @param[in]  a    vector 1
314  * @param[in]  b    vector 2
315  * @param[out] dest dest += (a + b)
316  */
317 CGLM_INLINE
318 void
glm_vec2_addadd(vec2 a,vec2 b,vec2 dest)319 glm_vec2_addadd(vec2 a, vec2 b, vec2 dest) {
320   dest[0] += a[0] + b[0];
321   dest[1] += a[1] + b[1];
322 }
323 
324 /*!
325  * @brief sub two vectors and add result to dest
326  *
327  * it applies += operator so dest must be initialized
328  *
329  * @param[in]  a    vector 1
330  * @param[in]  b    vector 2
331  * @param[out] dest dest += (a + b)
332  */
333 CGLM_INLINE
334 void
glm_vec2_subadd(vec2 a,vec2 b,vec2 dest)335 glm_vec2_subadd(vec2 a, vec2 b, vec2 dest) {
336   dest[0] += a[0] - b[0];
337   dest[1] += a[1] - b[1];
338 }
339 
340 /*!
341  * @brief mul two vectors and add result to dest
342  *
343  * it applies += operator so dest must be initialized
344  *
345  * @param[in]  a    vector 1
346  * @param[in]  b    vector 2
347  * @param[out] dest dest += (a * b)
348  */
349 CGLM_INLINE
350 void
glm_vec2_muladd(vec2 a,vec2 b,vec2 dest)351 glm_vec2_muladd(vec2 a, vec2 b, vec2 dest) {
352   dest[0] += a[0] * b[0];
353   dest[1] += a[1] * b[1];
354 }
355 
356 /*!
357  * @brief mul vector with scalar and add result to sum
358  *
359  * it applies += operator so dest must be initialized
360  *
361  * @param[in]  a    vector
362  * @param[in]  s    scalar
363  * @param[out] dest dest += (a * b)
364  */
365 CGLM_INLINE
366 void
glm_vec2_muladds(vec2 a,float s,vec2 dest)367 glm_vec2_muladds(vec2 a, float s, vec2 dest) {
368   dest[0] += a[0] * s;
369   dest[1] += a[1] * s;
370 }
371 
372 /*!
373  * @brief add max of two vector to result/dest
374  *
375  * it applies += operator so dest must be initialized
376  *
377  * @param[in]  a    vector 1
378  * @param[in]  b    vector 2
379  * @param[out] dest dest += max(a, b)
380  */
381 CGLM_INLINE
382 void
glm_vec2_maxadd(vec2 a,vec2 b,vec2 dest)383 glm_vec2_maxadd(vec2 a, vec2 b, vec2 dest) {
384   dest[0] += glm_max(a[0], b[0]);
385   dest[1] += glm_max(a[1], b[1]);
386 }
387 
388 /*!
389  * @brief add min of two vector to result/dest
390  *
391  * it applies += operator so dest must be initialized
392  *
393  * @param[in]  a    vector 1
394  * @param[in]  b    vector 2
395  * @param[out] dest dest += min(a, b)
396  */
397 CGLM_INLINE
398 void
glm_vec2_minadd(vec2 a,vec2 b,vec2 dest)399 glm_vec2_minadd(vec2 a, vec2 b, vec2 dest) {
400   dest[0] += glm_min(a[0], b[0]);
401   dest[1] += glm_min(a[1], b[1]);
402 }
403 
404 /*!
405  * @brief negate vector components and store result in dest
406  *
407  * @param[in]   v     vector
408  * @param[out]  dest  result vector
409  */
410 CGLM_INLINE
411 void
glm_vec2_negate_to(vec2 v,vec2 dest)412 glm_vec2_negate_to(vec2 v, vec2 dest) {
413   dest[0] = -v[0];
414   dest[1] = -v[1];
415 }
416 
417 /*!
418  * @brief negate vector components
419  *
420  * @param[in, out]  v  vector
421  */
422 CGLM_INLINE
423 void
glm_vec2_negate(vec2 v)424 glm_vec2_negate(vec2 v) {
425   glm_vec2_negate_to(v, v);
426 }
427 
428 /*!
429  * @brief normalize vector and store result in same vec
430  *
431  * @param[in, out] v vector
432  */
433 CGLM_INLINE
434 void
glm_vec2_normalize(vec2 v)435 glm_vec2_normalize(vec2 v) {
436   float norm;
437 
438   norm = glm_vec2_norm(v);
439 
440   if (norm == 0.0f) {
441     v[0] = v[1] = 0.0f;
442     return;
443   }
444 
445   glm_vec2_scale(v, 1.0f / norm, v);
446 }
447 
448 /*!
449  * @brief normalize vector to dest
450  *
451  * @param[in]  v    source
452  * @param[out] dest destination
453  */
454 CGLM_INLINE
455 void
glm_vec2_normalize_to(vec2 v,vec2 dest)456 glm_vec2_normalize_to(vec2 v, vec2 dest) {
457   float norm;
458 
459   norm = glm_vec2_norm(v);
460 
461   if (norm == 0.0f) {
462     glm_vec2_zero(dest);
463     return;
464   }
465 
466   glm_vec2_scale(v, 1.0f / norm, dest);
467 }
468 
469 /*!
470  * @brief rotate vec2 around origin by angle (CCW: counterclockwise)
471  *
472  * Formula:
473  *   ��2 = cos(a)��1 − sin(a)��1
474  *   ��2 = sin(a)��1 + cos(a)��1
475  *
476  * @param[in]  v     vector to rotate
477  * @param[in]  angle angle by radians
478  * @param[out] dest  destination vector
479  */
480 CGLM_INLINE
481 void
glm_vec2_rotate(vec2 v,float angle,vec2 dest)482 glm_vec2_rotate(vec2 v, float angle, vec2 dest) {
483   float c, s, x1, y1;
484 
485   c  = cosf(angle);
486   s  = sinf(angle);
487 
488   x1 = v[0];
489   y1 = v[1];
490 
491   dest[0] = c * x1 - s * y1;
492   dest[1] = s * x1 + c * y1;
493 }
494 
495 /**
496  * @brief squared distance between two vectors
497  *
498  * @param[in] a vector1
499  * @param[in] b vector2
500  * @return returns squared distance (distance * distance)
501  */
502 CGLM_INLINE
503 float
glm_vec2_distance2(vec2 a,vec2 b)504 glm_vec2_distance2(vec2 a, vec2 b) {
505   return glm_pow2(b[0] - a[0]) + glm_pow2(b[1] - a[1]);
506 }
507 
508 /**
509  * @brief distance between two vectors
510  *
511  * @param[in] a vector1
512  * @param[in] b vector2
513  * @return returns distance
514  */
515 CGLM_INLINE
516 float
glm_vec2_distance(vec2 a,vec2 b)517 glm_vec2_distance(vec2 a, vec2 b) {
518   return sqrtf(glm_vec2_distance2(a, b));
519 }
520 
521 /*!
522  * @brief max values of vectors
523  *
524  * @param[in]  a    vector1
525  * @param[in]  b    vector2
526  * @param[out] dest destination
527  */
528 CGLM_INLINE
529 void
glm_vec2_maxv(vec2 a,vec2 b,vec2 dest)530 glm_vec2_maxv(vec2 a, vec2 b, vec2 dest) {
531   dest[0] = glm_max(a[0], b[0]);
532   dest[1] = glm_max(a[1], b[1]);
533 }
534 
535 /*!
536  * @brief min values of vectors
537  *
538  * @param[in]  a    vector1
539  * @param[in]  b    vector2
540  * @param[out] dest destination
541  */
542 CGLM_INLINE
543 void
glm_vec2_minv(vec2 a,vec2 b,vec2 dest)544 glm_vec2_minv(vec2 a, vec2 b, vec2 dest) {
545   dest[0] = glm_min(a[0], b[0]);
546   dest[1] = glm_min(a[1], b[1]);
547 }
548 
549 /*!
550  * @brief clamp vector's individual members between min and max values
551  *
552  * @param[in, out]  v      vector
553  * @param[in]       minval minimum value
554  * @param[in]       maxval maximum value
555  */
556 CGLM_INLINE
557 void
glm_vec2_clamp(vec2 v,float minval,float maxval)558 glm_vec2_clamp(vec2 v, float minval, float maxval) {
559   v[0] = glm_clamp(v[0], minval, maxval);
560   v[1] = glm_clamp(v[1], minval, maxval);
561 }
562 
563 /*!
564  * @brief linear interpolation between two vector
565  *
566  * formula:  from + s * (to - from)
567  *
568  * @param[in]   from from value
569  * @param[in]   to   to value
570  * @param[in]   t    interpolant (amount) clamped between 0 and 1
571  * @param[out]  dest destination
572  */
573 CGLM_INLINE
574 void
glm_vec2_lerp(vec2 from,vec2 to,float t,vec2 dest)575 glm_vec2_lerp(vec2 from, vec2 to, float t, vec2 dest) {
576   vec2 s, v;
577 
578   /* from + s * (to - from) */
579   glm_vec2_fill(s, glm_clamp_zo(t));
580   glm_vec2_sub(to, from, v);
581   glm_vec2_mul(s, v, v);
582   glm_vec2_add(from, v, dest);
583 }
584 
585 #endif /* cglm_vec2_h */
586