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 libc3.
11 libc3 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 libc3 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 libc3. If not, see <http://www.gnu.org/licenses/>.
27 #include "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 };// older gcc <4.6 doesn't like this
49 c3vec2 c3vec2f(c3f x, c3f y)
51 c3vec2 v;// = { .x = x, .y = y };// older gcc <4.6 doesn't like this
56 /******************** c3vec2 ASSIGNMENT OPERATORS ******************/
58 c3vec2 c3vec2_add(c3vec2 a, const c3vec2 v)
65 c3vec2 c3vec2_sub(c3vec2 a, const c3vec2 v)
72 c3vec2 c3vec2_mulf(c3vec2 a, c3f d)
79 c3vec2 c3vec2_divf(c3vec2 a, c3f d)
87 /******************** c3vec2 SPECIAL FUNCTIONS ********************/
90 c3f c3vec2_length2(const c3vec2 a)
92 return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY];
95 c3f c3vec2_length(const c3vec2 a)
97 return (c3f) sqrt(c3vec2_length2(a));
100 c3vec2 c3vec2_normalize(const c3vec2 a) // it is up to caller to avoid divide-by-zero
102 return c3vec2_divf(a, c3vec2_length(a));
105 c3vec2 c3vec2_apply(c3vec2 a, V_FCT_PTR fct)
107 a.n[VX] = fct(a.n[VX]);
108 a.n[VY] = fct(a.n[VY]);
113 /******************** c3vec2 FRIENDS *****************************/
115 c3vec2 c3vec2_minus(const c3vec2 a)
117 return c3vec2f(-a.n[VX],-a.n[VY]);
120 c3vec2 c3mat3_mulv2(const c3mat3p a, const c3vec2 v)
124 av.n[VX] = a->v[0].n[VX]*v.n[VX] + a->v[0].n[VY]*v.n[VY] + a->v[0].n[VZ];
125 av.n[VY] = a->v[1].n[VX]*v.n[VX] + a->v[1].n[VY]*v.n[VY] + a->v[1].n[VZ];
126 // av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ];
131 c3vec2 c3vec2_mulm3(const c3vec2 v, const c3mat3p a)
133 c3mat3 t = c3mat3_transpose(a);
134 return c3mat3_mulv2(&t, v);
137 c3vec3 c3mat3_mulv3(const c3mat3p a, const c3vec3 v)
141 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];
142 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];
143 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];
148 c3vec3 c3vec3_mulm3(const c3vec3 v, const c3mat3p a)
150 c3mat3 t = c3mat3_transpose(a);
151 return c3mat3_mulv3(&t, v);
154 c3f c3vec2_dot(const c3vec2 a, const c3vec2 b)
156 return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY];
159 c3vec3 c3vec2_cross(const c3vec2 a, const c3vec2 b)
161 return c3vec3f(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]);
164 int c3vec2_equal(const c3vec2 a, const c3vec2 b)
166 return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]);
170 c3vec2 c3vec2_min(const c3vec2 a, const c3vec2 b)
172 return c3vec2f(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]));
175 c3vec2 c3vec2_max(const c3vec2 a, const c3vec2 b)
177 return c3vec2f(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]));
180 c3vec2 c3vec2_prod(const c3vec2 a, const c3vec2 b)
182 return c3vec2f(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]);
185 /****************************************************************
187 * c3vec3 Member functions *
189 ****************************************************************/
195 c3vec3 n;// = { .x = 0, .y = 0, .z = 0 };// older gcc <4.6 doesn't like this
200 c3vec3 c3vec3f(c3f x, c3f y, c3f z)
202 c3vec3 v;// = { .x = x, .y = y, .z = z };// older gcc <4.6 doesn't like this
203 v.x = x; v.y = y; v.z = z;
207 c3vec3 c3vec3_vec2f(const c3vec2 v, c3f d)
209 c3vec3 n;// = { .x = v.x, .y = v.y, .z = d }; // older gcc <4.6 doesn't like this
210 n.x = v.x; n.y = v.y; n.z = d;
214 c3vec3 c3vec3_vec2(const c3vec2 v)
216 return c3vec3_vec2f(v, 1.0);
219 c3vec3 c3vec3_vec4(const c3vec4 v) // it is up to caller to avoid divide-by-zero
222 n.n[VX] = v.n[VX] / v.n[VW];
223 n.n[VY] = v.n[VY] / v.n[VW];
224 n.n[VZ] = v.n[VZ] / v.n[VW];
229 c3vec3 c3vec3_add(c3vec3 a, const c3vec3 v)
237 c3vec3 c3vec3_sub(c3vec3 a, const c3vec3 v)
245 c3vec3 c3vec3_mulf(c3vec3 a, c3f d)
253 c3vec3 c3vec3_divf(c3vec3 a, c3f d)
264 c3f c3vec3_length2(const c3vec3 a)
266 return a.n[VX]*a.n[VX] + a.n[VY]*a.n[VY] + a.n[VZ]*a.n[VZ];
269 c3f c3vec3_length(const c3vec3 a)
271 return (c3f) sqrt(c3vec3_length2(a));
274 c3vec3 c3vec3_normalize(const c3vec3 a) // it is up to caller to avoid divide-by-zero
276 return c3vec3_divf(a, c3vec3_length(a));
279 c3vec3 c3vec3_homogenize(c3vec3 a) // it is up to caller to avoid divide-by-zero
287 c3vec3 c3vec3_apply(c3vec3 a, V_FCT_PTR fct)
289 a.n[VX] = fct(a.n[VX]);
290 a.n[VY] = fct(a.n[VY]);
291 a.n[VZ] = fct(a.n[VZ]);
297 c3vec3 c3vec3_minus(const c3vec3 a)
299 return c3vec3f(-a.n[VX],-a.n[VY],-a.n[VZ]);
303 c3vec3 operator*(const c3mat4 &a, const c3vec3 &v)
308 c3vec3 operator*(const c3vec3 &v, c3mat4 &a)
310 return a.transpose()*v;
314 c3f c3vec3_dot(const c3vec3 a, const c3vec3 b)
316 return a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ];
319 c3vec3 c3vec3_cross(const c3vec3 a, const c3vec3 b)
322 c3vec3f(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY],
323 a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ],
324 a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]);
327 int c3vec3_equal(const c3vec3 a, const c3vec3 b)
329 return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]);
333 c3vec3 c3vec3_min(const c3vec3 a, const c3vec3 b)
336 MIN(a.n[VX], b.n[VX]),
337 MIN(a.n[VY], b.n[VY]),
338 MIN(a.n[VZ], b.n[VZ]));
341 c3vec3 c3vec3_max(const c3vec3 a, const c3vec3 b)
344 MAX(a.n[VX], b.n[VX]),
345 MAX(a.n[VY], b.n[VY]),
346 MAX(a.n[VZ], b.n[VZ]));
349 c3vec3 c3vec3_prod(const c3vec3 a, const c3vec3 b)
351 return c3vec3f(a.n[VX]*b.n[VX], a.n[VY]*b.n[VY], a.n[VZ]*b.n[VZ]);
354 c3vec3 c3vec3_polar(const c3vec3 a)
356 c3f l = c3vec3_length(a);
357 c3f phi = atan2(a.y, a.x);
358 c3f theta = acos(a.z / l);
359 return c3vec3f(phi, theta, l);
362 /****************************************************************
364 * c3vec4 Member functions *
366 ****************************************************************/
372 c3vec4 n ;//= { .x = 0, .y = 0, .z = 0, .w = 1.0 }; // older gcc <4.6 doesn't like this
373 n.x = n.y = n.z = 0; n.w = 1.0;
377 c3vec4 c3vec4f(c3f x, c3f y, c3f z, c3f w)
379 c3vec4 n;// = { .x = x, .y = y, .z = z, .w = w }; // older gcc <4.6 doesn't like this
380 n.x =x; n.y = y; n.z = z; n.w = w;
384 c3vec4 c3vec4_vec3(const c3vec3 v)
386 return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], 1.0);
389 c3vec4 c3vec4_vec3f(const c3vec3 v, c3f d)
391 return c3vec4f(v.n[VX], v.n[VY], v.n[VZ], d);
394 // ASSIGNMENT OPERATORS
396 c3vec4 c3vec4_add(c3vec4 a, const c3vec4 v)
405 c3vec4 c3vec4_sub(c3vec4 a, const c3vec4 v)
414 c3vec4 c3vec4_mulf(c3vec4 a, c3f d)
423 c3vec4 c3vec4_divf(c3vec4 a, c3f d)
435 c3f c3vec4_length2(const c3vec4 a)
437 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];
440 c3f c3vec4_length(const c3vec4 a)
442 return (c3f) sqrt(c3vec4_length2(a));
445 c3vec4 c3vec4_normalize(c3vec4 a) // it is up to caller to avoid divide-by-zero
447 return c3vec4_divf(a, c3vec4_length(a));
450 c3vec4 c3vec4_homogenize(c3vec4 a) // it is up to caller to avoid divide-by-zero
459 c3vec4 c3vec4_apply(c3vec4 a, V_FCT_PTR fct)
461 a.n[VX] = fct(a.n[VX]);
462 a.n[VY] = fct(a.n[VY]);
463 a.n[VZ] = fct(a.n[VZ]);
464 a.n[VW] = fct(a.n[VW]);
468 c3vec4 c3mat4_mulv4(const c3mat4p a, const c3vec4 v)
471 a->v[i].n[0]*v.n[VX] + \
472 a->v[i].n[1]*v.n[VY] + \
473 a->v[i].n[2]*v.n[VZ] + \
476 return c3vec4f(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3));
481 c3vec4 c3vec4_mulm4(const c3vec4 v, const c3mat4p a)
483 c3mat4 m = c3mat4_transpose(a);
484 return c3mat4_mulv4(&m, v);
487 c3vec3 c3mat4_mulv3(const c3mat4p a, const c3vec3 v)
489 return c3vec3_vec4(c3mat4_mulv4(a, c3vec4_vec3(v)));
492 c3vec4 c3vec4_minus(const c3vec4 a)
494 return c3vec4f(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]);
497 int c3vec4_equal(const c3vec4 a, const c3vec4 b)
500 (a.n[VX] == b.n[VX]) &&
501 (a.n[VY] == b.n[VY]) &&
502 (a.n[VZ] == b.n[VZ]) &&
503 (a.n[VW] == b.n[VW]);
506 c3vec4 c3vec4_min(const c3vec4 a, const c3vec4 b)
509 MIN(a.n[VX], b.n[VX]),
510 MIN(a.n[VY], b.n[VY]),
511 MIN(a.n[VZ], b.n[VZ]),
512 MIN(a.n[VW], b.n[VW]));
515 c3vec4 c3vec4_max(const c3vec4 a, const c3vec4 b)
518 MAX(a.n[VX], b.n[VX]),
519 MAX(a.n[VY], b.n[VY]),
520 MAX(a.n[VZ], b.n[VZ]),
521 MAX(a.n[VW], b.n[VW]));
524 c3vec4 c3vec4_prod(const c3vec4 a, const c3vec4 b)
533 /****************************************************************
535 * c3mat3 member functions *
537 ****************************************************************/
541 c3mat3 c3mat3_identity()
546 c3mat3 c3mat3_vec3(const c3vec3 v0, const c3vec3 v1, const c3vec3 v2)
548 c3mat3 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2 };
552 c3mat3p c3mat3_add(const c3mat3p a, const c3mat3p m)
554 a->v[0] = c3vec3_add(a->v[0], m->v[0]);
555 a->v[1] = c3vec3_add(a->v[1], m->v[1]);
556 a->v[2] = c3vec3_add(a->v[2], m->v[2]);
560 c3mat3p c3mat3_sub(const c3mat3p a, const c3mat3p m)
562 a->v[0] = c3vec3_sub(a->v[0], m->v[0]);
563 a->v[1] = c3vec3_sub(a->v[1], m->v[1]);
564 a->v[2] = c3vec3_sub(a->v[2], m->v[2]);
568 c3mat3p c3mat3_mulf(const c3mat3p a, c3f d)
570 a->v[0] = c3vec3_mulf(a->v[0], d);
571 a->v[1] = c3vec3_mulf(a->v[1], d);
572 a->v[2] = c3vec3_mulf(a->v[2], d);
576 c3mat3p c3mat3_divf(const c3mat3p a, c3f d)
578 a->v[0] = c3vec3_divf(a->v[0], d);
579 a->v[1] = c3vec3_divf(a->v[1], d);
580 a->v[2] = c3vec3_divf(a->v[2], d);
586 c3mat3 c3mat3_transpose(const c3mat3p a)
589 c3vec3f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0]),
590 c3vec3f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1]),
591 c3vec3f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2]));
594 c3mat3 c3mat3_inverse(const c3mat3p m) // Gauss-Jordan elimination with partial pivoting
596 c3mat3 a = *m; // As a evolves from original mat into identity
597 c3mat3 b = c3mat3_identity(); // b evolves from identity into inverse(a)
600 // Loop over cols of a from left to right, eliminating above and below diag
601 for (j = 0; j < 3; j++) { // Find largest pivot in column j among rows j..2
602 i1 = j; // Row with largest pivot candidate
603 for (i = j + 1; i < 3; i++)
604 if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
607 // Swap rows i1 and j in a and b to put pivot on diagonal
609 _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]);
610 _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; //swap(b.v[i1], b.v[j]);
612 // Scale row j to have a unit diagonal
613 if (a.v[j].n[j] == 0.) {
614 // VEC_ERROR("c3mat3::inverse: singular matrix; can't invert\n");
618 b.v[j] = c3vec3_divf(b.v[j], a.v[j].n[j]);
619 a.v[j] = c3vec3_divf(a.v[j], a.v[j].n[j]);
621 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
622 for (i = 0; i < 3; i++)
624 b.v[i] = c3vec3_sub(b.v[i], c3vec3_mulf(b.v[j], a.v[i].n[j]));
625 a.v[i] = c3vec3_sub(a.v[i], c3vec3_mulf(a.v[j], a.v[i].n[j]));
632 c3mat3p c3mat3_apply(c3mat3p a, V_FCT_PTR fct)
634 a->v[0] = c3vec3_apply(a->v[0], fct);
635 a->v[1] = c3vec3_apply(a->v[1], fct);
636 a->v[2] = c3vec3_apply(a->v[2], fct);
641 c3mat3 c3mat3_minus(const c3mat3p a)
644 c3vec3_minus(a->v[0]),
645 c3vec3_minus(a->v[1]),
646 c3vec3_minus(a->v[2]));
649 c3mat3 c3mat3_mul(const c3mat3p a, const c3mat3p b)
651 #define ROWCOL(i, j) \
652 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]
655 c3vec3f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)),
656 c3vec3f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)),
657 c3vec3f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2)));
662 int c3mat3_equal(const c3mat3p a, const c3mat3p b)
665 c3vec3_equal(a->v[0], b->v[0]) &&
666 c3vec3_equal(a->v[1], b->v[1]) &&
667 c3vec3_equal(a->v[2], b->v[2]);
670 /****************************************************************
672 * c3mat4 member functions *
674 ****************************************************************/
678 c3mat4 c3mat4_identity()
683 c3mat4 c3mat4_vec4(const c3vec4 v0, const c3vec4 v1, const c3vec4 v2, const c3vec4 v3)
685 c3mat4 m = { .v[0] = v0, .v[1] = v1, .v[2] = v2, .v[3] = v3 };
690 c3f a00, c3f a01, c3f a02, c3f a03,
691 c3f a10, c3f a11, c3f a12, c3f a13,
692 c3f a20, c3f a21, c3f a22, c3f a23,
693 c3f a30, c3f a31, c3f a32, c3f a33 )
696 m.v[0] = c3vec4f(a00, a01, a01, a03);
697 m.v[1] = c3vec4f(a10, a11, a11, a13);
698 m.v[2] = c3vec4f(a20, a21, a21, a23);
699 m.v[3] = c3vec4f(a30, a31, a21, a33);
703 c3mat4p c3mat4p_add(c3mat4p a, const c3mat4p m)
705 a->v[0] = c3vec4_add(a->v[0], m->v[0]);
706 a->v[1] = c3vec4_add(a->v[1], m->v[1]);
707 a->v[2] = c3vec4_add(a->v[2], m->v[2]);
708 a->v[3] = c3vec4_add(a->v[3], m->v[3]);
712 c3mat4p c3mat4p_sub(c3mat4p a, const c3mat4p m)
714 a->v[0] = c3vec4_sub(a->v[0], m->v[0]);
715 a->v[1] = c3vec4_sub(a->v[1], m->v[1]);
716 a->v[2] = c3vec4_sub(a->v[2], m->v[2]);
717 a->v[3] = c3vec4_sub(a->v[3], m->v[3]);
721 c3mat4p c3mat4p_mulf(c3mat4p a, c3f d)
723 a->v[0] = c3vec4_mulf(a->v[0], d);
724 a->v[1] = c3vec4_mulf(a->v[1], d);
725 a->v[2] = c3vec4_mulf(a->v[2], d);
726 a->v[3] = c3vec4_mulf(a->v[3], d);
730 c3mat4p c3mat4p_divf(c3mat4p a, c3f d)
732 a->v[0] = c3vec4_divf(a->v[0], d);
733 a->v[1] = c3vec4_divf(a->v[1], d);
734 a->v[2] = c3vec4_divf(a->v[2], d);
735 a->v[3] = c3vec4_divf(a->v[3], d);
739 // SPECIAL FUNCTIONS;
741 c3mat4 c3mat4_transpose(const c3mat4p a)
744 c3vec4f(a->v[0].n[0], a->v[1].n[0], a->v[2].n[0], a->v[3].n[0]),
745 c3vec4f(a->v[0].n[1], a->v[1].n[1], a->v[2].n[1], a->v[3].n[1]),
746 c3vec4f(a->v[0].n[2], a->v[1].n[2], a->v[2].n[2], a->v[3].n[2]),
747 c3vec4f(a->v[0].n[3], a->v[1].n[3], a->v[2].n[3], a->v[3].n[3]));
750 c3mat4 c3mat4_inverse(const c3mat4p m) // Gauss-Jordan elimination with partial pivoting
752 c3mat4 a = *m; // As a evolves from original mat into identity
753 c3mat4 b = identity3D(); // b evolves from identity into inverse(a)
756 // Loop over cols of a from left to right, eliminating above and below diag
757 for (j = 0; j < 4; j++) { // Find largest pivot in column j among rows j..3
758 i1 = j; // Row with largest pivot candidate
759 for (i = j + 1; i < 4; i++)
760 if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
763 // Swap rows i1 and j in a and b to put pivot on diagonal
765 _s = a.v[i1]; a.v[i1] = a.v[j]; a.v[j] = _s; // swap(a.v[i1], a.v[j]);
766 _s = b.v[i1]; b.v[i1] = b.v[j]; b.v[j] = _s; // swap(b.v[i1], b.v[j]);
768 // Scale row j to have a unit diagonal
769 if (a.v[j].n[j] == 0.) {
770 // VEC_ERROR("c3mat4::inverse: singular matrix; can't invert\n");
773 b.v[j] = c3vec4_divf(b.v[j], a.v[j].n[j]);
774 a.v[j] = c3vec4_divf(a.v[j], a.v[j].n[j]);
776 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
777 for (i = 0; i < 4; i++)
779 b.v[i] = c3vec4_sub(b.v[i], c3vec4_mulf(b.v[j], a.v[i].n[j]));
780 a.v[i] = c3vec4_sub(a.v[i], c3vec4_mulf(a.v[j], a.v[i].n[j]));
787 c3mat4p c3mat4p_apply(c3mat4p a, V_FCT_PTR fct)
789 a->v[0] = c3vec4_apply(a->v[0], fct);
790 a->v[1] = c3vec4_apply(a->v[1], fct);
791 a->v[2] = c3vec4_apply(a->v[2], fct);
792 a->v[3] = c3vec4_apply(a->v[3], fct);
796 c3mat4p c3mat4p_swap_rows(c3mat4p a, int i, int j)
806 c3mat4p c3mat4p_swap_cols(c3mat4p a, int i, int j)
810 for (int k = 0; k < 4; k++) {
812 a->v[k].n[i] = a->v[k].n[j];
821 c3mat4 c3mat4_minus(const c3mat4p a)
824 c3vec4_minus(a->v[0]),
825 c3vec4_minus(a->v[1]),
826 c3vec4_minus(a->v[2]),
827 c3vec4_minus(a->v[3]));
830 c3mat4 c3mat4_add(const c3mat4p a, const c3mat4p b)
833 c3vec4_add(a->v[0], b->v[0]),
834 c3vec4_add(a->v[1], b->v[1]),
835 c3vec4_add(a->v[2], b->v[2]),
836 c3vec4_add(a->v[3], b->v[3]));
839 c3mat4 c3mat4_sub(const c3mat4p a, const c3mat4p b)
842 c3vec4_sub(a->v[0], b->v[0]),
843 c3vec4_sub(a->v[1], b->v[1]),
844 c3vec4_sub(a->v[2], b->v[2]),
845 c3vec4_sub(a->v[3], b->v[3]));
848 c3mat4 c3mat4_mul(const c3mat4p a, const c3mat4p b)
850 #define ROWCOL(i, j) \
851 a->v[i].n[0]*b->v[0].n[j] + \
852 a->v[i].n[1]*b->v[1].n[j] + \
853 a->v[i].n[2]*b->v[2].n[j] + \
854 a->v[i].n[3]*b->v[3].n[j]
857 c3vec4f(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
858 c3vec4f(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
859 c3vec4f(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
860 c3vec4f(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
866 c3mat4 c3mat4_mulf(const c3mat4p a, c3f d)
869 return *c3mat4p_mulf(&r, d);
872 c3mat4 c3mat4_divf(const c3mat4p a, c3f d)
875 return *c3mat4p_divf(&r, d);
878 int c3mat4_equal(const c3mat4p a, const c3mat4p b)
880 return !memcmp(a->n, b->n, sizeof(a->n));
883 c3vec4_equal(a->v[0], b->v[0]) &&
884 c3vec4_equal(a->v[1], b->v[1]) &&
885 c3vec4_equal(a->v[2], b->v[2]) &&
886 c3vec4_equal(a->v[3], b->v[3]);
890 /****************************************************************
892 * 2D functions and 3D functions *
894 ****************************************************************/
899 c3vec3f(1.0, 0.0, 0.0),
900 c3vec3f(0.0, 1.0, 0.0),
901 c3vec3f(0.0, 0.0, 1.0));
904 c3mat3 translation2D(const c3vec2 v)
907 c3vec3f(1.0, 0.0, v.n[VX]),
908 c3vec3f(0.0, 1.0, v.n[VY]),
909 c3vec3f(0.0, 0.0, 1.0));
912 c3mat3 rotation2D(const c3vec2 Center, c3f angleDeg)
914 c3f angleRad = (c3f) (angleDeg * M_PI / 180.0);
915 c3f c = (c3f) cos(angleRad);
916 c3f s = (c3f) sin(angleRad);
919 c3vec3f(c, -s, Center.n[VX] * (1.0f-c) + Center.n[VY] * s),
920 c3vec3f(s, c, Center.n[VY] * (1.0f-c) - Center.n[VX] * s),
921 c3vec3f(0.0, 0.0, 1.0));
924 c3mat3 scaling2D(const c3vec2 scaleVector)
927 c3vec3f(scaleVector.n[VX], 0.0, 0.0),
928 c3vec3f(0.0, scaleVector.n[VY], 0.0),
929 c3vec3f(0.0, 0.0, 1.0));
935 c3vec4f(1.0, 0.0, 0.0, 0.0),
936 c3vec4f(0.0, 1.0, 0.0, 0.0),
937 c3vec4f(0.0, 0.0, 1.0, 0.0),
938 c3vec4f(0.0, 0.0, 0.0, 1.0));
941 c3mat4 translation3D(const c3vec3 v)
944 c3vec4f(1.0, 0.0, 0.0, v.n[VX]),
945 c3vec4f(0.0, 1.0, 0.0, v.n[VY]),
946 c3vec4f(0.0, 0.0, 1.0, v.n[VZ]),
947 c3vec4f(0.0, 0.0, 0.0, 1.0));
950 c3mat4 rotation3D(const c3vec3 Axis, c3f angleDeg)
952 c3f angleRad = (c3f) (angleDeg * M_PI / 180.0);
953 c3f c = (c3f) cos(angleRad);
954 c3f s = (c3f) sin(angleRad);
957 c3vec3 axis = c3vec3_normalize(Axis);
960 c3vec4f(t * axis.n[VX] * axis.n[VX] + c,
961 t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ],
962 t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY],
964 c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ],
965 t * axis.n[VY] * axis.n[VY] + c,
966 t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX],
968 c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY],
969 t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX],
970 t * axis.n[VZ] * axis.n[VZ] + c,
972 c3vec4f(0.0, 0.0, 0.0, 1.0));
975 c3mat4 rotation3Drad(const c3vec3 Axis, c3f angleRad)
977 c3f c = (c3f) cos(angleRad);
978 c3f s = (c3f) sin(angleRad);
981 c3vec3 axis = c3vec3_normalize(Axis);
984 c3vec4f(t * axis.n[VX] * axis.n[VX] + c,
985 t * axis.n[VX] * axis.n[VY] - s * axis.n[VZ],
986 t * axis.n[VX] * axis.n[VZ] + s * axis.n[VY],
988 c3vec4f(t * axis.n[VX] * axis.n[VY] + s * axis.n[VZ],
989 t * axis.n[VY] * axis.n[VY] + c,
990 t * axis.n[VY] * axis.n[VZ] - s * axis.n[VX],
992 c3vec4f(t * axis.n[VX] * axis.n[VZ] - s * axis.n[VY],
993 t * axis.n[VY] * axis.n[VZ] + s * axis.n[VX],
994 t * axis.n[VZ] * axis.n[VZ] + c,
996 c3vec4f(0.0, 0.0, 0.0, 1.0));
999 c3mat4 scaling3D(const c3vec3 scaleVector)
1002 c3vec4f(scaleVector.n[VX], 0.0, 0.0, 0.0),
1003 c3vec4f(0.0, scaleVector.n[VY], 0.0, 0.0),
1004 c3vec4f(0.0, 0.0, scaleVector.n[VZ], 0.0),
1005 c3vec4f(0.0, 0.0, 0.0, 1.0));
1008 c3mat4 perspective3D(c3f d)
1011 c3vec4f(1.0f, 0.0f, 0.0f, 0.0f),
1012 c3vec4f(0.0f, 1.0f, 0.0f, 0.0f),
1013 c3vec4f(0.0f, 0.0f, 1.0f, 0.0f),
1014 c3vec4f(0.0f, 0.0f, 1.0f/d, 0.0f));