3 * simple math for blender code
5 * sort of cleaned up mar-01 nzc
7 * Functions here get counterparts with MTC prefixes. Basically, we phase
8 * out the calls here in favour of fully prototyped versions.
12 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version. The Blender
18 * Foundation also sells licenses for use in proprietary software under
19 * the Blender License. See http://www.blender.org/BL/ for information
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software Foundation,
29 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
32 * All rights reserved.
34 * The Original Code is: all of this file.
36 * Contributor(s): none yet.
38 * ***** END GPL/BL DUAL LICENSE BLOCK *****
41 /* ************************ FUNKTIES **************************** */
44 #include <sys/types.h>
52 #if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__)
56 #if !defined(__sgi) && !defined(WIN32)
62 #include "BLI_arithb.h"
64 /* A few small defines. Keep'em local! */
65 #define SMALL_NUMBER 1.e-8
66 #define ABS(x) ((x) < 0 ? -(x) : (x))
67 #define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
70 #if defined(WIN32) || defined(__APPLE__)
72 #define M_PI 3.14159265358979323846
73 #define M_SQRT2 1.41421356237309504880
75 #endif /* defined(WIN32) || defined(__APPLE__) */
78 float saacos(float fac)
80 if(fac<= -1.0f) return (float)M_PI;
81 else if(fac>=1.0f) return 0.0;
82 else return (float)acos(fac);
85 float sasqrt(float fac)
87 if(fac<=0.0) return 0.0;
88 return (float)sqrt(fac);
91 float Normalise(float *n)
95 d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
96 /* FLT_EPSILON is too large! A larger value causes normalise errors in a scaled down utah teapot */
97 if(d>0.0000000000001) {
110 void Crossf(float *c, float *a, float *b)
112 c[0] = a[1] * b[2] - a[2] * b[1];
113 c[1] = a[2] * b[0] - a[0] * b[2];
114 c[2] = a[0] * b[1] - a[1] * b[0];
117 float Inpf( float *v1, float *v2)
119 return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
122 /* Project v1 on v2 */
123 void Projf(float *c, float *v1, float *v2)
126 mul = Inpf(v1, v2) / Inpf(v2, v2);
133 void Mat3Transp(float mat[][3])
138 mat[0][1] = mat[1][0] ;
141 mat[0][2] = mat[2][0] ;
144 mat[1][2] = mat[2][1] ;
148 void Mat4Transp(float mat[][4])
153 mat[0][1] = mat[1][0] ;
156 mat[0][2] = mat[2][0] ;
159 mat[0][3] = mat[3][0] ;
163 mat[1][2] = mat[2][1] ;
166 mat[1][3] = mat[3][1] ;
170 mat[2][3] = mat[3][2] ;
177 * computes the inverse of mat and puts it in inverse. Returns
178 * TRUE on success (i.e. can always find a pivot) and FALSE on failure.
179 * Uses Gaussian Elimination with partial (maximal column) pivoting.
184 int Mat4Invert(float inverse[][4], float mat[][4])
192 /* Set inverse to identity */
199 /* Copy original matrix so we don't mess it up */
200 for(i = 0; i < 4; i++)
201 for(j = 0; j <4; j++)
202 tempmat[i][j] = mat[i][j];
204 for(i = 0; i < 4; i++) {
205 /* Look for row with max pivot */
206 max = ABS(tempmat[i][i]);
208 for(j = i + 1; j < 4; j++) {
209 if(ABS(tempmat[j][i]) > max) {
210 max = ABS(tempmat[j][i]);
214 /* Swap rows if necessary */
216 for( k = 0; k < 4; k++) {
217 SWAP(float, tempmat[i][k], tempmat[maxj][k]);
218 SWAP(float, inverse[i][k], inverse[maxj][k]);
222 temp = tempmat[i][i];
224 return 0; /* No non-zero pivot */
225 for(k = 0; k < 4; k++) {
226 tempmat[i][k] = (float)(tempmat[i][k]/temp);
227 inverse[i][k] = (float)(inverse[i][k]/temp);
229 for(j = 0; j < 4; j++) {
231 temp = tempmat[j][i];
232 for(k = 0; k < 4; k++) {
233 tempmat[j][k] -= (float)(tempmat[i][k]*temp);
234 inverse[j][k] -= (float)(inverse[i][k]*temp);
242 void Mat4InvertSimp(float inverse[][4], float mat[][4])
244 /* only for Matrices that have a rotation */
245 /* based at GG IV pag 205 */
248 scale= mat[0][0]*mat[0][0] + mat[1][0]*mat[1][0] + mat[2][0]*mat[2][0];
249 if(scale==0.0) return;
253 /* transpose and scale */
254 inverse[0][0]= scale*mat[0][0];
255 inverse[1][0]= scale*mat[0][1];
256 inverse[2][0]= scale*mat[0][2];
257 inverse[0][1]= scale*mat[1][0];
258 inverse[1][1]= scale*mat[1][1];
259 inverse[2][1]= scale*mat[1][2];
260 inverse[0][2]= scale*mat[2][0];
261 inverse[1][2]= scale*mat[2][1];
262 inverse[2][2]= scale*mat[2][2];
264 inverse[3][0]= -(inverse[0][0]*mat[3][0] + inverse[1][0]*mat[3][1] + inverse[2][0]*mat[3][2]);
265 inverse[3][1]= -(inverse[0][1]*mat[3][0] + inverse[1][1]*mat[3][1] + inverse[2][1]*mat[3][2]);
266 inverse[3][2]= -(inverse[0][2]*mat[3][0] + inverse[1][2]*mat[3][1] + inverse[2][2]*mat[3][2]);
268 inverse[0][3]= inverse[1][3]= inverse[2][3]= 0.0;
272 /* struct Matrix4; */
275 /* this seems to be unused.. */
277 void Mat4Inv(float *m1, float *m2)
280 /* This gets me into trouble: */
281 float mat1[3][3], mat2[3][3];
283 /* void Mat3Inv(); */
284 /* void Mat3CpyMat4(); */
285 /* void Mat4CpyMat3(); */
287 Mat3CpyMat4((float*)mat2,m2);
288 Mat3Inv((float*)mat1, (float*) mat2);
289 Mat4CpyMat3(m1, mat1);
295 float Det2x2(float a,float b,float c,float d)
303 float Det3x3(float a1, float a2, float a3,
304 float b1, float b2, float b3,
305 float c1, float c2, float c3 )
309 ans = a1 * Det2x2( b2, b3, c2, c3 )
310 - b1 * Det2x2( a2, a3, c2, c3 )
311 + c1 * Det2x2( a2, a3, b2, b3 );
316 float Det4x4(float m[][4])
319 float a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4;
341 ans = a1 * Det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4)
342 - b1 * Det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4)
343 + c1 * Det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4)
344 - d1 * Det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
350 void Mat4Adj(float out[][4], float in[][4]) /* out = ADJ(in) */
352 float a1, a2, a3, a4, b1, b2, b3, b4;
353 float c1, c2, c3, c4, d1, d2, d3, d4;
376 out[0][0] = Det3x3( b2, b3, b4, c2, c3, c4, d2, d3, d4);
377 out[1][0] = - Det3x3( a2, a3, a4, c2, c3, c4, d2, d3, d4);
378 out[2][0] = Det3x3( a2, a3, a4, b2, b3, b4, d2, d3, d4);
379 out[3][0] = - Det3x3( a2, a3, a4, b2, b3, b4, c2, c3, c4);
381 out[0][1] = - Det3x3( b1, b3, b4, c1, c3, c4, d1, d3, d4);
382 out[1][1] = Det3x3( a1, a3, a4, c1, c3, c4, d1, d3, d4);
383 out[2][1] = - Det3x3( a1, a3, a4, b1, b3, b4, d1, d3, d4);
384 out[3][1] = Det3x3( a1, a3, a4, b1, b3, b4, c1, c3, c4);
386 out[0][2] = Det3x3( b1, b2, b4, c1, c2, c4, d1, d2, d4);
387 out[1][2] = - Det3x3( a1, a2, a4, c1, c2, c4, d1, d2, d4);
388 out[2][2] = Det3x3( a1, a2, a4, b1, b2, b4, d1, d2, d4);
389 out[3][2] = - Det3x3( a1, a2, a4, b1, b2, b4, c1, c2, c4);
391 out[0][3] = - Det3x3( b1, b2, b3, c1, c2, c3, d1, d2, d3);
392 out[1][3] = Det3x3( a1, a2, a3, c1, c2, c3, d1, d2, d3);
393 out[2][3] = - Det3x3( a1, a2, a3, b1, b2, b3, d1, d2, d3);
394 out[3][3] = Det3x3( a1, a2, a3, b1, b2, b3, c1, c2, c3);
397 void Mat4InvGG(float out[][4], float in[][4]) /* from Graphic Gems I, out= INV(in) */
402 /* calculate the adjoint matrix */
408 if ( fabs( det ) < SMALL_NUMBER) {
412 /* scale the adjoint matrix to get the inverse */
416 out[i][j] = out[i][j] / det;
418 /* the last factor is not always 1. For that reason an extra division should be implemented? */
422 void Mat3Inv(float m1[][3], float m2[][3])
430 /* then determinant old matrix! */
431 det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
432 -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
433 +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
444 void Mat3Adj(float m1[][3], float m[][3])
446 m1[0][0]=m[1][1]*m[2][2]-m[1][2]*m[2][1];
447 m1[0][1]= -m[0][1]*m[2][2]+m[0][2]*m[2][1];
448 m1[0][2]=m[0][1]*m[1][2]-m[0][2]*m[1][1];
450 m1[1][0]= -m[1][0]*m[2][2]+m[1][2]*m[2][0];
451 m1[1][1]=m[0][0]*m[2][2]-m[0][2]*m[2][0];
452 m1[1][2]= -m[0][0]*m[1][2]+m[0][2]*m[1][0];
454 m1[2][0]=m[1][0]*m[2][1]-m[1][1]*m[2][0];
455 m1[2][1]= -m[0][0]*m[2][1]+m[0][1]*m[2][0];
456 m1[2][2]=m[0][0]*m[1][1]-m[0][1]*m[1][0];
459 void Mat4MulMat4(float m1[][4], float m2[][4], float m3[][4])
461 /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */
463 m1[0][0] = m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0] + m2[0][3]*m3[3][0];
464 m1[0][1] = m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1] + m2[0][3]*m3[3][1];
465 m1[0][2] = m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2] + m2[0][3]*m3[3][2];
466 m1[0][3] = m2[0][0]*m3[0][3] + m2[0][1]*m3[1][3] + m2[0][2]*m3[2][3] + m2[0][3]*m3[3][3];
468 m1[1][0] = m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0] + m2[1][3]*m3[3][0];
469 m1[1][1] = m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1] + m2[1][3]*m3[3][1];
470 m1[1][2] = m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2] + m2[1][3]*m3[3][2];
471 m1[1][3] = m2[1][0]*m3[0][3] + m2[1][1]*m3[1][3] + m2[1][2]*m3[2][3] + m2[1][3]*m3[3][3];
473 m1[2][0] = m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0] + m2[2][3]*m3[3][0];
474 m1[2][1] = m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1] + m2[2][3]*m3[3][1];
475 m1[2][2] = m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2] + m2[2][3]*m3[3][2];
476 m1[2][3] = m2[2][0]*m3[0][3] + m2[2][1]*m3[1][3] + m2[2][2]*m3[2][3] + m2[2][3]*m3[3][3];
478 m1[3][0] = m2[3][0]*m3[0][0] + m2[3][1]*m3[1][0] + m2[3][2]*m3[2][0] + m2[3][3]*m3[3][0];
479 m1[3][1] = m2[3][0]*m3[0][1] + m2[3][1]*m3[1][1] + m2[3][2]*m3[2][1] + m2[3][3]*m3[3][1];
480 m1[3][2] = m2[3][0]*m3[0][2] + m2[3][1]*m3[1][2] + m2[3][2]*m3[2][2] + m2[3][3]*m3[3][2];
481 m1[3][3] = m2[3][0]*m3[0][3] + m2[3][1]*m3[1][3] + m2[3][2]*m3[2][3] + m2[3][3]*m3[3][3];
485 void subMat4MulMat4(float *m1, float *m2, float *m3)
488 m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
489 m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
490 m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
491 m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
494 m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
495 m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
496 m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
497 m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
500 m1[0]= m2[0]*m3[0] + m2[1]*m3[4] + m2[2]*m3[8];
501 m1[1]= m2[0]*m3[1] + m2[1]*m3[5] + m2[2]*m3[9];
502 m1[2]= m2[0]*m3[2] + m2[1]*m3[6] + m2[2]*m3[10];
503 m1[3]= m2[0]*m3[3] + m2[1]*m3[7] + m2[2]*m3[11] + m2[3];
508 void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3])
510 void Mat3MulMat3(float *m1, float *m3, float *m2)
513 /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */
515 m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
516 m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
517 m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
519 m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
520 m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
521 m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
523 m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
524 m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
525 m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
527 m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
528 m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
529 m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
532 m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
533 m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
534 m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
537 m1[0]= m2[0]*m3[0] + m2[1]*m3[3] + m2[2]*m3[6];
538 m1[1]= m2[0]*m3[1] + m2[1]*m3[4] + m2[2]*m3[7];
539 m1[2]= m2[0]*m3[2] + m2[1]*m3[5] + m2[2]*m3[8];
541 } /* end of void Mat3MulMat3(float m1[][3], float m3[][3], float m2[][3]) */
543 void Mat4MulMat43(float (*m1)[4], float (*m3)[4], float (*m2)[3])
545 m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
546 m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
547 m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
548 m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
549 m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
550 m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
551 m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
552 m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
553 m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
555 /* m1 = m2 * m3, ignore the elements on the 4th row/column of m3*/
556 void Mat3IsMat3MulMat4(float m1[][3], float m2[][3], float m3[][4])
558 /* m1[i][j] = m2[i][k] * m3[k][j] */
559 m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] +m2[0][2] * m3[2][0];
560 m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] +m2[0][2] * m3[2][1];
561 m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] +m2[0][2] * m3[2][2];
563 m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] +m2[1][2] * m3[2][0];
564 m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] +m2[1][2] * m3[2][1];
565 m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] +m2[1][2] * m3[2][2];
567 m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] +m2[2][2] * m3[2][0];
568 m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] +m2[2][2] * m3[2][1];
569 m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] +m2[2][2] * m3[2][2];
574 void Mat4MulMat34(float (*m1)[4], float (*m3)[3], float (*m2)[4])
576 m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0];
577 m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1];
578 m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2];
579 m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0];
580 m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1];
581 m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2];
582 m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0];
583 m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1];
584 m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2];
587 void Mat4CpyMat4(float m1[][4], float m2[][4])
589 memcpy(m1, m2, 4*4*sizeof(float));
592 void Mat4SwapMat4(float *m1, float *m2)
606 typedef float Mat3Row[3];
607 typedef float Mat4Row[4];
610 void Mat3CpyMat4(float *m1p, float *m2p)
612 void Mat3CpyMat4(float m1[][3], float m2[][4])
617 Mat3Row *m1= (Mat3Row *)m1p;
618 Mat4Row *m2= (Mat4Row *)m2p;
619 for ( i = 0; i++; i < 3) {
620 for (j = 0; j++; j < 3) {
621 m1p[3*i + j] = m2p[4*i + j];
638 /* Butched. See .h for comment */
639 /* void Mat4CpyMat3(float m1[][4], float m2[][3]) */
641 void Mat4CpyMat3(float* m1, float *m2)
644 for (i = 0; i < 3; i++) {
645 m1[(4*i)] = m2[(3*i)];
646 m1[(4*i) + 1]= m2[(3*i) + 1];
647 m1[(4*i) + 2]= m2[(3*i) + 2];
652 m1[12]=m1[13]= m1[14]= 0.0;
657 void Mat4CpyMat3(float m1[][4], float m2[][3]) /* no clear */
671 /* Reevan's Bugfix */
685 void Mat3CpyMat3(float m1[][3], float m2[][3])
687 /* destination comes first: */
688 memcpy(&m1[0], &m2[0], 9*sizeof(float));
691 void Mat3MulSerie(float answ[][3],
692 float m1[][3], float m2[][3], float m3[][3],
693 float m4[][3], float m5[][3], float m6[][3],
694 float m7[][3], float m8[][3])
698 if(m1==0 || m2==0) return;
701 Mat3MulMat3(answ, m2, m1);
703 Mat3MulMat3(temp, m3, answ);
705 Mat3MulMat3(answ, m4, temp);
707 Mat3MulMat3(temp, m5, answ);
709 Mat3MulMat3(answ, m6, temp);
711 Mat3MulMat3(temp, m7, answ);
713 Mat3MulMat3(answ, m8, temp);
715 else Mat3CpyMat3(answ, temp);
718 else Mat3CpyMat3(answ, temp);
721 else Mat3CpyMat3(answ, temp);
725 void Mat4MulSerie(float answ[][4], float m1[][4],
726 float m2[][4], float m3[][4], float m4[][4],
727 float m5[][4], float m6[][4], float m7[][4],
732 if(m1==0 || m2==0) return;
734 Mat4MulMat4(answ, m2, m1);
736 Mat4MulMat4(temp, m3, answ);
738 Mat4MulMat4(answ, m4, temp);
740 Mat4MulMat4(temp, m5, answ);
742 Mat4MulMat4(answ, m6, temp);
744 Mat4MulMat4(temp, m7, answ);
746 Mat4MulMat4(answ, m8, temp);
748 else Mat4CpyMat4(answ, temp);
751 else Mat4CpyMat4(answ, temp);
754 else Mat4CpyMat4(answ, temp);
760 void Mat4Clr(float *m)
762 memset(m, 0, 4*4*sizeof(float));
765 void Mat3Clr(float *m)
767 memset(m, 0, 3*3*sizeof(float));
770 void Mat4One(float m[][4])
773 m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0;
774 m[0][1]= m[0][2]= m[0][3]= 0.0;
775 m[1][0]= m[1][2]= m[1][3]= 0.0;
776 m[2][0]= m[2][1]= m[2][3]= 0.0;
777 m[3][0]= m[3][1]= m[3][2]= 0.0;
780 void Mat3One(float m[][3])
783 m[0][0]= m[1][1]= m[2][2]= 1.0;
784 m[0][1]= m[0][2]= 0.0;
785 m[1][0]= m[1][2]= 0.0;
786 m[2][0]= m[2][1]= 0.0;
789 void Mat4MulVec( float mat[][4], int *vec)
795 vec[0]=(int)(x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0]);
796 vec[1]=(int)(x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1]);
797 vec[2]=(int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]);
800 void Mat4MulVecfl( float mat[][4], float *vec)
806 vec[0]=x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
807 vec[1]=x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
808 vec[2]=x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
811 void VecMat4MulVecfl(float *in, float mat[][4], float *vec)
817 in[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0];
818 in[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1];
819 in[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2];
822 void Mat4Mul3Vecfl( float mat[][4], float *vec)
828 vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
829 vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
830 vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
833 void Mat4MulVec4fl( float mat[][4], float *vec)
840 vec[0]=x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3];
841 vec[1]=x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3];
842 vec[2]=x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3];
843 vec[3]=x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3];
846 void Mat3MulVec( float mat[][3], int *vec)
852 vec[0]= (int)(x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2]);
853 vec[1]= (int)(x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2]);
854 vec[2]= (int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]);
857 void Mat3MulVecfl( float mat[][3], float *vec)
863 vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
864 vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
865 vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
868 void Mat3MulVecd( float mat[][3], double *vec)
874 vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2];
875 vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2];
876 vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2];
879 void Mat3TransMulVecfl( float mat[][3], float *vec)
885 vec[0]= x*mat[0][0] + y*mat[0][1] + mat[0][2]*vec[2];
886 vec[1]= x*mat[1][0] + y*mat[1][1] + mat[1][2]*vec[2];
887 vec[2]= x*mat[2][0] + y*mat[2][1] + mat[2][2]*vec[2];
890 void Mat3MulFloat(float *m, float f)
894 for(i=0;i<9;i++) m[i]*=f;
897 void Mat4MulFloat(float *m, float f)
901 for(i=0;i<12;i++) m[i]*=f; /* count to 12: without vector component */
905 void Mat4MulFloat3(float *m, float f) /* only scale component */
917 void VecStar(float mat[][3], float *vec)
920 mat[0][0]= mat[1][1]= mat[2][2]= 0.0;
930 short EenheidsMat(float mat[][3])
933 if(mat[0][0]==1.0 && mat[0][1]==0.0 && mat[0][2]==0.0)
934 if(mat[1][0]==0.0 && mat[1][1]==1.0 && mat[1][2]==0.0)
935 if(mat[2][0]==0.0 && mat[2][1]==0.0 && mat[2][2]==1.0)
941 int FloatCompare( float *v1, float *v2, float limit)
944 if( fabs(v1[0]-v2[0])<limit ) {
945 if( fabs(v1[1]-v2[1])<limit ) {
946 if( fabs(v1[2]-v2[2])<limit ) return 1;
952 void printmatrix4( char *str, float m[][4])
955 printf("%f %f %f %f\n",m[0][0],m[0][1],m[0][2],m[0][3]);
956 printf("%f %f %f %f\n",m[1][0],m[1][1],m[1][2],m[1][3]);
957 printf("%f %f %f %f\n",m[2][0],m[2][1],m[2][2],m[2][3]);
958 printf("%f %f %f %f\n",m[3][0],m[3][1],m[3][2],m[3][3]);
963 void printmatrix3( char *str, float m[][3])
966 printf("%f %f %f\n",m[0][0],m[0][1],m[0][2]);
967 printf("%f %f %f\n",m[1][0],m[1][1],m[1][2]);
968 printf("%f %f %f\n",m[2][0],m[2][1],m[2][2]);
973 /* **************** QUATERNIONS ********** */
976 void QuatMul(float *q, float *q1, float *q2)
980 t0= q1[0]*q2[0]-q1[1]*q2[1]-q1[2]*q2[2]-q1[3]*q2[3];
981 t1= q1[0]*q2[1]+q1[1]*q2[0]+q1[2]*q2[3]-q1[3]*q2[2];
982 t2= q1[0]*q2[2]+q1[2]*q2[0]+q1[3]*q2[1]-q1[1]*q2[3];
983 q[3]= q1[0]*q2[3]+q1[3]*q2[0]+q1[1]*q2[2]-q1[2]*q2[1];
989 void QuatSub(float *q, float *q1, float *q2)
997 void QuatToMat3( float *q, float m[][3])
999 double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
1016 m[0][0]= (float)(1.0-qbb-qcc);
1017 m[0][1]= (float)(qdc+qab);
1018 m[0][2]= (float)(-qdb+qac);
1020 m[1][0]= (float)(-qdc+qab);
1021 m[1][1]= (float)(1.0-qaa-qcc);
1022 m[1][2]= (float)(qda+qbc);
1024 m[2][0]= (float)(qdb+qac);
1025 m[2][1]= (float)(-qda+qbc);
1026 m[2][2]= (float)(1.0-qaa-qbb);
1030 void QuatToMat4( float *q, float m[][4])
1032 double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
1049 m[0][0]= (float)(1.0-qbb-qcc);
1050 m[0][1]= (float)(qdc+qab);
1051 m[0][2]= (float)(-qdb+qac);
1054 m[1][0]= (float)(-qdc+qab);
1055 m[1][1]= (float)(1.0-qaa-qcc);
1056 m[1][2]= (float)(qda+qbc);
1059 m[2][0]= (float)(qdb+qac);
1060 m[2][1]= (float)(-qda+qbc);
1061 m[2][2]= (float)(1.0-qaa-qbb);
1064 m[3][0]= m[3][1]= m[3][2]= 0.0f;
1068 void Mat3ToQuat( float wmat[][3], float *q) /* from Sig.Proc.85 pag 253 */
1073 /* work on a copy */
1074 Mat3CpyMat3(mat, wmat);
1075 Mat3Ortho(mat); /* this is needed AND a NormalQuat in the end */
1077 tr= 0.25*(1.0+mat[0][0]+mat[1][1]+mat[2][2]);
1079 if(tr>FLT_EPSILON) {
1083 q[1]= (float)((mat[1][2]-mat[2][1])/s);
1084 q[2]= (float)((mat[2][0]-mat[0][2])/s);
1085 q[3]= (float)((mat[0][1]-mat[1][0])/s);
1089 s= -0.5*(mat[1][1]+mat[2][2]);
1094 q[2]= (float)(mat[0][1]/(2*s));
1095 q[3]= (float)(mat[0][2]/(2*s));
1099 s= 0.5*(1.0-mat[2][2]);
1104 q[3]= (float)(mat[1][2]/(2*s));
1115 void Mat3ToQuat_is_ok( float wmat[][3], float *q)
1117 float mat[3][3], matr[3][3], matn[3][3], q1[4], q2[4], hoek, si, co, nor[3];
1119 /* work on a copy */
1120 Mat3CpyMat3(mat, wmat);
1123 /* rotate z-axis of matrix to z-axis */
1125 nor[0] = mat[2][1]; /* cross product with (0,0,1) */
1126 nor[1] = -mat[2][0];
1131 hoek= 0.5f*saacos(co);
1133 co= (float)cos(hoek);
1134 si= (float)sin(hoek);
1136 q1[1]= -nor[0]*si; /* negative here, but why? */
1140 /* rotate back x-axis from mat, using inverse q1 */
1141 QuatToMat3(q1, matr);
1142 Mat3Inv(matn, matr);
1143 Mat3MulVecfl(matn, mat[0]);
1145 /* and align x-axes */
1146 hoek= (float)(0.5*atan2(mat[0][1], mat[0][0]));
1148 co= (float)cos(hoek);
1149 si= (float)sin(hoek);
1159 void Mat4ToQuat( float m[][4], float *q)
1163 Mat3CpyMat4(mat, m);
1168 void QuatOne(float *q)
1170 q[0]= q[2]= q[3]= 0.0;
1174 void NormalQuat(float *q)
1178 len= (float)sqrt(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
1186 q[0]= q[2]= q[3]= 0.0f;
1190 float *vectoquat( float *vec, short axis, short upflag)
1193 float q2[4], nor[3], *fp, mat[3][3], hoek, si, co, x2, y2, z2, len1;
1195 /* first rotate to axis */
1197 x2= vec[0] ; y2= vec[1] ; z2= vec[2];
1201 x2= -vec[0] ; y2= -vec[1] ; z2= -vec[2];
1205 q1[1]=q1[2]=q1[3]= 0.0;
1207 len1= (float)sqrt(x2*x2+y2*y2+z2*z2);
1208 if(len1 == 0.0) return(q1);
1210 /* nasty! I need a good routine for this...
1211 * problem is a rotation of an Y axis to the negative Y-axis for example.
1214 if(axis==0) { /* x-axis */
1219 if( fabs(y2)+fabs(z2)<0.0001 ) {
1225 else if(axis==1) { /* y-axis */
1230 if( fabs(x2)+fabs(z2)<0.0001 ) {
1241 if( fabs(x2)+fabs(y2)<0.0001 ) {
1251 hoek= 0.5f*saacos(co);
1252 si= (float)sin(hoek);
1253 q1[0]= (float)cos(hoek);
1259 QuatToMat3(q1, mat);
1263 if(upflag==1) hoek= (float)(0.5*atan2(fp[2], fp[1]));
1264 else hoek= (float)(-0.5*atan2(fp[1], fp[2]));
1267 if(upflag==0) hoek= (float)(-0.5*atan2(fp[2], fp[0]));
1268 else hoek= (float)(0.5*atan2(fp[0], fp[2]));
1271 if(upflag==0) hoek= (float)(0.5*atan2(-fp[1], -fp[0]));
1272 else hoek= (float)(-0.5*atan2(-fp[0], -fp[1]));
1275 co= (float)cos(hoek);
1276 si= (float)(sin(hoek)/len1);
1288 void VecUpMat3old( float *vec, float mat[][3], short axis)
1291 short cox = 0, coy = 0, coz = 0;
1293 /* using different up's is not useful, infact there is no real 'up'!
1301 cox= 0; coy= 1; coz= 2; /* Y up Z tr */
1304 cox= 1; coy= 2; coz= 0; /* Z up X tr */
1307 cox= 2; coy= 0; coz= 1; /* X up Y tr */
1310 cox= 0; coy= 2; coz= 1; /* */
1313 cox= 1; coy= 0; coz= 2; /* */
1316 cox= 2; coy= 1; coz= 0; /* Y up X tr */
1319 mat[coz][0]= vec[0];
1320 mat[coz][1]= vec[1];
1321 mat[coz][2]= vec[2];
1322 Normalise((float *)mat[coz]);
1324 inp= mat[coz][0]*up[0] + mat[coz][1]*up[1] + mat[coz][2]*up[2];
1325 mat[coy][0]= up[0] - inp*mat[coz][0];
1326 mat[coy][1]= up[1] - inp*mat[coz][1];
1327 mat[coy][2]= up[2] - inp*mat[coz][2];
1329 Normalise((float *)mat[coy]);
1331 Crossf(mat[cox], mat[coy], mat[coz]);
1335 void VecUpMat3(float *vec, float mat[][3], short axis)
1338 short cox = 0, coy = 0, coz = 0;
1340 /* using different up's is not useful, infact there is no real 'up'!
1344 cox= 0; coy= 1; coz= 2; /* Y up Z tr */
1347 cox= 1; coy= 2; coz= 0; /* Z up X tr */
1350 cox= 2; coy= 0; coz= 1; /* X up Y tr */
1353 cox= 0; coy= 1; coz= 2; /* Y op -Z tr */
1359 cox= 1; coy= 0; coz= 2; /* */
1362 cox= 2; coy= 1; coz= 0; /* Y up X tr */
1365 mat[coz][0]= vec[0];
1366 mat[coz][1]= vec[1];
1367 mat[coz][2]= vec[2];
1368 Normalise((float *)mat[coz]);
1371 mat[coy][0]= - inp*mat[coz][0];
1372 mat[coy][1]= - inp*mat[coz][1];
1373 mat[coy][2]= 1.0f - inp*mat[coz][2];
1375 Normalise((float *)mat[coy]);
1377 Crossf(mat[cox], mat[coy], mat[coz]);
1382 /* **************** VIEW / PROJECTION ******************************** */
1386 float left, float right,
1387 float bottom, float top,
1388 float nearClip, float farClip,
1391 float Xdelta, Ydelta, Zdelta;
1393 Xdelta = right - left;
1394 Ydelta = top - bottom;
1395 Zdelta = farClip - nearClip;
1396 if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
1400 matrix[0][0] = 2.0f/Xdelta;
1401 matrix[3][0] = -(right + left)/Xdelta;
1402 matrix[1][1] = 2.0f/Ydelta;
1403 matrix[3][1] = -(top + bottom)/Ydelta;
1404 matrix[2][2] = -2.0f/Zdelta; /* note: negate Z */
1405 matrix[3][2] = -(farClip + nearClip)/Zdelta;
1409 float left, float right,
1410 float bottom, float top,
1411 float nearClip, float farClip,
1414 float Xdelta, Ydelta, Zdelta;
1416 Xdelta = right - left;
1417 Ydelta = top - bottom;
1418 Zdelta = farClip - nearClip;
1420 if (Xdelta == 0.0 || Ydelta == 0.0 || Zdelta == 0.0) {
1423 mat[0][0] = nearClip * 2.0f/Xdelta;
1424 mat[1][1] = nearClip * 2.0f/Ydelta;
1425 mat[2][0] = (right + left)/Xdelta; /* note: negate Z */
1426 mat[2][1] = (top + bottom)/Ydelta;
1427 mat[2][2] = -(farClip + nearClip)/Zdelta;
1429 mat[3][2] = (-2.0f * nearClip * farClip)/Zdelta;
1430 mat[0][1] = mat[0][2] = mat[0][3] =
1431 mat[1][0] = mat[1][2] = mat[1][3] =
1432 mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
1436 void i_translate(float Tx, float Ty, float Tz, float mat[][4])
1438 mat[3][0] += (Tx*mat[0][0] + Ty*mat[1][0] + Tz*mat[2][0]);
1439 mat[3][1] += (Tx*mat[0][1] + Ty*mat[1][1] + Tz*mat[2][1]);
1440 mat[3][2] += (Tx*mat[0][2] + Ty*mat[1][2] + Tz*mat[2][2]);
1443 void i_multmatrix( float icand[][4], float Vm[][4])
1448 for(row=0 ; row<4 ; row++)
1449 for(col=0 ; col<4 ; col++)
1450 temp[row][col] = icand[row][0] * Vm[0][col]
1451 + icand[row][1] * Vm[1][col]
1452 + icand[row][2] * Vm[2][col]
1453 + icand[row][3] * Vm[3][col];
1454 Mat4CpyMat4(Vm, temp);
1457 void i_rotate(float angle, char axis, float mat[][4])
1463 for(col=0; col<4 ; col++) /* init temp to zero matrix */
1466 angle = (float)(angle*(3.1415926535/180.0));
1467 cosine = (float)cos(angle);
1468 sine = (float)sin(angle);
1472 for(col=0 ; col<4 ; col++)
1473 temp[col] = cosine*mat[1][col] + sine*mat[2][col];
1474 for(col=0 ; col<4 ; col++) {
1475 mat[2][col] = - sine*mat[1][col] + cosine*mat[2][col];
1476 mat[1][col] = temp[col];
1482 for(col=0 ; col<4 ; col++)
1483 temp[col] = cosine*mat[0][col] - sine*mat[2][col];
1484 for(col=0 ; col<4 ; col++) {
1485 mat[2][col] = sine*mat[0][col] + cosine*mat[2][col];
1486 mat[0][col] = temp[col];
1492 for(col=0 ; col<4 ; col++)
1493 temp[col] = cosine*mat[0][col] + sine*mat[1][col];
1494 for(col=0 ; col<4 ; col++) {
1495 mat[1][col] = - sine*mat[0][col] + cosine*mat[1][col];
1496 mat[0][col] = temp[col];
1502 void i_polarview(float dist, float azimuth, float incidence, float twist, float Vm[][4])
1507 i_translate(0.0, 0.0, -dist, Vm);
1508 i_rotate(-twist,'z', Vm);
1509 i_rotate(-incidence,'x', Vm);
1510 i_rotate(-azimuth,'z', Vm);
1513 void i_lookat(float vx, float vy, float vz, float px, float py, float pz, float twist, float mat[][4])
1515 float sine, cosine, hyp, hyp1, dx, dy, dz;
1521 i_rotate(-twist,'z', mat);
1526 hyp = dx * dx + dz * dz; /* hyp squared */
1527 hyp1 = (float)sqrt(dy*dy + hyp);
1528 hyp = (float)sqrt(hyp); /* the real hyp */
1530 if (hyp1 != 0.0) { /* rotate X */
1537 mat1[1][1] = cosine;
1540 mat1[2][2] = cosine;
1542 i_multmatrix(mat1, mat);
1544 mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit */
1545 mat1[1][2] = mat1[2][1] = 0.0; /* those modified by the last */
1548 if (hyp != 0.0f) { /* rotate Y */
1555 mat1[0][0] = cosine;
1558 mat1[2][2] = cosine;
1560 i_multmatrix(mat1, mat);
1561 i_translate(-vx,-vy,-vz, mat); /* translate viewpoint to origin */
1568 /* ************************************************ */
1570 void Mat3Ortho(float mat[][3])
1577 void Mat4Ortho(float mat[][4])
1581 len= Normalise(mat[0]);
1582 if(len!=0.0) mat[0][3]/= len;
1583 len= Normalise(mat[1]);
1584 if(len!=0.0) mat[1][3]/= len;
1585 len= Normalise(mat[2]);
1586 if(len!=0.0) mat[2][3]/= len;
1589 void VecCopyf(float *v1, float *v2)
1597 int VecLen( int *v1, int *v2)
1601 x=(float)(v1[0]-v2[0]);
1602 y=(float)(v1[1]-v2[1]);
1603 z=(float)(v1[2]-v2[2]);
1604 return (int)floor(sqrt(x*x+y*y+z*z));
1607 float VecLenf( float *v1, float *v2)
1614 return (float)sqrt(x*x+y*y+z*z);
1617 void VecAddf(float *v, float *v1, float *v2)
1624 void VecSubf(float *v, float *v1, float *v2)
1631 void VecMidf(float *v, float *v1, float *v2)
1633 v[0]= 0.5f*(v1[0]+ v2[0]);
1634 v[1]= 0.5f*(v1[1]+ v2[1]);
1635 v[2]= 0.5f*(v1[2]+ v2[2]);
1638 void VecMulf(float *v1, float f)
1646 int VecCompare( float *v1, float *v2, float limit)
1648 if( fabs(v1[0]-v2[0])<limit )
1649 if( fabs(v1[1]-v2[1])<limit )
1650 if( fabs(v1[2]-v2[2])<limit ) return 1;
1654 void CalcNormShort( short *v1, short *v2, short *v3, float *n) /* is also cross product */
1658 n1[0]= (float)(v1[0]-v2[0]);
1659 n2[0]= (float)(v2[0]-v3[0]);
1660 n1[1]= (float)(v1[1]-v2[1]);
1661 n2[1]= (float)(v2[1]-v3[1]);
1662 n1[2]= (float)(v1[2]-v2[2]);
1663 n2[2]= (float)(v2[2]-v3[2]);
1664 n[0]= n1[1]*n2[2]-n1[2]*n2[1];
1665 n[1]= n1[2]*n2[0]-n1[0]*n2[2];
1666 n[2]= n1[0]*n2[1]-n1[1]*n2[0];
1670 void CalcNormLong( int* v1, int*v2, int*v3, float *n)
1674 n1[0]= (float)(v1[0]-v2[0]);
1675 n2[0]= (float)(v2[0]-v3[0]);
1676 n1[1]= (float)(v1[1]-v2[1]);
1677 n2[1]= (float)(v2[1]-v3[1]);
1678 n1[2]= (float)(v1[2]-v2[2]);
1679 n2[2]= (float)(v2[2]-v3[2]);
1680 n[0]= n1[1]*n2[2]-n1[2]*n2[1];
1681 n[1]= n1[2]*n2[0]-n1[0]*n2[2];
1682 n[2]= n1[0]*n2[1]-n1[1]*n2[0];
1686 float CalcNormFloat( float *v1, float *v2, float *v3, float *n)
1696 n[0]= n1[1]*n2[2]-n1[2]*n2[1];
1697 n[1]= n1[2]*n2[0]-n1[0]*n2[2];
1698 n[2]= n1[0]*n2[1]-n1[1]*n2[0];
1699 return Normalise(n);
1702 float CalcNormFloat4( float *v1, float *v2, float *v3, float *v4, float *n)
1715 n[0]= n1[1]*n2[2]-n1[2]*n2[1];
1716 n[1]= n1[2]*n2[0]-n1[0]*n2[2];
1717 n[2]= n1[0]*n2[1]-n1[1]*n2[0];
1719 return Normalise(n);
1723 void CalcCent3f(float *cent, float *v1, float *v2, float *v3)
1726 cent[0]= 0.33333f*(v1[0]+v2[0]+v3[0]);
1727 cent[1]= 0.33333f*(v1[1]+v2[1]+v3[1]);
1728 cent[2]= 0.33333f*(v1[2]+v2[2]+v3[2]);
1731 void CalcCent4f(float *cent, float *v1, float *v2, float *v3, float *v4)
1734 cent[0]= 0.25f*(v1[0]+v2[0]+v3[0]+v4[0]);
1735 cent[1]= 0.25f*(v1[1]+v2[1]+v3[1]+v4[1]);
1736 cent[2]= 0.25f*(v1[2]+v2[2]+v3[2]+v4[2]);
1739 float Sqrt3f(float f)
1741 if(f==0.0) return 0;
1742 if(f<0) return (float)(-exp(log(-f)/3));
1743 else return (float)(exp(log(f)/3));
1746 double Sqrt3d(double d)
1748 if(d==0.0) return 0;
1749 if(d<0) return -exp(log(-d)/3);
1750 else return exp(log(d)/3);
1753 /* distance v1 to line v2-v3 */
1754 /* using Hesse formula, NO LINE PIECE! */
1755 float DistVL2Dfl( float *v1, float *v2, float *v3) {
1760 deler= (float)sqrt(a[0]*a[0]+a[1]*a[1]);
1761 if(deler== 0.0f) return 0;
1763 return (float)(fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler);
1767 /* distance v1 to line-piece v2-v3 */
1768 float PdistVL2Dfl( float *v1, float *v2, float *v3)
1770 float labda, rc[2], pt[2], len;
1774 len= rc[0]*rc[0]+ rc[1]*rc[1];
1778 return (float)(sqrt(rc[0]*rc[0]+ rc[1]*rc[1]));
1781 labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
1786 else if(labda>=1.0) {
1791 pt[0]= labda*rc[0]+v2[0];
1792 pt[1]= labda*rc[1]+v2[1];
1797 return (float)sqrt(rc[0]*rc[0]+ rc[1]*rc[1]);
1800 float AreaF2Dfl( float *v1, float *v2, float *v3)
1802 return (float)(0.5*fabs( (v1[0]-v2[0])*(v2[1]-v3[1]) + (v1[1]-v2[1])*(v3[0]-v2[0]) ));
1806 float AreaQ3Dfl( float *v1, float *v2, float *v3, float *v4) /* only convex Quadrilaterals */
1808 float len, vec1[3], vec2[3], n[3];
1810 VecSubf(vec1, v2, v1);
1811 VecSubf(vec2, v4, v1);
1812 Crossf(n, vec1, vec2);
1815 VecSubf(vec1, v4, v3);
1816 VecSubf(vec2, v2, v3);
1817 Crossf(n, vec1, vec2);
1823 float AreaT3Dfl( float *v1, float *v2, float *v3) /* Triangles */
1825 float len, vec1[3], vec2[3], n[3];
1827 VecSubf(vec1, v3, v2);
1828 VecSubf(vec2, v1, v2);
1829 Crossf(n, vec1, vec2);
1835 #define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
1836 #define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
1839 float AreaPoly3Dfl(int nr, float *verts, float *normal)
1841 float x, y, z, area, max;
1845 /* first: find dominant axis: 0==X, 1==Y, 2==Z */
1846 x= (float)fabs(normal[0]);
1847 y= (float)fabs(normal[1]);
1848 z= (float)fabs(normal[2]);
1849 max = MAX3(x, y, z);
1856 /* The Trapezium Area Rule */
1857 prev= verts+3*(nr-1);
1860 for(a=0; a<nr; a++) {
1861 area+= (cur[px]-prev[px])*(cur[py]+prev[py]);
1866 return (float)fabs(0.5*area/max);
1869 void MinMax3(float *min, float *max, float *vec)
1871 if(min[0]>vec[0]) min[0]= vec[0];
1872 if(min[1]>vec[1]) min[1]= vec[1];
1873 if(min[2]>vec[2]) min[2]= vec[2];
1875 if(max[0]<vec[0]) max[0]= vec[0];
1876 if(max[1]<vec[1]) max[1]= vec[1];
1877 if(max[2]<vec[2]) max[2]= vec[2];
1880 /* ************ EULER *************** */
1882 void EulToMat3( float *eul, float mat[][3])
1884 double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1897 mat[0][0] = (float)(cj*ch);
1898 mat[1][0] = (float)(sj*sc-cs);
1899 mat[2][0] = (float)(sj*cc+ss);
1900 mat[0][1] = (float)(cj*sh);
1901 mat[1][1] = (float)(sj*ss+cc);
1902 mat[2][1] = (float)(sj*cs-sc);
1903 mat[0][2] = (float)-sj;
1904 mat[1][2] = (float)(cj*si);
1905 mat[2][2] = (float)(cj*ci);
1909 void EulToMat4( float *eul,float mat[][4])
1911 double ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
1924 mat[0][0] = (float)(cj*ch);
1925 mat[1][0] = (float)(sj*sc-cs);
1926 mat[2][0] = (float)(sj*cc+ss);
1927 mat[0][1] = (float)(cj*sh);
1928 mat[1][1] = (float)(sj*ss+cc);
1929 mat[2][1] = (float)(sj*cs-sc);
1930 mat[0][2] = (float)-sj;
1931 mat[1][2] = (float)(cj*si);
1932 mat[2][2] = (float)(cj*ci);
1935 mat[3][0]= mat[3][1]= mat[3][2]= mat[0][3]= mat[1][3]= mat[2][3]= 0.0f;
1940 void Mat3ToEul(float tmat[][3], float *eul)
1942 float cy, quat[4], mat[3][3];
1944 Mat3ToQuat(tmat, quat);
1945 QuatToMat3(quat, mat);
1946 Mat3CpyMat3(mat, tmat);
1949 cy = (float)sqrt(mat[0][0]*mat[0][0] + mat[0][1]*mat[0][1]);
1951 if (cy > 16.0*FLT_EPSILON) {
1952 eul[0] = (float)atan2(mat[1][2], mat[2][2]);
1953 eul[1] = (float)atan2(-mat[0][2], cy);
1954 eul[2] = (float)atan2(mat[0][1], mat[0][0]);
1956 eul[0] = (float)atan2(-mat[2][1], mat[1][1]);
1957 eul[1] = (float)atan2(-mat[0][2], cy);
1962 void Mat3ToEuln( float tmat[][3], float *eul)
1964 float sin1, cos1, sin2, cos2, sin3, cos3;
1967 cos1 = (float)sqrt(1 - sin1*sin1);
1969 if ( fabs(cos1) > FLT_EPSILON ) {
1970 sin2 = tmat[2][1] / cos1;
1971 cos2 = tmat[2][2] / cos1;
1972 sin3 = tmat[1][0] / cos1;
1973 cos3 = tmat[0][0] / cos1;
1982 eul[0] = (float)atan2(sin3, cos3);
1983 eul[1] = (float)atan2(sin1, cos1);
1984 eul[2] = (float)atan2(sin2, cos2);
1989 void QuatToEul( float *quat, float *eul)
1993 QuatToMat3(quat, mat);
1994 Mat3ToEul(mat, eul);
1998 void EulToQuat( float *eul, float *quat)
2000 float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
2002 ti = eul[0]*0.5f; tj = eul[1]*0.5f; th = eul[2]*0.5f;
2003 ci = (float)cos(ti); cj = (float)cos(tj); ch = (float)cos(th);
2004 si = (float)sin(ti); sj = (float)sin(tj); sh = (float)sin(th);
2005 cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
2007 quat[0] = cj*cc + sj*ss;
2008 quat[1] = cj*sc - sj*cs;
2009 quat[2] = cj*ss + sj*cc;
2010 quat[3] = cj*cs - sj*sc;
2013 void VecRotToMat3( float *vec, float phi, float mat[][3])
2015 /* rotation of phi radials around vec */
2016 float vx, vx2, vy, vy2, vz, vz2, co, si;
2024 co= (float)cos(phi);
2025 si= (float)sin(phi);
2027 mat[0][0]= vx2+co*(1.0f-vx2);
2028 mat[0][1]= vx*vy*(1.0f-co)+vz*si;
2029 mat[0][2]= vz*vx*(1.0f-co)-vy*si;
2030 mat[1][0]= vx*vy*(1.0f-co)-vz*si;
2031 mat[1][1]= vy2+co*(1.0f-vy2);
2032 mat[1][2]= vy*vz*(1.0f-co)+vx*si;
2033 mat[2][0]= vz*vx*(1.0f-co)+vy*si;
2034 mat[2][1]= vy*vz*(1.0f-co)-vx*si;
2035 mat[2][2]= vz2+co*(1.0f-vz2);
2039 void VecRotToQuat( float *vec, float phi, float *quat)
2041 /* rotation of phi radials around vec */
2048 if( Normalise(quat+1) == 0.0) {
2052 quat[0]= (float)cos( phi/2.0 );
2053 si= (float)sin( phi/2.0 );
2060 void euler_rot(float *beul, float ang, char axis)
2062 float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
2064 eul[0]= eul[1]= eul[2]= 0.0;
2065 if(axis=='x') eul[0]= ang;
2066 else if(axis=='y') eul[1]= ang;
2069 EulToMat3(eul, mat1);
2070 EulToMat3(beul, mat2);
2072 Mat3MulMat3(totmat, mat2, mat1);
2074 Mat3ToEul(totmat, beul);
2080 void SizeToMat3( float *size, float mat[][3])
2093 void Mat3ToSize( float mat[][3], float *size)
2098 VecCopyf(vec, mat[0]);
2099 size[0]= Normalise(vec);
2100 VecCopyf(vec, mat[1]);
2101 size[1]= Normalise(vec);
2102 VecCopyf(vec, mat[2]);
2103 size[2]= Normalise(vec);
2107 void Mat4ToSize( float mat[][4], float *size)
2112 VecCopyf(vec, mat[0]);
2113 size[0]= Normalise(vec);
2114 VecCopyf(vec, mat[1]);
2115 size[1]= Normalise(vec);
2116 VecCopyf(vec, mat[2]);
2117 size[2]= Normalise(vec);
2120 /* ************* SPECIALS ******************* */
2122 void triatoquat( float *v1, float *v2, float *v3, float *quat)
2124 /* imaginary x-axis, y-axis triangle is being rotated */
2125 float vec[3], q1[4], q2[4], n[3], si, co, hoek, mat[3][3], imat[3][3];
2127 /* move z-axis to face-normal */
2128 CalcNormFloat(v1, v2, v3, vec);
2135 if(n[0]==0.0 && n[1]==0.0) n[0]= 1.0;
2137 hoek= -0.5f*saacos(vec[2]);
2138 co= (float)cos(hoek);
2139 si= (float)sin(hoek);
2145 /* rotate back line v1-v2 */
2146 QuatToMat3(q1, mat);
2148 VecSubf(vec, v2, v1);
2149 Mat3MulVecfl(imat, vec);
2151 /* what angle has this line with x-axis? */
2155 hoek= (float)(0.5*atan2(vec[1], vec[0]));
2156 co= (float)cos(hoek);
2157 si= (float)sin(hoek);
2163 QuatMul(quat, q1, q2);
2166 void MinMaxRGB(short c[])
2168 if(c[0]>255) c[0]=255;
2169 else if(c[0]<0) c[0]=0;
2170 if(c[1]>255) c[1]=255;
2171 else if(c[1]<0) c[1]=0;
2172 if(c[2]>255) c[2]=255;
2173 else if(c[2]<0) c[2]=0;
2176 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
2196 t = v*(1.0f-(s*(1.0f-f)));
2233 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
2236 float cmax, cmin, cdelta;
2241 cmax = (g>cmax ? g:cmax);
2242 cmin = (g<cmin ? g:cmin);
2243 cmax = (b>cmax ? b:cmax);
2244 cmin = (b<cmin ? b:cmin);
2246 v = cmax; /* value */
2248 s = (cmax - cmin)/cmax;
2257 rc = (cmax-r)/cdelta;
2258 gc = (cmax-g)/cdelta;
2259 bc = (cmax-b)/cdelta;
2274 if( *lh < 0.0) *lh= 0.0;
2279 /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
2280 for that reason it is sensitive for endianness... with this function it works correctly
2283 unsigned int hsv_to_cpack(float h, float s, float v)
2289 hsv_to_rgb(h, s, v, &rf, &gf, &bf);
2291 r= (short)(rf*255.0f);
2292 g= (short)(gf*255.0f);
2293 b= (short)(bf*255.0f);
2295 col= ( r + (g*256) + (b*256*256) );
2300 unsigned int rgb_to_cpack(float r, float g, float b)
2304 ir= (int)floor(255.0*r);
2305 if(ir<0) ir= 0; else if(ir>255) ir= 255;
2306 ig= (int)floor(255.0*g);
2307 if(ig<0) ig= 0; else if(ig>255) ig= 255;
2308 ib= (int)floor(255.0*b);
2309 if(ib<0) ib= 0; else if(ib>255) ib= 255;
2311 return (ir+ (ig*256) + (ib*256*256));
2314 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
2317 *r= (float)((col)&0xFF);
2320 *g= (float)(((col)>>8)&0xFF);
2323 *b= (float)(((col)>>16)&0xFF);