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