3d options
[vg.git] / src / vg / vg_m.h
1 /* Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved */
2
3 #define VG_PIf 3.14159265358979323846264338327950288f
4 #define VG_TAUf 6.28318530717958647692528676655900576f
5
6 static inline float vg_minf( float a, float b )
7 {
8 return a < b? a: b;
9 }
10
11 static inline float vg_maxf( float a, float b )
12 {
13 return a > b? a: b;
14 }
15
16 static inline float vg_clampf( float a, float min, float max )
17 {
18 return vg_minf( max, vg_maxf( a, min ) );
19 }
20
21 static inline float vg_signf( float a )
22 {
23 return a < 0.0f? -1.0f: 1.0f;
24 }
25
26 #define VG_MIN( A, B ) ((A)<(B)?(A):(B))
27 #define VG_MAX( A, B ) ((A)>(B)?(A):(B))
28
29 static inline int vg_min( int a, int b )
30 {
31 return a < b? a: b;
32 }
33
34 static inline int vg_max( int a, int b )
35 {
36 return a > b? a: b;
37 }
38
39 static inline float vg_rad( float deg )
40 {
41 return deg * VG_PIf / 180.0f;
42 }
43
44 /*
45 * Vector 3
46 */
47 static inline void v2_copy( v2f a, v2f b )
48 {
49 b[0] = a[0]; b[1] = a[1];
50 }
51
52 static inline void v2i_copy( v2i a, v2i b )
53 {
54 b[0] = a[0]; b[1] = a[1];
55 }
56
57 static inline int v2i_eq( v2i a, v2i b )
58 {
59 return ((a[0] == b[0]) && (a[1] == b[1]));
60 }
61
62 static inline void v2i_add( v2i a, v2i b, v2i d )
63 {
64 d[0] = a[0]+b[0]; d[1] = a[1]+b[1];
65 }
66
67 static inline void v2i_sub( v2i a, v2i b, v2i d )
68 {
69 d[0] = a[0]-b[0]; d[1] = a[1]-b[1];
70 }
71
72 static inline void v2_minv( v2f a, v2f b, v2f dest )
73 {
74 dest[0] = vg_minf(a[0], b[0]);
75 dest[1] = vg_minf(a[1], b[1]);
76 }
77
78 static inline void v2_maxv( v2f a, v2f b, v2f dest )
79 {
80 dest[0] = vg_maxf(a[0], b[0]);
81 dest[1] = vg_maxf(a[1], b[1]);
82 }
83
84 static inline void v2_sub( v2f a, v2f b, v2f d )
85 {
86 d[0] = a[0]-b[0]; d[1] = a[1]-b[1];
87 }
88
89 static inline float v2_cross( v2f a, v2f b )
90 {
91 return a[0] * b[1] - a[1] * b[0];
92 }
93
94 static inline void v2_add( v2f a, v2f b, v2f d )
95 {
96 d[0] = a[0]+b[0]; d[1] = a[1]+b[1];
97 }
98
99 static inline void v2_muls( v2f a, float s, v2f d )
100 {
101 d[0] = a[0]*s; d[1] = a[1]*s;
102 }
103
104 static inline void v2_divs( v2f a, float s, v2f d )
105 {
106 d[0] = a[0]/s; d[1] = a[1]/s;
107 }
108
109 static inline void v2_mul( v2f a, v2f b, v2f d )
110 {
111 d[0] = a[0]*b[0];
112 d[1] = a[1]*b[1];
113 }
114
115 static inline void v2_div( v2f a, v2f b, v2f d )
116 {
117 d[0] = a[0]/b[0]; d[1] = a[1]/b[1];
118 }
119
120 static inline void v2_muladd( v2f a, v2f b, v2f s, v2f d )
121 {
122 d[0] = a[0]+b[0]*s[0];
123 d[1] = a[1]+b[1]*s[1];
124 }
125
126 static inline void v2_muladds( v2f a, v2f b, float s, v2f d )
127 {
128 d[0] = a[0]+b[0]*s;
129 d[1] = a[1]+b[1]*s;
130 }
131
132 static inline float v2_length2( v2f a )
133 {
134 return a[0]*a[0] + a[1]*a[1];
135 }
136
137 static inline float v2_length( v2f a )
138 {
139 return sqrtf( v2_length2( a ) );
140 }
141
142 static inline float v2_dist2( v2f a, v2f b )
143 {
144 v2f delta;
145 v2_sub( a, b, delta );
146 return v2_length2( delta );
147 }
148
149 static inline float v2_dist( v2f a, v2f b )
150 {
151 return sqrtf( v2_dist2( a, b ) );
152 }
153
154 static inline void v2_lerp( v2f a, v2f b, float t, v2f d )
155 {
156 d[0] = a[0] + t*(b[0]-a[0]);
157 d[1] = a[1] + t*(b[1]-a[1]);
158 }
159
160 /*
161 * Vector 3
162 */
163 static inline void v3_zero( v3f a )
164 {
165 a[0] = 0.f; a[1] = 0.f; a[2] = 0.f;
166 }
167
168 static inline void v3_copy( v3f a, v3f b )
169 {
170 b[0] = a[0]; b[1] = a[1]; b[2] = a[2];
171 }
172
173 static inline void v3_add( v3f a, v3f b, v3f d )
174 {
175 d[0] = a[0]+b[0]; d[1] = a[1]+b[1]; d[2] = a[2]+b[2];
176 }
177
178 static inline void v3_sub( v3f a, v3f b, v3f d )
179 {
180 d[0] = a[0]-b[0]; d[1] = a[1]-b[1]; d[2] = a[2]-b[2];
181 }
182
183 static inline void v3_mul( v3f a, v3f b, v3f d )
184 {
185 d[0] = a[0]*b[0]; d[1] = a[1]*b[1]; d[2] = a[2]*b[2];
186 }
187
188 static inline void v3_div( v3f a, v3f b, v3f d )
189 {
190 d[0] = a[0]/b[0]; d[1] = a[1]/b[1]; d[2] = a[2]/b[2];
191 }
192
193 static inline void v3_muls( v3f a, float s, v3f d )
194 {
195 d[0] = a[0]*s; d[1] = a[1]*s; d[2] = a[2]*s;
196 }
197
198 static inline void v3_divs( v3f a, float s, v3f d )
199 {
200 d[0] = a[0]/s; d[1] = a[1]/s; d[2] = a[2]/s;
201 }
202
203 static inline void v3_muladds( v3f a, v3f b, float s, v3f d )
204 {
205 d[0] = a[0]+b[0]*s; d[1] = a[1]+b[1]*s; d[2] = a[2]+b[2]*s;
206 }
207
208 static inline float v3_dot( v3f a, v3f b )
209 {
210 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
211 }
212
213 static inline void v3_cross( v3f a, v3f b, v3f d )
214 {
215 d[0] = a[1] * b[2] - a[2] * b[1];
216 d[1] = a[2] * b[0] - a[0] * b[2];
217 d[2] = a[0] * b[1] - a[1] * b[0];
218 }
219
220 static inline float v3_length2( v3f a )
221 {
222 return v3_dot( a, a );
223 }
224
225 static inline float v3_length( v3f a )
226 {
227 return sqrtf( v3_length2( a ) );
228 }
229
230 static inline float v3_dist2( v3f a, v3f b )
231 {
232 v3f delta;
233 v3_sub( a, b, delta );
234 return v3_length2( delta );
235 }
236
237 static inline float v3_dist( v3f a, v3f b )
238 {
239 return sqrtf( v3_dist2( a, b ) );
240 }
241
242 static inline void v3_normalize( v3f a )
243 {
244 v3_muls( a, 1.f / v3_length( a ), a );
245 }
246
247 static inline float vg_lerpf( float a, float b, float t )
248 {
249 return a + t*(b-a);
250 }
251
252 static inline void v3_lerp( v3f a, v3f b, float t, v3f d )
253 {
254 d[0] = a[0] + t*(b[0]-a[0]);
255 d[1] = a[1] + t*(b[1]-a[1]);
256 d[2] = a[2] + t*(b[2]-a[2]);
257 }
258
259 static inline void v3_minv( v3f a, v3f b, v3f dest )
260 {
261 dest[0] = vg_minf(a[0], b[0]);
262 dest[1] = vg_minf(a[1], b[1]);
263 dest[2] = vg_minf(a[2], b[2]);
264 }
265
266 static inline void v3_maxv( v3f a, v3f b, v3f dest )
267 {
268 dest[0] = vg_maxf(a[0], b[0]);
269 dest[1] = vg_maxf(a[1], b[1]);
270 dest[2] = vg_maxf(a[2], b[2]);
271 }
272
273 static inline float v3_minf( v3f a )
274 {
275 return vg_minf( vg_minf( a[0], a[1] ), a[2] );
276 }
277
278 static inline float v3_maxf( v3f a )
279 {
280 return vg_maxf( vg_maxf( a[0], a[1] ), a[2] );
281 }
282
283 static inline void v3_fill( v3f a, float v )
284 {
285 a[0] = v;
286 a[1] = v;
287 a[2] = v;
288 }
289
290 static inline void v3_floor( v3f a, v3f b )
291 {
292 b[0] = floorf( a[0] );
293 b[1] = floorf( a[1] );
294 b[2] = floorf( a[2] );
295 }
296
297 static inline void v3_negate( v3f a, v3f b )
298 {
299 b[0] = -a[0];
300 b[1] = -a[1];
301 b[2] = -a[2];
302 }
303
304 /*
305 * Vector 4
306 */
307 static inline void v4_copy( v4f a, v4f b )
308 {
309 b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; b[3] = a[3];
310 }
311
312 static inline void v4_zero( v4f a )
313 {
314 a[0] = 0.f; a[1] = 0.f; a[2] = 0.f; a[3] = 0.f;
315 }
316
317 static inline void v4_muladds( v3f a, v3f b, float s, v3f d )
318 {
319 d[0] = a[0]+b[0]*s;
320 d[1] = a[1]+b[1]*s;
321 d[2] = a[2]+b[2]*s;
322 d[3] = a[3]+b[3]*s;
323 }
324
325 /*
326 * Matrix 2x2
327 */
328
329 #define M2X2_INDENTIY {{1.0f, 0.0f, }, \
330 { 0.0f, 1.0f, }}
331
332 #define M2X2_ZERO {{0.0f, 0.0f, }, \
333 { 0.0f, 0.0f, }}
334
335 static inline void m2x2_copy( m2x2f a, m2x2f b )
336 {
337 v2_copy( a[0], b[0] );
338 v2_copy( a[1], b[1] );
339 }
340
341 static inline void m2x2_identity( m2x2f a )
342 {
343 m2x2f id = M2X2_INDENTIY;
344 m2x2_copy( id, a );
345 }
346
347 static inline void m2x2_create_rotation( m2x2f a, float theta )
348 {
349 float s, c;
350
351 s = sinf( theta );
352 c = cosf( theta );
353
354 a[0][0] = c;
355 a[0][1] = -s;
356 a[1][0] = s;
357 a[1][1] = c;
358 }
359
360 /*
361 * Matrix 3x3
362 */
363
364 #define M3X3_IDENTITY {{1.0f, 0.0f, 0.0f, },\
365 { 0.0f, 1.0f, 0.0f, },\
366 { 0.0f, 0.0f, 1.0f, }}
367
368 #define M3X3_ZERO {{0.0f, 0.0f, 0.0f, },\
369 { 0.0f, 0.0f, 0.0f, },\
370 { 0.0f, 0.0f, 0.0f, }}
371
372
373 static inline void m3x3_copy( m3x3f a, m3x3f b )
374 {
375 v3_copy( a[0], b[0] );
376 v3_copy( a[1], b[1] );
377 v3_copy( a[2], b[2] );
378 }
379
380 static inline void m3x3_identity( m3x3f a )
381 {
382 m3x3f id = M3X3_IDENTITY;
383 m3x3_copy( id, a );
384 }
385
386 static inline void m3x3_zero( m3x3f a )
387 {
388 m3x3f z = M3X3_ZERO;
389 m3x3_copy( z, a );
390 }
391
392 static inline void m3x3_inv( m3x3f src, m3x3f dest )
393 {
394 float a = src[0][0], b = src[0][1], c = src[0][2],
395 d = src[1][0], e = src[1][1], f = src[1][2],
396 g = src[2][0], h = src[2][1], i = src[2][2];
397
398 float det = 1.f /
399 (+a*(e*i-h*f)
400 -b*(d*i-f*g)
401 +c*(d*h-e*g));
402
403 dest[0][0] = (e*i-h*f)*det;
404 dest[0][1] = -(b*i-c*h)*det;
405 dest[0][2] = (b*f-c*e)*det;
406 dest[1][0] = -(d*i-f*g)*det;
407 dest[1][1] = (a*i-c*g)*det;
408 dest[1][2] = -(a*f-d*c)*det;
409 dest[2][0] = (d*h-g*e)*det;
410 dest[2][1] = -(a*h-g*b)*det;
411 dest[2][2] = (a*e-d*b)*det;
412 }
413
414 static inline void m3x3_transpose( m3x3f src, m3x3f dest )
415 {
416 float a = src[0][0], b = src[0][1], c = src[0][2],
417 d = src[1][0], e = src[1][1], f = src[1][2],
418 g = src[2][0], h = src[2][1], i = src[2][2];
419
420 dest[0][0] = a;
421 dest[0][1] = d;
422 dest[0][2] = g;
423 dest[1][0] = b;
424 dest[1][1] = e;
425 dest[1][2] = h;
426 dest[2][0] = c;
427 dest[2][1] = f;
428 dest[2][2] = i;
429 }
430
431 static inline void m3x3_mul( m3x3f a, m3x3f b, m3x3f d )
432 {
433 float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2],
434 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2],
435 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2],
436
437 b00 = b[0][0], b01 = b[0][1], b02 = b[0][2],
438 b10 = b[1][0], b11 = b[1][1], b12 = b[1][2],
439 b20 = b[2][0], b21 = b[2][1], b22 = b[2][2];
440
441 d[0][0] = a00*b00 + a10*b01 + a20*b02;
442 d[0][1] = a01*b00 + a11*b01 + a21*b02;
443 d[0][2] = a02*b00 + a12*b01 + a22*b02;
444 d[1][0] = a00*b10 + a10*b11 + a20*b12;
445 d[1][1] = a01*b10 + a11*b11 + a21*b12;
446 d[1][2] = a02*b10 + a12*b11 + a22*b12;
447 d[2][0] = a00*b20 + a10*b21 + a20*b22;
448 d[2][1] = a01*b20 + a11*b21 + a21*b22;
449 d[2][2] = a02*b20 + a12*b21 + a22*b22;
450 }
451
452 static inline void m3x3_mulv( m3x3f m, v3f v, v3f d )
453 {
454 v3f res;
455
456 res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
457 res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
458 res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
459
460 v3_copy( res, d );
461 }
462
463 static inline void m3x3_projection( m3x3f dst,
464 float const left, float const right, float const bottom, float const top )
465 {
466 float rl, tb;
467
468 m3x3_zero( dst );
469
470 rl = 1.0f / (right - left);
471 tb = 1.0f / (top - bottom);
472
473 dst[0][0] = 2.0f * rl;
474 dst[1][1] = 2.0f * tb;
475 dst[2][2] = 1.0f;
476 }
477
478 static inline void m3x3_translate( m3x3f m, v3f v )
479 {
480 m[2][0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0];
481 m[2][1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1];
482 m[2][2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2];
483 }
484
485 static inline void m3x3_scale( m3x3f m, v3f v )
486 {
487 m[0][0] = m[0][0] * v[0];
488 m[0][1] = m[0][1] * v[0];
489 m[0][2] = m[0][2] * v[0];
490
491 m[1][0] = m[1][0] * v[1];
492 m[1][1] = m[1][1] * v[1];
493 m[1][2] = m[1][2] * v[1];
494 }
495
496 static inline void m3x3_rotate( m3x3f m, float angle )
497 {
498 float m00 = m[0][0], m10 = m[1][0],
499 m01 = m[0][1], m11 = m[1][1],
500 m02 = m[0][2], m12 = m[1][2];
501 float c, s;
502
503 s = sinf( angle );
504 c = cosf( angle );
505
506 m[0][0] = m00 * c + m10 * s;
507 m[0][1] = m01 * c + m11 * s;
508 m[0][2] = m02 * c + m12 * s;
509
510 m[1][0] = m00 * -s + m10 * c;
511 m[1][1] = m01 * -s + m11 * c;
512 m[1][2] = m02 * -s + m12 * c;
513 }
514
515 /*
516 * Matrix 4x3
517 */
518
519 #define M4X3_IDENTITY {{1.0f, 0.0f, 0.0f, },\
520 { 0.0f, 1.0f, 0.0f, },\
521 { 0.0f, 0.0f, 1.0f, },\
522 { 0.0f, 0.0f, 0.0f }}
523
524 static inline void m4x3_to_3x3( m4x3f a, m3x3f b )
525 {
526 v3_copy( a[0], b[0] );
527 v3_copy( a[1], b[1] );
528 v3_copy( a[2], b[2] );
529 }
530
531 static inline void m4x3_copy( m4x3f a, m4x3f b )
532 {
533 v3_copy( a[0], b[0] );
534 v3_copy( a[1], b[1] );
535 v3_copy( a[2], b[2] );
536 v3_copy( a[3], b[3] );
537 }
538
539 static inline void m4x3_identity( m4x3f a )
540 {
541 m4x3f id = M4X3_IDENTITY;
542 m4x3_copy( id, a );
543 }
544
545 static inline void m4x3_mul( m4x3f a, m4x3f b, m4x3f d )
546 {
547 float
548 a00 = a[0][0], a01 = a[0][1], a02 = a[0][2],
549 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2],
550 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2],
551 a30 = a[3][0], a31 = a[3][1], a32 = a[3][2],
552 b00 = b[0][0], b01 = b[0][1], b02 = b[0][2],
553 b10 = b[1][0], b11 = b[1][1], b12 = b[1][2],
554 b20 = b[2][0], b21 = b[2][1], b22 = b[2][2],
555 b30 = b[3][0], b31 = b[3][1], b32 = b[3][2];
556
557 d[0][0] = a00*b00 + a10*b01 + a20*b02;
558 d[0][1] = a01*b00 + a11*b01 + a21*b02;
559 d[0][2] = a02*b00 + a12*b01 + a22*b02;
560 d[1][0] = a00*b10 + a10*b11 + a20*b12;
561 d[1][1] = a01*b10 + a11*b11 + a21*b12;
562 d[1][2] = a02*b10 + a12*b11 + a22*b12;
563 d[2][0] = a00*b20 + a10*b21 + a20*b22;
564 d[2][1] = a01*b20 + a11*b21 + a21*b22;
565 d[2][2] = a02*b20 + a12*b21 + a22*b22;
566 d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30;
567 d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31;
568 d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32;
569 }
570
571 static inline void m4x3_mulv( m4x3f m, v3f v, v3f d )
572 {
573 v3f res;
574
575 res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0];
576 res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1];
577 res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2];
578
579 v3_copy( res, d );
580 }
581
582 /*
583 * Affine transforms
584 */
585
586 static inline void m4x3_translate( m4x3f m, v3f v )
587 {
588 v3_muladds( m[3], m[0], v[0], m[3] );
589 v3_muladds( m[3], m[1], v[1], m[3] );
590 v3_muladds( m[3], m[2], v[2], m[3] );
591 }
592
593 static inline void m4x3_scale( m4x3f m, float s )
594 {
595 v3_muls( m[0], s, m[0] );
596 v3_muls( m[1], s, m[1] );
597 v3_muls( m[2], s, m[2] );
598 }
599
600 static inline void m4x3_rotate_x( m4x3f m, float angle )
601 {
602 m4x3f t = M4X3_IDENTITY;
603 float c, s;
604
605 c = cosf( angle );
606 s = sinf( angle );
607
608 t[1][1] = c;
609 t[1][2] = s;
610 t[2][1] = -s;
611 t[2][2] = c;
612
613 m4x3_mul( m, t, m );
614 }
615
616 static inline void m4x3_rotate_y( m4x3f m, float angle )
617 {
618 m4x3f t = M4X3_IDENTITY;
619 float c, s;
620
621 c = cosf( angle );
622 s = sinf( angle );
623
624 t[0][0] = c;
625 t[0][2] = -s;
626 t[2][0] = s;
627 t[2][2] = c;
628
629 m4x3_mul( m, t, m );
630 }
631
632 static inline void m4x3_rotate_z( m4x3f m, float angle )
633 {
634 m4x3f t = M4X3_IDENTITY;
635 float c, s;
636
637 c = cosf( angle );
638 s = sinf( angle );
639
640 t[0][0] = c;
641 t[0][1] = s;
642 t[1][0] = -s;
643 t[1][1] = c;
644
645 m4x3_mul( m, t, m );
646 }
647
648 static inline void m4x3_expand( m4x3f m, m4x4f d )
649 {
650 v3_copy( m[0], d[0] );
651 v3_copy( m[1], d[1] );
652 v3_copy( m[2], d[2] );
653 v3_copy( m[3], d[3] );
654 d[0][3] = 0.0f;
655 d[1][3] = 0.0f;
656 d[2][3] = 0.0f;
657 d[3][3] = 1.0f;
658 }
659
660 static inline void m4x3_expand_aabb_point( m4x3f m, boxf box, v3f point )
661 {
662 v3f v;
663 m4x3_mulv( m, point, v );
664
665 v3_minv( box[0], v, box[0] );
666 v3_maxv( box[1], v, box[1] );
667 }
668
669 static inline void box_concat( boxf a, boxf b )
670 {
671 v3_minv( a[0], b[0], a[0] );
672 v3_maxv( a[1], b[1], a[1] );
673 }
674
675 static inline void box_copy( boxf a, boxf b )
676 {
677 v3_copy( a[0], b[0] );
678 v3_copy( a[1], b[1] );
679 }
680
681 static inline void m4x3_transform_aabb( m4x3f m, boxf box )
682 {
683 v3f a; v3f b;
684
685 v3_copy( box[0], a );
686 v3_copy( box[1], b );
687 v3_fill( box[0], INFINITY );
688 v3_fill( box[1], -INFINITY );
689
690 m4x3_expand_aabb_point( m, box, a );
691 m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], a[2] } );
692 m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], a[2] } );
693 m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], a[2] } );
694 m4x3_expand_aabb_point( m, box, b );
695 m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], b[2] } );
696 m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], b[2] } );
697 m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], b[2] } );
698 }
699
700 /*
701 * Matrix 4x4
702 */
703
704 #define M4X4_IDENTITY {{1.0f, 0.0f, 0.0f, 0.0f },\
705 { 0.0f, 1.0f, 0.0f, 0.0f },\
706 { 0.0f, 0.0f, 1.0f, 0.0f },\
707 { 0.0f, 0.0f, 0.0f, 1.0f }}
708
709 static void m4x4_projection( m4x4f m, float angle,
710 float ratio, float near, float far )
711 {
712 float scale = tanf( angle * 0.5f * VG_PIf / 180.0f ) * near,
713 r = ratio * scale,
714 l = -r,
715 t = scale,
716 b = -t;
717
718 m[0][0] = 2.0f * near / (r - l);
719 m[0][1] = 0.0f;
720 m[0][2] = 0.0f;
721 m[0][3] = 0.0f;
722 m[1][0] = 0.0f;
723 m[1][1] = 2.0f * near / (t - b);
724 m[1][2] = 0.0f;
725 m[1][3] = 0.0f;
726 m[2][0] = (r + l) / (r - l);
727 m[2][1] = (t + b) / (t - b);
728 m[2][2] = -(far + near) / (far - near);
729 m[2][3] = -1.0f;
730 m[3][0] = 0.0f;
731 m[3][1] = 0.0f;
732 m[3][2] = -2.0f * far * near / (far - near);
733 m[3][3] = 0.0f;
734 }
735
736 static void m4x4_translate( m4x4f m, v3f v )
737 {
738 v4_muladds( m[3], m[0], v[0], m[3] );
739 v4_muladds( m[3], m[1], v[1], m[3] );
740 v4_muladds( m[3], m[2], v[2], m[3] );
741 }
742
743 static inline void m4x4_copy( m4x4f a, m4x4f b )
744 {
745 v4_copy( a[0], b[0] );
746 v4_copy( a[1], b[1] );
747 v4_copy( a[2], b[2] );
748 v4_copy( a[3], b[3] );
749 }
750
751 static inline void m4x4_identity( m4x4f a )
752 {
753 m4x4f id = M4X4_IDENTITY;
754 m4x4_copy( id, a );
755 }
756
757 static inline void m4x4_mul( m4x4f a, m4x4f b, m4x4f d )
758 {
759 float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3],
760 a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3],
761 a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3],
762 a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3],
763
764 b00 = b[0][0], b01 = b[0][1], b02 = b[0][2], b03 = b[0][3],
765 b10 = b[1][0], b11 = b[1][1], b12 = b[1][2], b13 = b[1][3],
766 b20 = b[2][0], b21 = b[2][1], b22 = b[2][2], b23 = b[2][3],
767 b30 = b[3][0], b31 = b[3][1], b32 = b[3][2], b33 = b[3][3];
768
769 d[0][0] = a00*b00 + a10*b01 + a20*b02 + a30*b03;
770 d[0][1] = a01*b00 + a11*b01 + a21*b02 + a31*b03;
771 d[0][2] = a02*b00 + a12*b01 + a22*b02 + a32*b03;
772 d[0][3] = a03*b00 + a13*b01 + a23*b02 + a33*b03;
773 d[1][0] = a00*b10 + a10*b11 + a20*b12 + a30*b13;
774 d[1][1] = a01*b10 + a11*b11 + a21*b12 + a31*b13;
775 d[1][2] = a02*b10 + a12*b11 + a22*b12 + a32*b13;
776 d[1][3] = a03*b10 + a13*b11 + a23*b12 + a33*b13;
777 d[2][0] = a00*b20 + a10*b21 + a20*b22 + a30*b23;
778 d[2][1] = a01*b20 + a11*b21 + a21*b22 + a31*b23;
779 d[2][2] = a02*b20 + a12*b21 + a22*b22 + a32*b23;
780 d[2][3] = a03*b20 + a13*b21 + a23*b22 + a33*b23;
781 d[3][0] = a00*b30 + a10*b31 + a20*b32 + a30*b33;
782 d[3][1] = a01*b30 + a11*b31 + a21*b32 + a31*b33;
783 d[3][2] = a02*b30 + a12*b31 + a22*b32 + a32*b33;
784 d[3][3] = a03*b30 + a13*b31 + a23*b32 + a33*b33;
785 }
786
787 /*
788 * Planes (double precision)
789 */
790 static inline void tri_to_plane( double a[3], double b[3],
791 double c[3], double p[4] )
792 {
793 double edge0[3];
794 double edge1[3];
795 double l;
796
797 edge0[0] = b[0] - a[0];
798 edge0[1] = b[1] - a[1];
799 edge0[2] = b[2] - a[2];
800
801 edge1[0] = c[0] - a[0];
802 edge1[1] = c[1] - a[1];
803 edge1[2] = c[2] - a[2];
804
805 p[0] = edge0[1] * edge1[2] - edge0[2] * edge1[1];
806 p[1] = edge0[2] * edge1[0] - edge0[0] * edge1[2];
807 p[2] = edge0[0] * edge1[1] - edge0[1] * edge1[0];
808
809 l = sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
810 p[3] = (p[0] * a[0] + p[1] * a[1] + p[2] * a[2]) / l;
811
812 p[0] = p[0] / l;
813 p[1] = p[1] / l;
814 p[2] = p[2] / l;
815 }
816
817 static inline int plane_intersect( double a[4], double b[4],
818 double c[4], double p[4] )
819 {
820 double const epsilon = 1e-8f;
821
822 double x[3];
823 double d;
824
825 x[0] = a[1] * b[2] - a[2] * b[1];
826 x[1] = a[2] * b[0] - a[0] * b[2];
827 x[2] = a[0] * b[1] - a[1] * b[0];
828
829 d = x[0] * c[0] + x[1] * c[1] + x[2] * c[2];
830
831 if( d < epsilon && d > -epsilon ) return 0;
832
833 p[0] = (b[1] * c[2] - b[2] * c[1]) * -a[3];
834 p[1] = (b[2] * c[0] - b[0] * c[2]) * -a[3];
835 p[2] = (b[0] * c[1] - b[1] * c[0]) * -a[3];
836
837 p[0] += (c[1] * a[2] - c[2] * a[1]) * -b[3];
838 p[1] += (c[2] * a[0] - c[0] * a[2]) * -b[3];
839 p[2] += (c[0] * a[1] - c[1] * a[0]) * -b[3];
840
841 p[0] += (a[1] * b[2] - a[2] * b[1]) * -c[3];
842 p[1] += (a[2] * b[0] - a[0] * b[2]) * -c[3];
843 p[2] += (a[0] * b[1] - a[1] * b[0]) * -c[3];
844
845 p[0] = -p[0] / d;
846 p[1] = -p[1] / d;
847 p[2] = -p[2] / d;
848
849 return 1;
850 }
851
852 static inline double plane_polarity( double p[4], double a[3] )
853 {
854 return
855 (a[0] * p[0] + a[1] * p[1] + a[2] * p[2])
856 -(p[0]*p[3] * p[0] + p[1]*p[3] * p[1] + p[2]*p[3] * p[2])
857 ;
858 }