4 Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
6 Derivative and inspiration from original C++:
7 Paul Rademacher & Jean-Francois DOUEG,
9 This file is part of simavr.
11 simavr is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 simavr is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with simavr. If not, see <http://www.gnu.org/licenses/>.
27 #include "c3/c3algebra.h"
30 #define MAX(a,b) ((a)>(b) ? (a) : (b))
31 #define MIN(a,b) ((a)<(b) ? (a) : (b))
34 /****************************************************************
36 * c3vec2 Member functions *
38 ****************************************************************/
40 /******************** c3vec2 CONSTRUCTORS ********************/
44 c3vec2 n = { .x = 0, .y = 0 };
48 c3vec2 c3vec2f(c3f x, c3f y)
50 c3vec2 v = { .x = x, .y = y };
54 /******************** c3vec2 ASSIGNMENT OPERATORS ******************/
56 c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v)
63 c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v)
70 c3vec2 c3vec2_mulf(c3vec2 a, c3f d)
77 c3vec2 c3vec2_divf(c3vec2 a, c3f d)
85 /******************** c3vec2 SPECIAL FUNCTIONS ********************/
88 c3f c3vec2_length2(const c3vec2 a)
90 return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY];
93 c3f c3vec2_length(const c3vec2 a)
95 return (c3f) sqrt(c3vec2_length2(a));
98 c3vec2 c3vec2_normalize(const c3vec2 a) // it is up to caller to avoid divide-by-zero
100 return c3vec2_divf(a, c3vec2_length(a));
103 c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct)
105 a.n[VX] = fct(a.n[VX]);
106 a.n[VY] = fct(a.n[VY]);
111 /******************** c3vec2 FRIENDS *****************************/
113 c3vec2 c3vec2_minus(const c3vec2 a)
115 return c3vec2f(-a.n[VX],-a.n[VY]);
118 c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v)
122 av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ];
123 av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ];
124 // av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ];
129 c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a)
131 c3mat3 t = c3mat3_transpose(a);
132 return c3mat3_mulv2(&t, v);
135 c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v)
139 av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ]*v.n[VZ];
140 av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ]*v.n[VZ];
141 av.n[VZ] = a->v[2].n[VX]*v.n[VX] + a->v[2].n[VY]*v.n[VY] + a->v[2].n[VZ]*v.n[VZ];
146 c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a)
148 c3mat3 t = c3mat3_transpose(a);
149 return c3mat3_mulv3(&t, v);
152 c3f c3vec2_dot(const c3vec2 a, const c3vec2 b)
154 return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY];
157 c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b)
159 return c3vec3f(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]);
162 int c3vec2_equal(const c3vec2 a, const c3vec2 b)
164 return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]);
168 c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b)
170 return c3vec2f(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]));
173 c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b)
175 return c3vec2f(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]));
178 c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b)
180 return c3vec2f(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]);
183 /****************************************************************
185 * c3vec3 Member functions *
187 ****************************************************************/
193 c3vec3 n = { .x = 0, .y = 0, .z = 0 };
197 c3vec3 c3vec3f(c3f x, c3f y, c3f z)
199 c3vec3 v = { .x = x, .y = y, .z = z };
203 c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d)
205 c3vec3 n = { .x = v.x, .y = v.y, .z = d };
209 c3vec3 c3vec3_vec2(const c3vec2 v)
211 return c3vec3_vec2f(v, 1.0);
214 c3vec3 c3vec3_vec4(const c3vec4 v) // it is up to caller to avoid divide-by-zero
217 n.n[VX] = v.n[VX] / v.n[VW];
218 n.n[VY] = v.n[VY] / v.n[VW];
219 n.n[VZ] = v.n[VZ] / v.n[VW];
224 c3vec3 c3vec3_add(c3vec3 a, const c3vec3 v)
232 c3vec3 c3vec3_sub(c3vec3 a, const c3vec3 v)
240 c3vec3 c3vec3_mulf(c3vec3 a, c3f d)
248 c3vec3 c3vec3_divf(c3vec3 a, c3f d)
259 c3f c3vec3_length2(const c3vec3 a)
261 return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ];
264 c3f c3vec3_length(const c3vec3 a)
266 return (c3f) sqrt(c3vec3_length2(a));
269 c3vec3 c3vec3_normalize(const c3vec3 a) // it is up to caller to avoid divide-by-zero
271 return c3vec3_divf(a, c3vec3_length(a));
274 c3vec3 c3vec3_homogenize(c3vec3 a) // it is up to caller to avoid divide-by-zero
282 c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct)
284 a.n[VX] = fct(a.n[VX]);
285 a.n[VY] = fct(a.n[VY]);
286 a.n[VZ] = fct(a.n[VZ]);
292 c3vec3 c3vec3_minus(const c3vec3 a)
294 return c3vec3f(-a.n[VX],-a.n[VY],-a.n[VZ]);
298 c3vec3 operator*(const c3mat4 &a, const c3vec3 &v)
303 c3vec3 operator*(const c3vec3 &v, c3mat4 &a)
305 return a.transpose()*v;
309 c3f c3vec3_dot(const c3vec3 a, const c3vec3 b)
311 return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ];
314 c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b)
317 c3vec3f(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY],
318 a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ],
319 a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]);
322 int c3vec3_equal(const c3vec3 a, const c3vec3 b)
324 return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]);
328 c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b)
331 MIN(a.n[VX], b.n[VX]),
332 MIN(a.n[VY], b.n[VY]),
333 MIN(a.n[VZ], b.n[VZ]));
336 c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b)
339 MAX(a.n[VX], b.n[VX]),
340 MAX(a.n[VY], b.n[VY]),
341 MAX(a.n[VZ], b.n[VZ]));
344 c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b)
346 return c3vec3f(a.n[VX]*b.n[VX], a.n[VY]*b.n[VY], a.n[VZ]*b.n[VZ]);
349 /****************************************************************
351 * c3vec4 Member functions *
353 ****************************************************************/
359 c3vec4 n = { .x = 0, .y = 0, .z = 0, .w = 1.0 };
363 c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w)
365 c3vec4 n = { .x = x, .y = y, .z = z, .w = w };
369 c3vec4 c3vec4_vec3(const c3vec3 v)
371 return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], 1.0);
374 c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d)
376 return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], d);
379 // ASSIGNMENT OPERATORS
381 c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v)
390 c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v)
399 c3vec4 c3vec4_mulf(c3vec4 a, c3f d)
408 c3vec4 c3vec4_divf(c3vec4 a, c3f d)
420 c3f c3vec4_length2(const c3vec4 a)
422 return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ] + a.n[VW]*a.n[VW];
425 c3f c3vec4_length(const c3vec4 a)
427 return (c3f) sqrt(c3vec4_length2(a));
430 c3vec4 c3vec4_normalize(c3vec4 a) // it is up to caller to avoid divide-by-zero
432 return c3vec4_divf(a, c3vec4_length(a));
435 c3vec4 c3vec4_homogenize(c3vec4 a) // it is up to caller to avoid divide-by-zero
444 c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct)
446 a.n[VX] = fct(a.n[VX]);
447 a.n[VY] = fct(a.n[VY]);
448 a.n[VZ] = fct(a.n[VZ]);
449 a.n[VW] = fct(a.n[VW]);
453 c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v)
456 a->v[i].n[0]*v.n[VX] + \
457 a->v[i].n[1]*v.n[VY] + \
458 a->v[i].n[2]*v.n[VZ] + \
461 return c3vec4f(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3));
466 c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a)
468 c3mat4 m = c3mat4_transpose(a);
469 return c3mat4_mulv4(&m, v);
472 c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v)
474 return c3vec3_vec4(c3mat4_mulv4(a, c3vec4_vec3(v)));
477 c3vec4 c3vec4_minus(const c3vec4 a)
479 return c3vec4f(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]);
482 int c3vec4_equal(const c3vec4 a, const c3vec4 b)
485 (a.n[VX] == b.n[VX]) &&
486 (a.n[VY] == b.n[VY]) &&
487 (a.n[VZ] == b.n[VZ]) &&
488 (a.n[VW] == b.n[VW]);
491 c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b)
494 MIN(a.n[VX], b.n[VX]),
495 MIN(a.n[VY], b.n[VY]),
496 MIN(a.n[VZ], b.n[VZ]),
497 MIN(a.n[VW], b.n[VW]));
500 c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b)
503 MAX(a.n[VX], b.n[VX]),
504 MAX(a.n[VY], b.n[VY]),
505 MAX(a.n[VZ], b.n[VZ]),
506 MAX(a.n[VW], b.n[VW]));
509 c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b)
518 /****************************************************************
520 * c3mat3 member functions *
522 ****************************************************************/
526 c3mat3 c3mat3_identity()
531 c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2)
533 c3mat3 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2 };
537 c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m)
539 a->v[0] = c3vec3_add(a->v[0], m->v[0]);
540 a->v[1] = c3vec3_add(a->v[1], m->v[1]);
541 a->v[2] = c3vec3_add(a->v[2], m->v[2]);
545 c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m)
547 a->v[0] = c3vec3_sub(a->v[0], m->v[0]);
548 a->v[1] = c3vec3_sub(a->v[1], m->v[1]);
549 a->v[2] = c3vec3_sub(a->v[2], m->v[2]);
553 c3mat3p c3mat3_mulf(const c3mat3p a, c3f d)
555 a->v[0] = c3vec3_mulf(a->v[0], d);
556 a->v[1] = c3vec3_mulf(a->v[1], d);
557 a->v[2] = c3vec3_mulf(a->v[2], d);
561 c3mat3p c3mat3_divf(const c3mat3p a, c3f d)
563 a->v[0] = c3vec3_divf(a->v[0], d);
564 a->v[1] = c3vec3_divf(a->v[1], d);
565 a->v[2] = c3vec3_divf(a->v[2], d);
571 c3mat3 c3mat3_transpose(const c3mat3p a)
574 c3vec3f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0]),
575 c3vec3f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1]),
576 c3vec3f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2]));
579 c3mat3 c3mat3_inverse(const c3mat3p m) // Gauss-Jordan elimination with partial pivoting
581 c3mat3 a = *m; // As a evolves from original mat into identity
582 c3mat3 b = c3mat3_identity(); // b evolves from identity into inverse(a)
585 // Loop over cols of a from left to right, eliminating above and below diag
586 for (j = 0; j < 3; j++) { // Find largest pivot in column j among rows j..2
587 i1 = j; // Row with largest pivot candidate
588 for (i = j + 1; i < 3; i++)
589 if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
592 // Swap rows i1 and j in a and b to put pivot on diagonal
594 _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]);
595 _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; //swap(b.v[i1], b.v[j]);
597 // Scale row j to have a unit diagonal
598 if (a.v[j].n[j] == 0.) {
599 // VEC_ERROR("c3mat3::inverse: singular matrix; can't invert\n");
603 b.v[j] = c3vec3_divf(b.v[j], a.v[j].n[j]);
604 a.v[j] = c3vec3_divf(a.v[j], a.v[j].n[j]);
606 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
607 for (i = 0; i < 3; i++)
609 b.v[i] = c3vec3_sub(b.v[i], c3vec3_mulf(b.v[j], a.v[i].n[j]));
610 a.v[i] = c3vec3_sub(a.v[i], c3vec3_mulf(a.v[j], a.v[i].n[j]));
617 c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct)
619 a->v[0] = c3vec3_apply(a->v[0], fct);
620 a->v[1] = c3vec3_apply(a->v[1], fct);
621 a->v[2] = c3vec3_apply(a->v[2], fct);
626 c3mat3 c3mat3_minus(const c3mat3p a)
629 c3vec3_minus(a->v[0]),
630 c3vec3_minus(a->v[1]),
631 c3vec3_minus(a->v[2]));
634 c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b)
636 #define ROWCOL(i, j) \
637 a->v[i].n[0]*b->v[0].n[j] + a->v[i].n[1]*b->v[1].n[j] + a->v[i].n[2]*b->v[2].n[j]
640 c3vec3f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)),
641 c3vec3f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)),
642 c3vec3f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2)));
647 int c3mat3_equal(const c3mat3p a, const c3mat3p b)
650 c3vec3_equal(a->v[0], b->v[0]) &&
651 c3vec3_equal(a->v[1], b->v[1]) &&
652 c3vec3_equal(a->v[2], b->v[2]);
655 /****************************************************************
657 * c3mat4 member functions *
659 ****************************************************************/
663 c3mat4 c3mat4_identity()
668 c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3)
670 c3mat4 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2, .v[3] = v3 };
675 c3f a00, c3f a01, c3f a02, c3f a03,
676 c3f a10, c3f a11, c3f a12, c3f a13,
677 c3f a20, c3f a21, c3f a22, c3f a23,
678 c3f a30, c3f a31, c3f a32, c3f a33 )
681 m.v[0] = c3vec4f(a00, a01, a01, a03);
682 m.v[1] = c3vec4f(a10, a11, a11, a13);
683 m.v[2] = c3vec4f(a20, a21, a21, a23);
684 m.v[3] = c3vec4f(a30, a31, a21, a33);
688 c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m)
690 a->v[0] = c3vec4_add(a->v[0], m->v[0]);
691 a->v[1] = c3vec4_add(a->v[1], m->v[1]);
692 a->v[2] = c3vec4_add(a->v[2], m->v[2]);
693 a->v[3] = c3vec4_add(a->v[3], m->v[3]);
697 c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m)
699 a->v[0] = c3vec4_sub(a->v[0], m->v[0]);
700 a->v[1] = c3vec4_sub(a->v[1], m->v[1]);
701 a->v[2] = c3vec4_sub(a->v[2], m->v[2]);
702 a->v[3] = c3vec4_sub(a->v[3], m->v[3]);
706 c3mat4p c3mat4p_mulf(c3mat4p a, c3f d)
708 a->v[0] = c3vec4_mulf(a->v[0], d);
709 a->v[1] = c3vec4_mulf(a->v[1], d);
710 a->v[2] = c3vec4_mulf(a->v[2], d);
711 a->v[3] = c3vec4_mulf(a->v[3], d);
715 c3mat4p c3mat4p_divf(c3mat4p a, c3f d)
717 a->v[0] = c3vec4_divf(a->v[0], d);
718 a->v[1] = c3vec4_divf(a->v[1], d);
719 a->v[2] = c3vec4_divf(a->v[2], d);
720 a->v[3] = c3vec4_divf(a->v[3], d);
724 // SPECIAL FUNCTIONS;
726 c3mat4 c3mat4_transpose(const c3mat4p a)
729 c3vec4f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0], a->v[3].n[0]),
730 c3vec4f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1], a->v[3].n[1]),
731 c3vec4f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2], a->v[3].n[2]),
732 c3vec4f(a->v[0].n[3], a->v[1].n[3], a->v[2].n[3], a->v[3].n[3]));
735 c3mat4 c3mat4_inverse(const c3mat4p m) // Gauss-Jordan elimination with partial pivoting
737 c3mat4 a = *m; // As a evolves from original mat into identity
738 c3mat4 b = identity3D(); // b evolves from identity into inverse(a)
741 // Loop over cols of a from left to right, eliminating above and below diag
742 for (j = 0; j < 4; j++) { // Find largest pivot in column j among rows j..3
743 i1 = j; // Row with largest pivot candidate
744 for (i = j + 1; i < 4; i++)
745 if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
748 // Swap rows i1 and j in a and b to put pivot on diagonal
750 _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]);
751 _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; // swap(b.v[i1], b.v[j]);
753 // Scale row j to have a unit diagonal
754 if (a.v[j].n[j] == 0.) {
755 // VEC_ERROR("c3mat4::inverse: singular matrix; can't invert\n");
758 b.v[j] = c3vec4_divf(b.v[j], a.v[j].n[j]);
759 a.v[j] = c3vec4_divf(a.v[j], a.v[j].n[j]);
761 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
762 for (i = 0; i < 4; i++)
764 b.v[i] = c3vec4_sub(b.v[i], c3vec4_mulf(b.v[j], a.v[i].n[j]));
765 a.v[i] = c3vec4_sub(a.v[i], c3vec4_mulf(a.v[j], a.v[i].n[j]));
772 c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct)
774 a->v[0] = c3vec4_apply(a->v[0], fct);
775 a->v[1] = c3vec4_apply(a->v[1], fct);
776 a->v[2] = c3vec4_apply(a->v[2], fct);
777 a->v[3] = c3vec4_apply(a->v[3], fct);
781 c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j)
791 c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j)
795 for (int k = 0; k < 4; k++) {
797 a->v[k].n[i] = a->v[k].n[j];
806 c3mat4 c3mat4_minus(const c3mat4p a)
809 c3vec4_minus(a->v[0]),
810 c3vec4_minus(a->v[1]),
811 c3vec4_minus(a->v[2]),
812 c3vec4_minus(a->v[3]));
815 c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b)
818 c3vec4_add(a->v[0], b->v[0]),
819 c3vec4_add(a->v[1], b->v[1]),
820 c3vec4_add(a->v[2], b->v[2]),
821 c3vec4_add(a->v[3], b->v[3]));
824 c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b)
827 c3vec4_sub(a->v[0], b->v[0]),
828 c3vec4_sub(a->v[1], b->v[1]),
829 c3vec4_sub(a->v[2], b->v[2]),
830 c3vec4_sub(a->v[3], b->v[3]));
833 c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b)
835 #define ROWCOL(i, j) \
836 a->v[i].n[0]*b->v[0].n[j] + \
837 a->v[i].n[1]*b->v[1].n[j] + \
838 a->v[i].n[2]*b->v[2].n[j] + \
839 a->v[i].n[3]*b->v[3].n[j]
842 c3vec4f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
843 c3vec4f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
844 c3vec4f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
845 c3vec4f(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
851 c3mat4 c3mat4_mulf(const c3mat4p a, c3f d)
854 return *c3mat4p_mulf(&r, d);
857 c3mat4 c3mat4_divf(const c3mat4p a, c3f d)
860 return *c3mat4p_divf(&r, d);
863 int c3mat4_equal(const c3mat4p a, const c3mat4p b)
865 return !memcmp(a->n, b->n, sizeof(a->n));
868 c3vec4_equal(a->v[0], b->v[0]) &&
869 c3vec4_equal(a->v[1], b->v[1]) &&
870 c3vec4_equal(a->v[2], b->v[2]) &&
871 c3vec4_equal(a->v[3], b->v[3]);
875 /****************************************************************
877 * 2D functions and 3D functions *
879 ****************************************************************/
884 c3vec3f(1.0, 0.0, 0.0),
885 c3vec3f(0.0, 1.0, 0.0),
886 c3vec3f(0.0, 0.0, 1.0));
889 c3mat3 translation2D(const c3vec2 v)
892 c3vec3f(1.0, 0.0, v.n[VX]),
893 c3vec3f(0.0, 1.0, v.n[VY]),
894 c3vec3f(0.0, 0.0, 1.0));
897 c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg)
899 c3f angleRad = (c3f) (angleDeg * M_PI / 180.0);
900 c3f c = (c3f) cos(angleRad);
901 c3f s = (c3f) sin(angleRad);
904 c3vec3f(c, -s, Center.n[VX] * (1.0f-c) + Center.n[VY] * s),
905 c3vec3f(s, c, Center.n[VY] * (1.0f-c) - Center.n[VX] * s),
906 c3vec3f(0.0, 0.0, 1.0));
909 c3mat3 scaling2D(const c3vec2 scaleVector)
912 c3vec3f(scaleVector.n[VX], 0.0, 0.0),
913 c3vec3f(0.0, scaleVector.n[VY], 0.0),
914 c3vec3f(0.0, 0.0, 1.0));
920 c3vec4f(1.0, 0.0, 0.0, 0.0),
921 c3vec4f(0.0, 1.0, 0.0, 0.0),
922 c3vec4f(0.0, 0.0, 1.0, 0.0),
923 c3vec4f(0.0, 0.0, 0.0, 1.0));
926 c3mat4 translation3D(const c3vec3 v)
929 c3vec4f(1.0, 0.0, 0.0, v.n[VX]),
930 c3vec4f(0.0, 1.0, 0.0, v.n[VY]),
931 c3vec4f(0.0, 0.0, 1.0, v.n[VZ]),
932 c3vec4f(0.0, 0.0, 0.0, 1.0));
935 c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg)
937 c3f angleRad = (c3f) (angleDeg * M_PI / 180.0);
938 c3f c = (c3f) cos(angleRad);
939 c3f s = (c3f) sin(angleRad);
942 c3vec3 axis = c3vec3_normalize(Axis);
945 c3vec4f(t * axis.n[VX] * axis.n[VX] + c,
946 t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ],
947 t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY],
949 c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ],
950 t * axis.n[VY] * axis.n[VY] + c,
951 t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX],
953 c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY],
954 t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX],
955 t * axis.n[VZ] * axis.n[VZ] + c,
957 c3vec4f(0.0, 0.0, 0.0, 1.0));
960 c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad)
962 c3f c = (c3f) cos(angleRad);
963 c3f s = (c3f) sin(angleRad);
966 c3vec3 axis = c3vec3_normalize(Axis);
969 c3vec4f(t * axis.n[VX] * axis.n[VX] + c,
970 t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ],
971 t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY],
973 c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ],
974 t * axis.n[VY] * axis.n[VY] + c,
975 t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX],
977 c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY],
978 t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX],
979 t * axis.n[VZ] * axis.n[VZ] + c,
981 c3vec4f(0.0, 0.0, 0.0, 1.0));
984 c3mat4 scaling3D(const c3vec3 scaleVector)
987 c3vec4f(scaleVector.n[VX], 0.0, 0.0, 0.0),
988 c3vec4f(0.0, scaleVector.n[VY], 0.0, 0.0),
989 c3vec4f(0.0, 0.0, scaleVector.n[VZ], 0.0),
990 c3vec4f(0.0, 0.0, 0.0, 1.0));
993 c3mat4 perspective3D(c3f d)
996 c3vec4f(1.0f, 0.0f, 0.0f, 0.0f),
997 c3vec4f(0.0f, 1.0f, 0.0f, 0.0f),
998 c3vec4f(0.0f, 0.0f, 1.0f, 0.0f),
999 c3vec4f(0.0f, 0.0f, 1.0f/d, 0.0f));