audio rework pt 1
[vg.git] / src / vg / vg_m.h
1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
2
3 #ifndef VG_M_H
4 #define VG_M_H
5
6 #include "vg_platform.h"
7 #include <math.h>
8 #include <stdlib.h>
9
10 #define VG_PIf 3.14159265358979323846264338327950288f
11 #define VG_TAUf 6.28318530717958647692528676655900576f
12
13 static inline float vg_minf( float a, float b )
14 {
15 return a < b? a: b;
16 }
17
18 static inline float vg_maxf( float a, float b )
19 {
20 return a > b? a: b;
21 }
22
23 static inline float vg_clampf( float a, float min, float max )
24 {
25 return vg_minf( max, vg_maxf( a, min ) );
26 }
27
28 static inline float vg_signf( float a )
29 {
30 return a < 0.0f? -1.0f: 1.0f;
31 }
32
33 static inline float vg_fractf( float a )
34 {
35 return a - floorf( a );
36 }
37
38 static float stable_force( float current, float diff )
39 {
40 float fnew = current + diff;
41
42 if( fnew * current < 0.0f )
43 return 0.0f;
44
45 return fnew;
46 }
47
48 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
49 #define VG_MAX( A, B ) ((A)>(B)?(A):(B))
50
51 static inline int vg_min( int a, int b )
52 {
53 return a < b? a: b;
54 }
55
56 static inline int vg_max( int a, int b )
57 {
58 return a > b? a: b;
59 }
60
61 static inline float vg_rad( float deg )
62 {
63 return deg * VG_PIf / 180.0f;
64 }
65
66 /*
67 * Vector 3
68 */
69 static inline void v2_copy( v2f a, v2f b )
70 {
71 b[0] = a[0]; b[1] = a[1];
72 }
73
74 static inline void v2_zero( v2f a )
75 {
76 a[0] = 0.f; a[1] = 0.f;
77 }
78
79 static inline void v2i_copy( v2i a, v2i b )
80 {
81 b[0] = a[0]; b[1] = a[1];
82 }
83
84 static inline int v2i_eq( v2i a, v2i b )
85 {
86 return ((a[0] == b[0]) && (a[1] == b[1]));
87 }
88
89 static inline void v2i_add( v2i a, v2i b, v2i d )
90 {
91 d[0] = a[0]+b[0]; d[1] = a[1]+b[1];
92 }
93
94 static inline void v2i_sub( v2i a, v2i b, v2i d )
95 {
96 d[0] = a[0]-b[0]; d[1] = a[1]-b[1];
97 }
98
99 static inline void v2_minv( v2f a, v2f b, v2f dest )
100 {
101 dest[0] = vg_minf(a[0], b[0]);
102 dest[1] = vg_minf(a[1], b[1]);
103 }
104
105 static inline void v2_maxv( v2f a, v2f b, v2f dest )
106 {
107 dest[0] = vg_maxf(a[0], b[0]);
108 dest[1] = vg_maxf(a[1], b[1]);
109 }
110
111 static inline void v2_sub( v2f a, v2f b, v2f d )
112 {
113 d[0] = a[0]-b[0]; d[1] = a[1]-b[1];
114 }
115
116 static inline float v2_dot( v2f a, v2f b )
117 {
118 return a[0] * b[0] + a[1] * b[1];
119 }
120
121 static inline float v2_cross( v2f a, v2f b )
122 {
123 return a[0]*b[1] - a[1]*b[0];
124 }
125
126 static inline void v2_add( v2f a, v2f b, v2f d )
127 {
128 d[0] = a[0]+b[0]; d[1] = a[1]+b[1];
129 }
130
131 static inline void v2_muls( v2f a, float s, v2f d )
132 {
133 d[0] = a[0]*s; d[1] = a[1]*s;
134 }
135
136 static inline void v2_divs( v2f a, float s, v2f d )
137 {
138 d[0] = a[0]/s; d[1] = a[1]/s;
139 }
140
141 static inline void v2_mul( v2f a, v2f b, v2f d )
142 {
143 d[0] = a[0]*b[0];
144 d[1] = a[1]*b[1];
145 }
146
147 static inline void v2_div( v2f a, v2f b, v2f d )
148 {
149 d[0] = a[0]/b[0]; d[1] = a[1]/b[1];
150 }
151
152 static inline void v2_muladd( v2f a, v2f b, v2f s, v2f d )
153 {
154 d[0] = a[0]+b[0]*s[0];
155 d[1] = a[1]+b[1]*s[1];
156 }
157
158 static inline void v2_muladds( v2f a, v2f b, float s, v2f d )
159 {
160 d[0] = a[0]+b[0]*s;
161 d[1] = a[1]+b[1]*s;
162 }
163
164 static inline float v2_length2( v2f a )
165 {
166 return a[0]*a[0] + a[1]*a[1];
167 }
168
169 static inline float v2_length( v2f a )
170 {
171 return sqrtf( v2_length2( a ) );
172 }
173
174 static inline float v2_dist2( v2f a, v2f b )
175 {
176 v2f delta;
177 v2_sub( a, b, delta );
178 return v2_length2( delta );
179 }
180
181 static inline float v2_dist( v2f a, v2f b )
182 {
183 return sqrtf( v2_dist2( a, b ) );
184 }
185
186 static inline void v2_lerp( v2f a, v2f b, float t, v2f d )
187 {
188 d[0] = a[0] + t*(b[0]-a[0]);
189 d[1] = a[1] + t*(b[1]-a[1]);
190 }
191
192 static inline void v2_normalize( v2f a )
193 {
194 v2_muls( a, 1.f / v2_length( a ), a );
195 }
196
197 static inline void v2_floor( v2f a, v2f b )
198 {
199 b[0] = floorf( a[0] );
200 b[1] = floorf( a[1] );
201 }
202
203 /*
204 * Vector 3
205 */
206 static inline void v3_zero( v3f a )
207 {
208 a[0] = 0.f; a[1] = 0.f; a[2] = 0.f;
209 }
210
211 static inline void v3_copy( v3f a, v3f b )
212 {
213 b[0] = a[0]; b[1] = a[1]; b[2] = a[2];
214 }
215
216 static inline void v3_add( v3f a, v3f b, v3f d )
217 {
218 d[0] = a[0]+b[0]; d[1] = a[1]+b[1]; d[2] = a[2]+b[2];
219 }
220
221 static inline void v3_sub( v3f a, v3f b, v3f d )
222 {
223 d[0] = a[0]-b[0]; d[1] = a[1]-b[1]; d[2] = a[2]-b[2];
224 }
225
226 static inline void v3_mul( v3f a, v3f b, v3f d )
227 {
228 d[0] = a[0]*b[0]; d[1] = a[1]*b[1]; d[2] = a[2]*b[2];
229 }
230
231 static inline void v3_div( v3f a, v3f b, v3f d )
232 {
233 d[0] = a[0]/b[0]; d[1] = a[1]/b[1]; d[2] = a[2]/b[2];
234 }
235
236 static inline void v3_muls( v3f a, float s, v3f d )
237 {
238 d[0] = a[0]*s; d[1] = a[1]*s; d[2] = a[2]*s;
239 }
240
241 static inline void v3_divs( v3f a, float s, v3f d )
242 {
243 d[0] = a[0]/s; d[1] = a[1]/s; d[2] = a[2]/s;
244 }
245
246 static inline void v3_muladds( v3f a, v3f b, float s, v3f d )
247 {
248 d[0] = a[0]+b[0]*s; d[1] = a[1]+b[1]*s; d[2] = a[2]+b[2]*s;
249 }
250
251 static inline void v3_muladd( v2f a, v2f b, v2f s, v2f d )
252 {
253 d[0] = a[0]+b[0]*s[0];
254 d[1] = a[1]+b[1]*s[1];
255 d[2] = a[2]+b[2]*s[2];
256 }
257
258 static inline float v3_dot( v3f a, v3f b )
259 {
260 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
261 }
262
263 static inline void v3_cross( v3f a, v3f b, v3f dest )
264 {
265 v3f d;
266 d[0] = a[1]*b[2] - a[2]*b[1];
267 d[1] = a[2]*b[0] - a[0]*b[2];
268 d[2] = a[0]*b[1] - a[1]*b[0];
269 v3_copy( d, dest );
270 }
271
272 static inline float v3_length2( v3f a )
273 {
274 return v3_dot( a, a );
275 }
276
277 static inline float v3_length( v3f a )
278 {
279 return sqrtf( v3_length2( a ) );
280 }
281
282 static inline float v3_dist2( v3f a, v3f b )
283 {
284 v3f delta;
285 v3_sub( a, b, delta );
286 return v3_length2( delta );
287 }
288
289 static inline float v3_dist( v3f a, v3f b )
290 {
291 return sqrtf( v3_dist2( a, b ) );
292 }
293
294 static inline void v3_normalize( v3f a )
295 {
296 v3_muls( a, 1.f / v3_length( a ), a );
297 }
298
299 static inline float vg_lerpf( float a, float b, float t )
300 {
301 return a + t*(b-a);
302 }
303
304 static inline void v3_lerp( v3f a, v3f b, float t, v3f d )
305 {
306 d[0] = a[0] + t*(b[0]-a[0]);
307 d[1] = a[1] + t*(b[1]-a[1]);
308 d[2] = a[2] + t*(b[2]-a[2]);
309 }
310
311 static inline void v3_minv( v3f a, v3f b, v3f dest )
312 {
313 dest[0] = vg_minf(a[0], b[0]);
314 dest[1] = vg_minf(a[1], b[1]);
315 dest[2] = vg_minf(a[2], b[2]);
316 }
317
318 static inline void v3_maxv( v3f a, v3f b, v3f dest )
319 {
320 dest[0] = vg_maxf(a[0], b[0]);
321 dest[1] = vg_maxf(a[1], b[1]);
322 dest[2] = vg_maxf(a[2], b[2]);
323 }
324
325 static inline float v3_minf( v3f a )
326 {
327 return vg_minf( vg_minf( a[0], a[1] ), a[2] );
328 }
329
330 static inline float v3_maxf( v3f a )
331 {
332 return vg_maxf( vg_maxf( a[0], a[1] ), a[2] );
333 }
334
335 static inline void v3_fill( v3f a, float v )
336 {
337 a[0] = v;
338 a[1] = v;
339 a[2] = v;
340 }
341
342 static inline void v3_floor( v3f a, v3f b )
343 {
344 b[0] = floorf( a[0] );
345 b[1] = floorf( a[1] );
346 b[2] = floorf( a[2] );
347 }
348
349 static inline void v3_ceil( v3f a, v3f b )
350 {
351 b[0] = ceilf( a[0] );
352 b[1] = ceilf( a[1] );
353 b[2] = ceilf( a[2] );
354 }
355
356 static inline void v3_negate( v3f a, v3f b )
357 {
358 b[0] = -a[0];
359 b[1] = -a[1];
360 b[2] = -a[2];
361 }
362
363 static inline void v3_rotate( v3f v, float angle, v3f axis, v3f d )
364 {
365 v3f v1, v2, k;
366 float c, s;
367
368 c = cosf( angle );
369 s = sinf( angle );
370
371 v3_copy( axis, k );
372 v3_normalize( k );
373 v3_muls( v, c, v1 );
374 v3_cross( k, v, v2 );
375 v3_muls( v2, s, v2 );
376 v3_add( v1, v2, v1 );
377 v3_muls( k, v3_dot(k, v) * (1.0f - c), v2);
378 v3_add( v1, v2, d );
379 }
380
381 /*
382 * Vector 4
383 */
384 static inline void v4_copy( v4f a, v4f b )
385 {
386 b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; b[3] = a[3];
387 }
388
389 static inline void v4_zero( v4f a )
390 {
391 a[0] = 0.f; a[1] = 0.f; a[2] = 0.f; a[3] = 0.f;
392 }
393
394 static inline void v4_muls( v4f a, float s, v4f d )
395 {
396 d[0] = a[0]*s;
397 d[1] = a[1]*s;
398 d[2] = a[2]*s;
399 d[3] = a[3]*s;
400 }
401
402 static inline void v4_muladds( v4f a, v4f b, float s, v4f d )
403 {
404 d[0] = a[0]+b[0]*s;
405 d[1] = a[1]+b[1]*s;
406 d[2] = a[2]+b[2]*s;
407 d[3] = a[3]+b[3]*s;
408 }
409
410 static inline void v4_lerp( v4f a, v4f b, float t, v4f d )
411 {
412 d[0] = a[0] + t*(b[0]-a[0]);
413 d[1] = a[1] + t*(b[1]-a[1]);
414 d[2] = a[2] + t*(b[2]-a[2]);
415 d[3] = a[3] + t*(b[3]-a[3]);
416 }
417
418 static inline float v4_dot( v4f a, v4f b )
419 {
420 return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*a[3];
421 }
422
423 static inline float v4_length( v4f a )
424 {
425 return sqrtf( v4_dot(a,a) );
426 }
427
428 /*
429 * Matrix 2x2
430 */
431
432 #define M2X2_INDENTIY {{1.0f, 0.0f, }, \
433 { 0.0f, 1.0f, }}
434
435 #define M2X2_ZERO {{0.0f, 0.0f, }, \
436 { 0.0f, 0.0f, }}
437
438 static inline void m2x2_copy( m2x2f a, m2x2f b )
439 {
440 v2_copy( a[0], b[0] );
441 v2_copy( a[1], b[1] );
442 }
443
444 static inline void m2x2_identity( m2x2f a )
445 {
446 m2x2f id = M2X2_INDENTIY;
447 m2x2_copy( id, a );
448 }
449
450 static inline void m2x2_create_rotation( m2x2f a, float theta )
451 {
452 float s, c;
453
454 s = sinf( theta );
455 c = cosf( theta );
456
457 a[0][0] = c;
458 a[0][1] = -s;
459 a[1][0] = s;
460 a[1][1] = c;
461 }
462
463 /*
464 * Matrix 3x3
465 */
466
467 #define M3X3_IDENTITY {{1.0f, 0.0f, 0.0f, },\
468 { 0.0f, 1.0f, 0.0f, },\
469 { 0.0f, 0.0f, 1.0f, }}
470
471 #define M3X3_ZERO {{0.0f, 0.0f, 0.0f, },\
472 { 0.0f, 0.0f, 0.0f, },\
473 { 0.0f, 0.0f, 0.0f, }}
474
475
476 static inline void m3x3_copy( m3x3f a, m3x3f b )
477 {
478 v3_copy( a[0], b[0] );
479 v3_copy( a[1], b[1] );
480 v3_copy( a[2], b[2] );
481 }
482
483 static inline void m3x3_identity( m3x3f a )
484 {
485 m3x3f id = M3X3_IDENTITY;
486 m3x3_copy( id, a );
487 }
488
489 static inline void m3x3_zero( m3x3f a )
490 {
491 m3x3f z = M3X3_ZERO;
492 m3x3_copy( z, a );
493 }
494
495 static inline void m3x3_inv( m3x3f src, m3x3f dest )
496 {
497 float a = src[0][0], b = src[0][1], c = src[0][2],
498 d = src[1][0], e = src[1][1], f = src[1][2],
499 g = src[2][0], h = src[2][1], i = src[2][2];
500
501 float det = 1.f /
502 (+a*(e*i-h*f)
503 -b*(d*i-f*g)
504 +c*(d*h-e*g));
505
506 dest[0][0] = (e*i-h*f)*det;
507 dest[0][1] = -(b*i-c*h)*det;
508 dest[0][2] = (b*f-c*e)*det;
509 dest[1][0] = -(d*i-f*g)*det;
510 dest[1][1] = (a*i-c*g)*det;
511 dest[1][2] = -(a*f-d*c)*det;
512 dest[2][0] = (d*h-g*e)*det;
513 dest[2][1] = -(a*h-g*b)*det;
514 dest[2][2] = (a*e-d*b)*det;
515 }
516
517 static inline void m3x3_transpose( m3x3f src, m3x3f dest )
518 {
519 float a = src[0][0], b = src[0][1], c = src[0][2],
520 d = src[1][0], e = src[1][1], f = src[1][2],
521 g = src[2][0], h = src[2][1], i = src[2][2];
522
523 dest[0][0] = a;
524 dest[0][1] = d;
525 dest[0][2] = g;
526 dest[1][0] = b;
527 dest[1][1] = e;
528 dest[1][2] = h;
529 dest[2][0] = c;
530 dest[2][1] = f;
531 dest[2][2] = i;
532 }
533
534 static inline void m3x3_mul( m3x3f a, m3x3f b, m3x3f d )
535 {
536 float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2],
537 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2],
538 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2],
539
540 b00 = b[0][0], b01 = b[0][1], b02 = b[0][2],
541 b10 = b[1][0], b11 = b[1][1], b12 = b[1][2],
542 b20 = b[2][0], b21 = b[2][1], b22 = b[2][2];
543
544 d[0][0] = a00*b00 + a10*b01 + a20*b02;
545 d[0][1] = a01*b00 + a11*b01 + a21*b02;
546 d[0][2] = a02*b00 + a12*b01 + a22*b02;
547 d[1][0] = a00*b10 + a10*b11 + a20*b12;
548 d[1][1] = a01*b10 + a11*b11 + a21*b12;
549 d[1][2] = a02*b10 + a12*b11 + a22*b12;
550 d[2][0] = a00*b20 + a10*b21 + a20*b22;
551 d[2][1] = a01*b20 + a11*b21 + a21*b22;
552 d[2][2] = a02*b20 + a12*b21 + a22*b22;
553 }
554
555 static inline void m3x3_mulv( m3x3f m, v3f v, v3f d )
556 {
557 v3f res;
558
559 res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
560 res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
561 res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
562
563 v3_copy( res, d );
564 }
565
566 static inline void m3x3_projection( m3x3f dst,
567 float const left, float const right, float const bottom, float const top )
568 {
569 float rl, tb;
570
571 m3x3_zero( dst );
572
573 rl = 1.0f / (right - left);
574 tb = 1.0f / (top - bottom);
575
576 dst[0][0] = 2.0f * rl;
577 dst[1][1] = 2.0f * tb;
578 dst[2][2] = 1.0f;
579 }
580
581 static inline void m3x3_translate( m3x3f m, v3f v )
582 {
583 m[2][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0];
584 m[2][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1];
585 m[2][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2];
586 }
587
588 static inline void m3x3_scale( m3x3f m, v3f v )
589 {
590 m[0][0] = m[0][0] * v[0];
591 m[0][1] = m[0][1] * v[0];
592 m[0][2] = m[0][2] * v[0];
593
594 m[1][0] = m[1][0] * v[1];
595 m[1][1] = m[1][1] * v[1];
596 m[1][2] = m[1][2] * v[1];
597 }
598
599 static inline void m3x3_rotate( m3x3f m, float angle )
600 {
601 float m00 = m[0][0], m10 = m[1][0],
602 m01 = m[0][1], m11 = m[1][1],
603 m02 = m[0][2], m12 = m[1][2];
604 float c, s;
605
606 s = sinf( angle );
607 c = cosf( angle );
608
609 m[0][0] = m00 * c + m10 * s;
610 m[0][1] = m01 * c + m11 * s;
611 m[0][2] = m02 * c + m12 * s;
612
613 m[1][0] = m00 * -s + m10 * c;
614 m[1][1] = m01 * -s + m11 * c;
615 m[1][2] = m02 * -s + m12 * c;
616 }
617
618 /*
619 * Matrix 4x3
620 */
621
622 #define M4X3_IDENTITY {{1.0f, 0.0f, 0.0f, },\
623 { 0.0f, 1.0f, 0.0f, },\
624 { 0.0f, 0.0f, 1.0f, },\
625 { 0.0f, 0.0f, 0.0f }}
626
627 static inline void m4x3_to_3x3( m4x3f a, m3x3f b )
628 {
629 v3_copy( a[0], b[0] );
630 v3_copy( a[1], b[1] );
631 v3_copy( a[2], b[2] );
632 }
633
634 static inline void m4x3_invert_affine( m4x3f a, m4x3f b )
635 {
636 m3x3_transpose( a, b );
637 m3x3_mulv( b, a[3], b[3] );
638 v3_negate( b[3], b[3] );
639 }
640
641 static inline void m4x3_copy( m4x3f a, m4x3f b )
642 {
643 v3_copy( a[0], b[0] );
644 v3_copy( a[1], b[1] );
645 v3_copy( a[2], b[2] );
646 v3_copy( a[3], b[3] );
647 }
648
649 static inline void m4x3_identity( m4x3f a )
650 {
651 m4x3f id = M4X3_IDENTITY;
652 m4x3_copy( id, a );
653 }
654
655 static inline void m4x3_mul( m4x3f a, m4x3f b, m4x3f d )
656 {
657 float
658 a00 = a[0][0], a01 = a[0][1], a02 = a[0][2],
659 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2],
660 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2],
661 a30 = a[3][0], a31 = a[3][1], a32 = a[3][2],
662 b00 = b[0][0], b01 = b[0][1], b02 = b[0][2],
663 b10 = b[1][0], b11 = b[1][1], b12 = b[1][2],
664 b20 = b[2][0], b21 = b[2][1], b22 = b[2][2],
665 b30 = b[3][0], b31 = b[3][1], b32 = b[3][2];
666
667 d[0][0] = a00*b00 + a10*b01 + a20*b02;
668 d[0][1] = a01*b00 + a11*b01 + a21*b02;
669 d[0][2] = a02*b00 + a12*b01 + a22*b02;
670 d[1][0] = a00*b10 + a10*b11 + a20*b12;
671 d[1][1] = a01*b10 + a11*b11 + a21*b12;
672 d[1][2] = a02*b10 + a12*b11 + a22*b12;
673 d[2][0] = a00*b20 + a10*b21 + a20*b22;
674 d[2][1] = a01*b20 + a11*b21 + a21*b22;
675 d[2][2] = a02*b20 + a12*b21 + a22*b22;
676 d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30;
677 d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31;
678 d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32;
679 }
680
681 static inline void m4x3_mulv( m4x3f m, v3f v, v3f d )
682 {
683 v3f res;
684
685 res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0];
686 res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1];
687 res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2];
688
689 v3_copy( res, d );
690 }
691
692 /*
693 * Transform plane ( xyz, distance )
694 */
695 static inline void m4x3_mulp( m4x3f m, v4f p, v4f d )
696 {
697 v3f o;
698
699 v3_muls( p, p[3], o );
700 m4x3_mulv( m, o, o );
701 m3x3_mulv( m, p, d );
702
703 d[3] = v3_dot( o, d );
704 }
705
706 /*
707 * Affine transforms
708 */
709
710 static inline void m4x3_translate( m4x3f m, v3f v )
711 {
712 v3_muladds( m[3], m[0], v[0], m[3] );
713 v3_muladds( m[3], m[1], v[1], m[3] );
714 v3_muladds( m[3], m[2], v[2], m[3] );
715 }
716
717 static inline void m4x3_scale( m4x3f m, float s )
718 {
719 v3_muls( m[0], s, m[0] );
720 v3_muls( m[1], s, m[1] );
721 v3_muls( m[2], s, m[2] );
722 }
723
724 static inline void m4x3_scalev( m4x3f m, v3f v )
725 {
726 v3_muls(m[0], v[0], m[0]);
727 v3_muls(m[1], v[1], m[1]);
728 v3_muls(m[2], v[2], m[2]);
729 }
730
731 static inline void m4x3_rotate_x( m4x3f m, float angle )
732 {
733 m4x3f t = M4X3_IDENTITY;
734 float c, s;
735
736 c = cosf( angle );
737 s = sinf( angle );
738
739 t[1][1] = c;
740 t[1][2] = s;
741 t[2][1] = -s;
742 t[2][2] = c;
743
744 m4x3_mul( m, t, m );
745 }
746
747 static inline void m4x3_rotate_y( m4x3f m, float angle )
748 {
749 m4x3f t = M4X3_IDENTITY;
750 float c, s;
751
752 c = cosf( angle );
753 s = sinf( angle );
754
755 t[0][0] = c;
756 t[0][2] = -s;
757 t[2][0] = s;
758 t[2][2] = c;
759
760 m4x3_mul( m, t, m );
761 }
762
763 static inline void m4x3_rotate_z( m4x3f m, float angle )
764 {
765 m4x3f t = M4X3_IDENTITY;
766 float c, s;
767
768 c = cosf( angle );
769 s = sinf( angle );
770
771 t[0][0] = c;
772 t[0][1] = s;
773 t[1][0] = -s;
774 t[1][1] = c;
775
776 m4x3_mul( m, t, m );
777 }
778
779 static inline void m4x3_expand( m4x3f m, m4x4f d )
780 {
781 v3_copy( m[0], d[0] );
782 v3_copy( m[1], d[1] );
783 v3_copy( m[2], d[2] );
784 v3_copy( m[3], d[3] );
785 d[0][3] = 0.0f;
786 d[1][3] = 0.0f;
787 d[2][3] = 0.0f;
788 d[3][3] = 1.0f;
789 }
790
791 static inline void m4x3_expand_aabb_point( m4x3f m, boxf box, v3f point )
792 {
793 v3f v;
794 m4x3_mulv( m, point, v );
795
796 v3_minv( box[0], v, box[0] );
797 v3_maxv( box[1], v, box[1] );
798 }
799
800 static inline void box_addpt( boxf a, v3f pt )
801 {
802 v3_minv( a[0], pt, a[0] );
803 v3_maxv( a[1], pt, a[1] );
804 }
805
806 static inline void box_concat( boxf a, boxf b )
807 {
808 v3_minv( a[0], b[0], a[0] );
809 v3_maxv( a[1], b[1], a[1] );
810 }
811
812 static inline void box_copy( boxf a, boxf b )
813 {
814 v3_copy( a[0], b[0] );
815 v3_copy( a[1], b[1] );
816 }
817
818 static inline int box_overlap( boxf a, boxf b )
819 {
820 return
821 ( a[0][0] <= b[1][0] && a[1][0] >= b[0][0] ) &&
822 ( a[0][1] <= b[1][1] && a[1][1] >= b[0][1] ) &&
823 ( a[0][2] <= b[1][2] && a[1][2] >= b[0][2] )
824 ;
825 }
826
827 static inline void box_init_inf( boxf box )
828 {
829 v3_fill( box[0], INFINITY );
830 v3_fill( box[1], -INFINITY );
831 }
832
833 static inline void m4x3_transform_aabb( m4x3f m, boxf box )
834 {
835 v3f a; v3f b;
836
837 v3_copy( box[0], a );
838 v3_copy( box[1], b );
839 v3_fill( box[0], INFINITY );
840 v3_fill( box[1], -INFINITY );
841
842 m4x3_expand_aabb_point( m, box, (v3f){ a[0], a[1], a[2] } );
843 m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], a[2] } );
844 m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], a[2] } );
845 m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], a[2] } );
846
847 m4x3_expand_aabb_point( m, box, (v3f){ a[0], a[1], b[2] } );
848 m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], b[2] } );
849 m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], b[2] } );
850 m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], b[2] } );
851 }
852
853 int ray_aabb( boxf box, v3f co, v3f dir, float dist )
854 {
855 v3f v0, v1;
856 float tmin, tmax;
857
858 v3_sub( box[0], co, v0 );
859 v3_sub( box[1], co, v1 );
860 v3_div( v0, dir, v0 );
861 v3_div( v1, dir, v1 );
862
863 tmin = vg_minf( v0[0], v1[0] );
864 tmax = vg_maxf( v0[0], v1[0] );
865 tmin = vg_maxf( tmin, vg_minf( v0[1], v1[1] ));
866 tmax = vg_minf( tmax, vg_maxf( v0[1], v1[1] ));
867 tmin = vg_maxf( tmin, vg_minf( v0[2], v1[2] ));
868 tmax = vg_minf( tmax, vg_maxf( v0[2], v1[2] ));
869
870 return tmax >= tmin && tmin < dist && tmax > 0;
871 }
872
873 static inline void m4x3_lookat( m4x3f m, v3f pos, v3f target, v3f up )
874 {
875 v3f dir;
876 v3_sub( target, pos, dir );
877 v3_normalize( dir );
878
879 v3_copy( dir, m[2] );
880
881 v3_cross( up, m[2], m[0] );
882 v3_normalize( m[0] );
883
884 v3_cross( m[2], m[0], m[1] );
885 v3_copy( pos, m[3] );
886 }
887
888 /*
889 * Matrix 4x4
890 */
891
892 #define M4X4_IDENTITY {{1.0f, 0.0f, 0.0f, 0.0f },\
893 { 0.0f, 1.0f, 0.0f, 0.0f },\
894 { 0.0f, 0.0f, 1.0f, 0.0f },\
895 { 0.0f, 0.0f, 0.0f, 1.0f }}
896 #define M4X4_ZERO {{0.0f, 0.0f, 0.0f, 0.0f },\
897 { 0.0f, 0.0f, 0.0f, 0.0f },\
898 { 0.0f, 0.0f, 0.0f, 0.0f },\
899 { 0.0f, 0.0f, 0.0f, 0.0f }}
900
901 static void m4x4_projection( m4x4f m, float angle,
902 float ratio, float fnear, float ffar )
903 {
904 float scale = tanf( angle * 0.5f * VG_PIf / 180.0f ) * fnear,
905 r = ratio * scale,
906 l = -r,
907 t = scale,
908 b = -t;
909
910 m[0][0] = 2.0f * fnear / (r - l);
911 m[0][1] = 0.0f;
912 m[0][2] = 0.0f;
913 m[0][3] = 0.0f;
914 m[1][0] = 0.0f;
915 m[1][1] = 2.0f * fnear / (t - b);
916 m[1][2] = 0.0f;
917 m[1][3] = 0.0f;
918 m[2][0] = (r + l) / (r - l);
919 m[2][1] = (t + b) / (t - b);
920 m[2][2] = -(ffar + fnear) / (ffar - fnear);
921 m[2][3] = -1.0f;
922 m[3][0] = 0.0f;
923 m[3][1] = 0.0f;
924 m[3][2] = -2.0f * ffar * fnear / (ffar - fnear);
925 m[3][3] = 0.0f;
926 }
927
928 static void m4x4_translate( m4x4f m, v3f v )
929 {
930 v4_muladds( m[3], m[0], v[0], m[3] );
931 v4_muladds( m[3], m[1], v[1], m[3] );
932 v4_muladds( m[3], m[2], v[2], m[3] );
933 }
934
935 static inline void m4x4_copy( m4x4f a, m4x4f b )
936 {
937 v4_copy( a[0], b[0] );
938 v4_copy( a[1], b[1] );
939 v4_copy( a[2], b[2] );
940 v4_copy( a[3], b[3] );
941 }
942
943 static inline void m4x4_identity( m4x4f a )
944 {
945 m4x4f id = M4X4_IDENTITY;
946 m4x4_copy( id, a );
947 }
948
949 static inline void m4x4_zero( m4x4f a )
950 {
951 m4x4f zero = M4X4_ZERO;
952 m4x4_copy( zero, a );
953 }
954
955 static inline void m4x4_mul( m4x4f a, m4x4f b, m4x4f d )
956 {
957 float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3],
958 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3],
959 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3],
960 a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3],
961
962 b00 = b[0][0], b01 = b[0][1], b02 = b[0][2], b03 = b[0][3],
963 b10 = b[1][0], b11 = b[1][1], b12 = b[1][2], b13 = b[1][3],
964 b20 = b[2][0], b21 = b[2][1], b22 = b[2][2], b23 = b[2][3],
965 b30 = b[3][0], b31 = b[3][1], b32 = b[3][2], b33 = b[3][3];
966
967 d[0][0] = a00*b00 + a10*b01 + a20*b02 + a30*b03;
968 d[0][1] = a01*b00 + a11*b01 + a21*b02 + a31*b03;
969 d[0][2] = a02*b00 + a12*b01 + a22*b02 + a32*b03;
970 d[0][3] = a03*b00 + a13*b01 + a23*b02 + a33*b03;
971 d[1][0] = a00*b10 + a10*b11 + a20*b12 + a30*b13;
972 d[1][1] = a01*b10 + a11*b11 + a21*b12 + a31*b13;
973 d[1][2] = a02*b10 + a12*b11 + a22*b12 + a32*b13;
974 d[1][3] = a03*b10 + a13*b11 + a23*b12 + a33*b13;
975 d[2][0] = a00*b20 + a10*b21 + a20*b22 + a30*b23;
976 d[2][1] = a01*b20 + a11*b21 + a21*b22 + a31*b23;
977 d[2][2] = a02*b20 + a12*b21 + a22*b22 + a32*b23;
978 d[2][3] = a03*b20 + a13*b21 + a23*b22 + a33*b23;
979 d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30*b33;
980 d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31*b33;
981 d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32*b33;
982 d[3][3] = a03*b30 + a13*b31 + a23*b32 + a33*b33;
983 }
984
985 static inline void m4x4_mulv( m4x4f m, v4f v, v4f d )
986 {
987 v4f res;
988
989 res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3];
990 res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3];
991 res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3];
992 res[3] = m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3];
993
994 v4_copy( res, d );
995 }
996
997 static inline void m4x4_inv( m4x4f a, m4x4f d )
998 {
999 float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3],
1000 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3],
1001 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3],
1002 a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3],
1003 det,
1004 t[6];
1005
1006 t[0] = a22*a33 - a32*a23;
1007 t[1] = a21*a33 - a31*a23;
1008 t[2] = a21*a32 - a31*a22;
1009 t[3] = a20*a33 - a30*a23;
1010 t[4] = a20*a32 - a30*a22;
1011 t[5] = a20*a31 - a30*a21;
1012
1013 d[0][0] = a11*t[0] - a12*t[1] + a13*t[2];
1014 d[1][0] =-(a10*t[0] - a12*t[3] + a13*t[4]);
1015 d[2][0] = a10*t[1] - a11*t[3] + a13*t[5];
1016 d[3][0] =-(a10*t[2] - a11*t[4] + a12*t[5]);
1017
1018 d[0][1] =-(a01*t[0] - a02*t[1] + a03*t[2]);
1019 d[1][1] = a00*t[0] - a02*t[3] + a03*t[4];
1020 d[2][1] =-(a00*t[1] - a01*t[3] + a03*t[5]);
1021 d[3][1] = a00*t[2] - a01*t[4] + a02*t[5];
1022
1023 t[0] = a12*a33 - a32*a13;
1024 t[1] = a11*a33 - a31*a13;
1025 t[2] = a11*a32 - a31*a12;
1026 t[3] = a10*a33 - a30*a13;
1027 t[4] = a10*a32 - a30*a12;
1028 t[5] = a10*a31 - a30*a11;
1029
1030 d[0][2] = a01*t[0] - a02*t[1] + a03*t[2];
1031 d[1][2] =-(a00*t[0] - a02*t[3] + a03*t[4]);
1032 d[2][2] = a00*t[1] - a01*t[3] + a03*t[5];
1033 d[3][2] =-(a00*t[2] - a01*t[4] + a02*t[5]);
1034
1035 t[0] = a12*a23 - a22*a13;
1036 t[1] = a11*a23 - a21*a13;
1037 t[2] = a11*a22 - a21*a12;
1038 t[3] = a10*a23 - a20*a13;
1039 t[4] = a10*a22 - a20*a12;
1040 t[5] = a10*a21 - a20*a11;
1041
1042 d[0][3] =-(a01*t[0] - a02*t[1] + a03*t[2]);
1043 d[1][3] = a00*t[0] - a02*t[3] + a03*t[4];
1044 d[2][3] =-(a00*t[1] - a01*t[3] + a03*t[5]);
1045 d[3][3] = a00*t[2] - a01*t[4] + a02*t[5];
1046
1047 det = 1.0f / (a00*d[0][0] + a01*d[1][0] + a02*d[2][0] + a03*d[3][0]);
1048 v4_muls( d[0], det, d[0] );
1049 v4_muls( d[1], det, d[1] );
1050 v4_muls( d[2], det, d[2] );
1051 v4_muls( d[3], det, d[3] );
1052 }
1053
1054 /*
1055 * Planes (double precision)
1056 */
1057 static inline void tri_to_plane( double a[3], double b[3],
1058 double c[3], double p[4] )
1059 {
1060 double edge0[3];
1061 double edge1[3];
1062 double l;
1063
1064 edge0[0] = b[0] - a[0];
1065 edge0[1] = b[1] - a[1];
1066 edge0[2] = b[2] - a[2];
1067
1068 edge1[0] = c[0] - a[0];
1069 edge1[1] = c[1] - a[1];
1070 edge1[2] = c[2] - a[2];
1071
1072 p[0] = edge0[1] * edge1[2] - edge0[2] * edge1[1];
1073 p[1] = edge0[2] * edge1[0] - edge0[0] * edge1[2];
1074 p[2] = edge0[0] * edge1[1] - edge0[1] * edge1[0];
1075
1076 l = sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
1077 p[3] = (p[0] * a[0] + p[1] * a[1] + p[2] * a[2]) / l;
1078
1079 p[0] = p[0] / l;
1080 p[1] = p[1] / l;
1081 p[2] = p[2] / l;
1082 }
1083
1084 static inline int plane_intersect( double a[4], double b[4],
1085 double c[4], double p[4] )
1086 {
1087 double const epsilon = 1e-8f;
1088
1089 double x[3];
1090 double d;
1091
1092 x[0] = a[1] * b[2] - a[2] * b[1];
1093 x[1] = a[2] * b[0] - a[0] * b[2];
1094 x[2] = a[0] * b[1] - a[1] * b[0];
1095
1096 d = x[0] * c[0] + x[1] * c[1] + x[2] * c[2];
1097
1098 if( d < epsilon && d > -epsilon ) return 0;
1099
1100 p[0] = (b[1] * c[2] - b[2] * c[1]) * -a[3];
1101 p[1] = (b[2] * c[0] - b[0] * c[2]) * -a[3];
1102 p[2] = (b[0] * c[1] - b[1] * c[0]) * -a[3];
1103
1104 p[0] += (c[1] * a[2] - c[2] * a[1]) * -b[3];
1105 p[1] += (c[2] * a[0] - c[0] * a[2]) * -b[3];
1106 p[2] += (c[0] * a[1] - c[1] * a[0]) * -b[3];
1107
1108 p[0] += (a[1] * b[2] - a[2] * b[1]) * -c[3];
1109 p[1] += (a[2] * b[0] - a[0] * b[2]) * -c[3];
1110 p[2] += (a[0] * b[1] - a[1] * b[0]) * -c[3];
1111
1112 p[0] = -p[0] / d;
1113 p[1] = -p[1] / d;
1114 p[2] = -p[2] / d;
1115
1116 return 1;
1117 }
1118
1119 static inline double plane_polarity( double p[4], double a[3] )
1120 {
1121 return
1122 (a[0] * p[0] + a[1] * p[1] + a[2] * p[2])
1123 -(p[0]*p[3] * p[0] + p[1]*p[3] * p[1] + p[2]*p[3] * p[2])
1124 ;
1125 }
1126
1127 /* Quaternions */
1128
1129 static inline void q_identity( v4f q )
1130 {
1131 q[0] = 0.0f; q[1] = 0.0f; q[2] = 0.0f; q[3] = 1.0f;
1132 }
1133
1134 static inline void q_axis_angle( v4f q, v3f axis, float angle )
1135 {
1136 float a = angle*0.5f,
1137 c = cosf(a),
1138 s = sinf(a);
1139
1140 q[0] = s*axis[0];
1141 q[1] = s*axis[1];
1142 q[2] = s*axis[2];
1143 q[3] = c;
1144 }
1145
1146 static inline void q_mul( v4f q, v4f q1, v4f d )
1147 {
1148 v4f t;
1149 t[0] = q[3]*q1[0] + q[0]*q1[3] + q[1]*q1[2] - q[2]*q1[1];
1150 t[1] = q[3]*q1[1] - q[0]*q1[2] + q[1]*q1[3] + q[2]*q1[0];
1151 t[2] = q[3]*q1[2] + q[0]*q1[1] - q[1]*q1[0] + q[2]*q1[3];
1152 t[3] = q[3]*q1[3] - q[0]*q1[0] - q[1]*q1[1] - q[2]*q1[2];
1153 v4_copy( t, d );
1154 }
1155
1156 static inline void q_normalize( v4f q )
1157 {
1158 float s = 1.0f/ sqrtf(v4_dot(q,q));
1159 q[0] *= s;
1160 q[1] *= s;
1161 q[2] *= s;
1162 q[3] *= s;
1163 }
1164
1165 static inline void q_inv( v4f q, v4f d )
1166 {
1167 float s = 1.0f / v4_dot(q,q);
1168 d[0] = -q[0]*s;
1169 d[1] = -q[1]*s;
1170 d[2] = -q[2]*s;
1171 d[3] = q[3]*s;
1172 }
1173
1174 static inline void q_nlerp( v4f a, v4f b, float t, v4f d )
1175 {
1176 v4_lerp( a, b, t, d );
1177 q_normalize( d );
1178 }
1179
1180 static inline void q_m3x3( v4f q, m3x3f d )
1181 {
1182 float
1183 l = v4_length(q),
1184 s = l > 0.0f? 2.0f/l: 0.0f,
1185
1186 xx = s*q[0]*q[0], xy = s*q[0]*q[1], wx = s*q[3]*q[0],
1187 yy = s*q[1]*q[1], yz = s*q[1]*q[2], wy = s*q[3]*q[1],
1188 zz = s*q[2]*q[2], xz = s*q[0]*q[2], wz = s*q[3]*q[2];
1189
1190 d[0][0] = 1.0f - yy - zz;
1191 d[1][1] = 1.0f - xx - zz;
1192 d[2][2] = 1.0f - xx - yy;
1193 d[0][1] = xy + wz;
1194 d[1][2] = yz + wx;
1195 d[2][0] = xz + wy;
1196 d[1][0] = xy - wz;
1197 d[2][1] = yz - wx;
1198 d[0][2] = xz - wy;
1199 }
1200
1201 static void m3x3_q( m3x3f m, v4f q )
1202 {
1203 float diag, r, rinv;
1204
1205 diag = m[0][0] + m[1][1] + m[2][2];
1206 if( diag >= 0.0f )
1207 {
1208 r = sqrtf( 1.0f + diag );
1209 rinv = 0.5f / r;
1210 q[0] = rinv * (m[1][2] - m[2][1]);
1211 q[1] = rinv * (m[2][0] - m[0][2]);
1212 q[2] = rinv * (m[0][1] - m[1][0]);
1213 q[3] = r * 0.5f;
1214 }
1215 else if( m[0][0] >= m[1][1] && m[0][0] >= m[2][2] )
1216 {
1217 r = sqrtf( 1.0f - m[1][1] - m[2][2] + m[0][0] );
1218 rinv = 0.5f / r;
1219 q[0] = r * 0.5f;
1220 q[1] = rinv * (m[0][1] + m[1][0]);
1221 q[2] = rinv * (m[0][2] + m[2][0]);
1222 q[3] = rinv * (m[1][2] - m[2][1]);
1223 }
1224 else if( m[1][1] >= m[2][2] )
1225 {
1226 r = sqrtf( 1.0f - m[0][0] - m[2][2] + m[1][1] );
1227 rinv = 0.5f / r;
1228 q[0] = rinv * (m[0][1] + m[1][0]);
1229 q[1] = r * 0.5f;
1230 q[2] = rinv * (m[1][2] + m[2][1]);
1231 q[3] = rinv * (m[2][0] - m[0][2]);
1232 }
1233 else
1234 {
1235 r = sqrtf( 1.0f - m[0][0] - m[1][1] + m[2][2] );
1236 rinv = 0.5f / r;
1237 q[0] = rinv * (m[0][2] + m[2][0]);
1238 q[1] = rinv * (m[1][2] + m[2][1]);
1239 q[2] = r * 0.5f;
1240 q[3] = rinv * (m[0][1] - m[1][0]);
1241 }
1242 }
1243
1244 static int ray_tri( v3f tri[3], v3f co, v3f dir, float *dist )
1245 {
1246 float const kEpsilon = 0.00001f;
1247
1248 v3f v0, v1, h, s, q, n;
1249 float a,f,u,v,t;
1250
1251 float *pa = tri[0],
1252 *pb = tri[1],
1253 *pc = tri[2];
1254
1255 v3_sub( pb, pa, v0 );
1256 v3_sub( pc, pa, v1 );
1257 v3_cross( dir, v1, h );
1258 v3_cross( v0, v1, n );
1259
1260 if( v3_dot( n, dir ) > 0.0f ) /* Backface culling */
1261 return 0;
1262
1263 /* Parralel */
1264 a = v3_dot( v0, h );
1265 if( a > -kEpsilon && a < kEpsilon )
1266 return 0;
1267
1268 f = 1.0f/a;
1269 v3_sub( co, pa, s );
1270
1271 u = f * v3_dot(s, h);
1272 if( u < 0.0f || u > 1.0f )
1273 return 0;
1274
1275 v3_cross( s, v0, q );
1276 v = f * v3_dot( dir, q );
1277 if( v < 0.0f || u+v > 1.0f )
1278 return 0;
1279
1280 t = f * v3_dot(v1, q);
1281 if( t > kEpsilon )
1282 {
1283 *dist = t;
1284 return 1;
1285 }
1286 else return 0;
1287 }
1288
1289 static inline float vg_randf(void)
1290 {
1291 return (float)rand()/(float)(RAND_MAX);
1292 }
1293
1294 static inline void vg_rand_dir(v3f dir)
1295 {
1296 dir[0] = vg_randf();
1297 dir[1] = vg_randf();
1298 dir[2] = vg_randf();
1299
1300 v3_muls( dir, 2.0f, dir );
1301 v3_sub( dir, (v3f){1.0f,1.0f,1.0f}, dir );
1302
1303 v3_normalize( dir );
1304 }
1305
1306 static inline void vg_rand_sphere( v3f co )
1307 {
1308 vg_rand_dir(co);
1309 v3_muls( co, cbrtf( vg_randf() ), co );
1310 }
1311
1312 static inline int vg_randint(int max)
1313 {
1314 return rand()%max;
1315 }
1316
1317 #endif /* VG_M_H */