diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-11-10 01:42:41 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-11-10 01:42:41 +0300 |
commit | 60ea7456137a019c2ddad75f14b3b6a0892f7b56 (patch) | |
tree | 7bcd9059496194f5af8d1c671998996a15e38f15 /source/blender/blenlib/intern/math_matrix.c | |
parent | 5935ef004935b27fc5795349aed32f87cf637049 (diff) |
Math Lib Reorganization
* New header and source files.
* Still need a few tweaks before switching code to use them.
Diffstat (limited to 'source/blender/blenlib/intern/math_matrix.c')
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 1102 |
1 files changed, 1102 insertions, 0 deletions
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c new file mode 100644 index 00000000000..f25f24927b4 --- /dev/null +++ b/source/blender/blenlib/intern/math_matrix.c @@ -0,0 +1,1102 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: some of this file. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <float.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "BLI_math.h" + +/********************************* Init **************************************/ + +void zero_m3(float *m) +{ + memset(m, 0, 3*3*sizeof(float)); +} + +void zero_m4(float *m) +{ + memset(m, 0, 4*4*sizeof(float)); +} + +void unit_m3(float m[][3]) +{ + m[0][0]= m[1][1]= m[2][2]= 1.0; + m[0][1]= m[0][2]= 0.0; + m[1][0]= m[1][2]= 0.0; + m[2][0]= m[2][1]= 0.0; +} + +void unit_m4(float m[][4]) +{ + m[0][0]= m[1][1]= m[2][2]= m[3][3]= 1.0; + m[0][1]= m[0][2]= m[0][3]= 0.0; + m[1][0]= m[1][2]= m[1][3]= 0.0; + m[2][0]= m[2][1]= m[2][3]= 0.0; + m[3][0]= m[3][1]= m[3][2]= 0.0; +} + +void copy_m3_m3(float m1[][3], float m2[][3]) +{ + /* destination comes first: */ + memcpy(&m1[0], &m2[0], 9*sizeof(float)); +} + +void copy_m4_m4(float m1[][4], float m2[][4]) +{ + memcpy(m1, m2, 4*4*sizeof(float)); +} + +void copy_m3_m4(float m1[][3], float m2[][4]) +{ + m1[0][0]= m2[0][0]; + m1[0][1]= m2[0][1]; + m1[0][2]= m2[0][2]; + + m1[1][0]= m2[1][0]; + m1[1][1]= m2[1][1]; + m1[1][2]= m2[1][2]; + + m1[2][0]= m2[2][0]; + m1[2][1]= m2[2][1]; + m1[2][2]= m2[2][2]; +} + +void copy_m4_m3(float m1[][4], float m2[][3]) /* no clear */ +{ + m1[0][0]= m2[0][0]; + m1[0][1]= m2[0][1]; + m1[0][2]= m2[0][2]; + + m1[1][0]= m2[1][0]; + m1[1][1]= m2[1][1]; + m1[1][2]= m2[1][2]; + + m1[2][0]= m2[2][0]; + m1[2][1]= m2[2][1]; + m1[2][2]= m2[2][2]; + + /* Reevan's Bugfix */ + m1[0][3]=0.0F; + m1[1][3]=0.0F; + m1[2][3]=0.0F; + + m1[3][0]=0.0F; + m1[3][1]=0.0F; + m1[3][2]=0.0F; + m1[3][3]=1.0F; + +} + +void swap_m4m4(float m1[][4], float m2[][4]) +{ + float t; + int i, j; + + for(i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + t = m1[i][j]; + m1[i][j] = m2[i][j]; + m2[i][j] = t; + } + } +} + +/******************************** Arithmetic *********************************/ + +void mul_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) +{ + /* matrix product: m1[j][k] = m2[j][i].m3[i][k] */ + + 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]; + 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]; + 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]; + 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]; + + 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]; + 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]; + 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]; + 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]; + + 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]; + 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]; + 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]; + 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]; + + 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]; + 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]; + 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]; + 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]; + +} + +void mul_m3_m3m3(float m1[][3], float m3[][3], float m2[][3]) +{ + /* m1[i][j] = m2[i][k]*m3[k][j], args are flipped! */ + m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0]; + m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1]; + m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2]; + + m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0]; + m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1]; + m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2]; + + m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0]; + m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1]; + m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2]; +} + +void mul_m4_m4m3(float (*m1)[4], float (*m3)[4], float (*m2)[3]) +{ + m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0]; + m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1]; + m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2]; + m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0]; + m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1]; + m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2]; + m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0]; + m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1]; + m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2]; +} +/* m1 = m2 * m3, ignore the elements on the 4th row/column of m3*/ +void mul_m3_m3m4(float m1[][3], float m2[][3], float m3[][4]) +{ + /* m1[i][j] = m2[i][k] * m3[k][j] */ + m1[0][0] = m2[0][0] * m3[0][0] + m2[0][1] * m3[1][0] +m2[0][2] * m3[2][0]; + m1[0][1] = m2[0][0] * m3[0][1] + m2[0][1] * m3[1][1] +m2[0][2] * m3[2][1]; + m1[0][2] = m2[0][0] * m3[0][2] + m2[0][1] * m3[1][2] +m2[0][2] * m3[2][2]; + + m1[1][0] = m2[1][0] * m3[0][0] + m2[1][1] * m3[1][0] +m2[1][2] * m3[2][0]; + m1[1][1] = m2[1][0] * m3[0][1] + m2[1][1] * m3[1][1] +m2[1][2] * m3[2][1]; + m1[1][2] = m2[1][0] * m3[0][2] + m2[1][1] * m3[1][2] +m2[1][2] * m3[2][2]; + + m1[2][0] = m2[2][0] * m3[0][0] + m2[2][1] * m3[1][0] +m2[2][2] * m3[2][0]; + m1[2][1] = m2[2][0] * m3[0][1] + m2[2][1] * m3[1][1] +m2[2][2] * m3[2][1]; + m1[2][2] = m2[2][0] * m3[0][2] + m2[2][1] * m3[1][2] +m2[2][2] * m3[2][2]; +} + + + +void mul_m4_m3m4(float (*m1)[4], float (*m3)[3], float (*m2)[4]) +{ + m1[0][0]= m2[0][0]*m3[0][0] + m2[0][1]*m3[1][0] + m2[0][2]*m3[2][0]; + m1[0][1]= m2[0][0]*m3[0][1] + m2[0][1]*m3[1][1] + m2[0][2]*m3[2][1]; + m1[0][2]= m2[0][0]*m3[0][2] + m2[0][1]*m3[1][2] + m2[0][2]*m3[2][2]; + m1[1][0]= m2[1][0]*m3[0][0] + m2[1][1]*m3[1][0] + m2[1][2]*m3[2][0]; + m1[1][1]= m2[1][0]*m3[0][1] + m2[1][1]*m3[1][1] + m2[1][2]*m3[2][1]; + m1[1][2]= m2[1][0]*m3[0][2] + m2[1][1]*m3[1][2] + m2[1][2]*m3[2][2]; + m1[2][0]= m2[2][0]*m3[0][0] + m2[2][1]*m3[1][0] + m2[2][2]*m3[2][0]; + m1[2][1]= m2[2][0]*m3[0][1] + m2[2][1]*m3[1][1] + m2[2][2]*m3[2][1]; + m1[2][2]= m2[2][0]*m3[0][2] + m2[2][1]*m3[1][2] + m2[2][2]*m3[2][2]; +} + +void mul_serie_m3(float answ[][3], + float m1[][3], float m2[][3], float m3[][3], + float m4[][3], float m5[][3], float m6[][3], + float m7[][3], float m8[][3]) +{ + float temp[3][3]; + + if(m1==0 || m2==0) return; + + + mul_m3_m3m3(answ, m2, m1); + if(m3) { + mul_m3_m3m3(temp, m3, answ); + if(m4) { + mul_m3_m3m3(answ, m4, temp); + if(m5) { + mul_m3_m3m3(temp, m5, answ); + if(m6) { + mul_m3_m3m3(answ, m6, temp); + if(m7) { + mul_m3_m3m3(temp, m7, answ); + if(m8) { + mul_m3_m3m3(answ, m8, temp); + } + else copy_m3_m3(answ, temp); + } + } + else copy_m3_m3(answ, temp); + } + } + else copy_m3_m3(answ, temp); + } +} + +void mul_serie_m4(float answ[][4], float m1[][4], + float m2[][4], float m3[][4], float m4[][4], + float m5[][4], float m6[][4], float m7[][4], + float m8[][4]) +{ + float temp[4][4]; + + if(m1==0 || m2==0) return; + + mul_m4_m4m4(answ, m2, m1); + if(m3) { + mul_m4_m4m4(temp, m3, answ); + if(m4) { + mul_m4_m4m4(answ, m4, temp); + if(m5) { + mul_m4_m4m4(temp, m5, answ); + if(m6) { + mul_m4_m4m4(answ, m6, temp); + if(m7) { + mul_m4_m4m4(temp, m7, answ); + if(m8) { + mul_m4_m4m4(answ, m8, temp); + } + else copy_m4_m4(answ, temp); + } + } + else copy_m4_m4(answ, temp); + } + } + else copy_m4_m4(answ, temp); + } +} + +void mul_m4_v3(float mat[][4], float *vec) +{ + float x,y; + + x=vec[0]; + y=vec[1]; + vec[0]=x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0]; + vec[1]=x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1]; + vec[2]=x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]; +} + +void mul_v3_m4v3(float *in, float mat[][4], float *vec) +{ + float x,y; + + x=vec[0]; + y=vec[1]; + in[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2] + mat[3][0]; + in[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2] + mat[3][1]; + in[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]; +} + +void mul_no_transl_m4v3(float mat[][4], float *vec) +{ + float x,y; + + x= vec[0]; + y= vec[1]; + vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2]; + vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2]; + vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]; +} + +void mul_project_m4_v4(float mat[][4], float *vec) +{ + float w; + + w = vec[0]*mat[0][3] + vec[1]*mat[1][3] + vec[2]*mat[2][3] + mat[3][3]; + mul_m4_v3(mat, vec); + + vec[0] /= w; + vec[1] /= w; + vec[2] /= w; +} + +void mul_m4_v4(float mat[][4], float *vec) +{ + float x,y,z; + + x=vec[0]; + y=vec[1]; + z= vec[2]; + vec[0]=x*mat[0][0] + y*mat[1][0] + z*mat[2][0] + mat[3][0]*vec[3]; + vec[1]=x*mat[0][1] + y*mat[1][1] + z*mat[2][1] + mat[3][1]*vec[3]; + vec[2]=x*mat[0][2] + y*mat[1][2] + z*mat[2][2] + mat[3][2]*vec[3]; + vec[3]=x*mat[0][3] + y*mat[1][3] + z*mat[2][3] + mat[3][3]*vec[3]; +} + +void mul_m3_v3(float mat[][3], float *vec) +{ + float x,y; + + x=vec[0]; + y=vec[1]; + vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2]; + vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2]; + vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]; +} + +void mul_transposed_m3_v3(float mat[][3], float *vec) +{ + float x,y; + + x=vec[0]; + y=vec[1]; + vec[0]= x*mat[0][0] + y*mat[0][1] + mat[0][2]*vec[2]; + vec[1]= x*mat[1][0] + y*mat[1][1] + mat[1][2]*vec[2]; + vec[2]= x*mat[2][0] + y*mat[2][1] + mat[2][2]*vec[2]; +} + +void mul_m3_fl(float *m, float f) +{ + int i; + + for(i=0;i<9;i++) m[i]*=f; +} + +void mul_m4_fl(float *m, float f) +{ + int i; + + for(i=0;i<16;i++) m[i]*=f; /* count to 12: without vector component */ +} + +void mul_no_transl_m4_fl(float *m, float f) /* only scale component */ +{ + int i,j; + + for(i=0; i<3; i++) { + for(j=0; j<3; j++) { + + m[4*i+j] *= f; + } + } +} + +void mul_m3_v3_double(float mat[][3], double *vec) +{ + double x,y; + + x=vec[0]; + y=vec[1]; + vec[0]= x*mat[0][0] + y*mat[1][0] + mat[2][0]*vec[2]; + vec[1]= x*mat[0][1] + y*mat[1][1] + mat[2][1]*vec[2]; + vec[2]= x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2]; +} + +void add_m3_m3m3(float m1[][3], float m2[][3], float m3[][3]) +{ + int i, j; + + for(i=0;i<3;i++) + for(j=0;j<3;j++) + m1[i][j]= m2[i][j] + m3[i][j]; +} + +void add_m4_m4m4(float m1[][4], float m2[][4], float m3[][4]) +{ + int i, j; + + for(i=0;i<4;i++) + for(j=0;j<4;j++) + m1[i][j]= m2[i][j] + m3[i][j]; +} + +void invert_m3_m3(float m1[][3], float m2[][3]) +{ + short a,b; + float det; + + /* calc adjoint */ + adjoint_m3_m3(m1,m2); + + /* then determinant old matrix! */ + det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1]) + -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1]) + +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]); + + if(det==0) det=1; + det= 1/det; + for(a=0;a<3;a++) { + for(b=0;b<3;b++) { + m1[a][b]*=det; + } + } +} + +/* + * invertmat - + * computes the inverse of mat and puts it in inverse. Returns + * TRUE on success (i.e. can always find a pivot) and FALSE on failure. + * Uses Gaussian Elimination with partial (maximal column) pivoting. + * + * Mark Segal - 1992 + */ + +int invert_m4_m4(float inverse[][4], float mat[][4]) +{ + int i, j, k; + double temp; + float tempmat[4][4]; + float max; + int maxj; + + /* Set inverse to identity */ + for (i=0; i<4; i++) + for (j=0; j<4; j++) + inverse[i][j] = 0; + for (i=0; i<4; i++) + inverse[i][i] = 1; + + /* Copy original matrix so we don't mess it up */ + for(i = 0; i < 4; i++) + for(j = 0; j <4; j++) + tempmat[i][j] = mat[i][j]; + + for(i = 0; i < 4; i++) { + /* Look for row with max pivot */ + max = fabs(tempmat[i][i]); + maxj = i; + for(j = i + 1; j < 4; j++) { + if(fabs(tempmat[j][i]) > max) { + max = fabs(tempmat[j][i]); + maxj = j; + } + } + /* Swap rows if necessary */ + if (maxj != i) { + for(k = 0; k < 4; k++) { + SWAP(float, tempmat[i][k], tempmat[maxj][k]); + SWAP(float, inverse[i][k], inverse[maxj][k]); + } + } + + temp = tempmat[i][i]; + if (temp == 0) + return 0; /* No non-zero pivot */ + for(k = 0; k < 4; k++) { + tempmat[i][k] = (float)(tempmat[i][k]/temp); + inverse[i][k] = (float)(inverse[i][k]/temp); + } + for(j = 0; j < 4; j++) { + if(j != i) { + temp = tempmat[j][i]; + for(k = 0; k < 4; k++) { + tempmat[j][k] -= (float)(tempmat[i][k]*temp); + inverse[j][k] -= (float)(inverse[i][k]*temp); + } + } + } + } + return 1; +} + +/****************************** Linear Algebra *******************************/ + +void transpose_m3(float mat[][3]) +{ + float t; + + t = mat[0][1] ; + mat[0][1] = mat[1][0] ; + mat[1][0] = t; + t = mat[0][2] ; + mat[0][2] = mat[2][0] ; + mat[2][0] = t; + t = mat[1][2] ; + mat[1][2] = mat[2][1] ; + mat[2][1] = t; +} + +void transpose_m4(float mat[][4]) +{ + float t; + + t = mat[0][1] ; + mat[0][1] = mat[1][0] ; + mat[1][0] = t; + t = mat[0][2] ; + mat[0][2] = mat[2][0] ; + mat[2][0] = t; + t = mat[0][3] ; + mat[0][3] = mat[3][0] ; + mat[3][0] = t; + + t = mat[1][2] ; + mat[1][2] = mat[2][1] ; + mat[2][1] = t; + t = mat[1][3] ; + mat[1][3] = mat[3][1] ; + mat[3][1] = t; + + t = mat[2][3] ; + mat[2][3] = mat[3][2] ; + mat[3][2] = t; +} + +void orthogonalize_m3(float mat[][3], int axis) +{ + float size[3]; + size[0] = len_v3(mat[0]); + size[1] = len_v3(mat[1]); + size[2] = len_v3(mat[2]); + normalize_v3(mat[axis]); + switch(axis) + { + case 0: + if (dot_v3v3(mat[0], mat[1]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } else { + float vec[3] = {mat[0][1], mat[0][2], mat[0][0]}; + + cross_v3_v3v3(mat[2], mat[0], vec); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + case 1: + if (dot_v3v3(mat[1], mat[0]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } else { + float vec[3] = {mat[1][1], mat[1][2], mat[1][0]}; + + cross_v3_v3v3(mat[0], mat[1], vec); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + case 2: + if (dot_v3v3(mat[2], mat[0]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } else if (dot_v3v3(mat[2], mat[1]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } else { + float vec[3] = {mat[2][1], mat[2][2], mat[2][0]}; + + cross_v3_v3v3(mat[0], vec, mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + } + mul_v3_fl(mat[0], size[0]); + mul_v3_fl(mat[1], size[1]); + mul_v3_fl(mat[2], size[2]); +} + +void orthogonalize_m4(float mat[][4], int axis) +{ + float size[3]; + size[0] = len_v3(mat[0]); + size[1] = len_v3(mat[1]); + size[2] = len_v3(mat[2]); + normalize_v3(mat[axis]); + switch(axis) + { + case 0: + if (dot_v3v3(mat[0], mat[1]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } else { + float vec[3] = {mat[0][1], mat[0][2], mat[0][0]}; + + cross_v3_v3v3(mat[2], mat[0], vec); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + case 1: + normalize_v3(mat[0]); + if (dot_v3v3(mat[1], mat[0]) < 1) { + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } else if (dot_v3v3(mat[0], mat[2]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } else { + float vec[3] = {mat[1][1], mat[1][2], mat[1][0]}; + + cross_v3_v3v3(mat[0], mat[1], vec); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[2], mat[0], mat[1]); + } + case 2: + if (dot_v3v3(mat[2], mat[0]) < 1) { + cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); + cross_v3_v3v3(mat[0], mat[1], mat[2]); + } else if (dot_v3v3(mat[2], mat[1]) < 1) { + cross_v3_v3v3(mat[0], mat[1], mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } else { + float vec[3] = {mat[2][1], mat[2][2], mat[2][0]}; + + cross_v3_v3v3(mat[0], vec, mat[2]); + normalize_v3(mat[0]); + cross_v3_v3v3(mat[1], mat[2], mat[0]); + } + } + mul_v3_fl(mat[0], size[0]); + mul_v3_fl(mat[1], size[1]); + mul_v3_fl(mat[2], size[2]); +} + +int is_orthogonal_m3(float mat[][3]) +{ + if (fabs(dot_v3v3(mat[0], mat[1])) > 1.5 * FLT_EPSILON) + return 0; + + if (fabs(dot_v3v3(mat[1], mat[2])) > 1.5 * FLT_EPSILON) + return 0; + + if (fabs(dot_v3v3(mat[0], mat[2])) > 1.5 * FLT_EPSILON) + return 0; + + return 1; +} + +int is_orthogonal_m4(float mat[][4]) +{ + if (fabs(dot_v3v3(mat[0], mat[1])) > 1.5 * FLT_EPSILON) + return 0; + + if (fabs(dot_v3v3(mat[1], mat[2])) > 1.5 * FLT_EPSILON) + return 0; + + if (fabs(dot_v3v3(mat[0], mat[2])) > 1.5 * FLT_EPSILON) + return 0; + + return 1; +} + +void normalize_m3(float mat[][3]) +{ + normalize_v3(mat[0]); + normalize_v3(mat[1]); + normalize_v3(mat[2]); +} + +void normalize_m4(float mat[][4]) +{ + float len; + + len= normalize_v3(mat[0]); + if(len!=0.0) mat[0][3]/= len; + len= normalize_v3(mat[1]); + if(len!=0.0) mat[1][3]/= len; + len= normalize_v3(mat[2]); + if(len!=0.0) mat[2][3]/= len; +} + +void adjoint_m3_m3(float m1[][3], float m[][3]) +{ + m1[0][0]=m[1][1]*m[2][2]-m[1][2]*m[2][1]; + m1[0][1]= -m[0][1]*m[2][2]+m[0][2]*m[2][1]; + m1[0][2]=m[0][1]*m[1][2]-m[0][2]*m[1][1]; + + m1[1][0]= -m[1][0]*m[2][2]+m[1][2]*m[2][0]; + m1[1][1]=m[0][0]*m[2][2]-m[0][2]*m[2][0]; + m1[1][2]= -m[0][0]*m[1][2]+m[0][2]*m[1][0]; + + m1[2][0]=m[1][0]*m[2][1]-m[1][1]*m[2][0]; + m1[2][1]= -m[0][0]*m[2][1]+m[0][1]*m[2][0]; + m1[2][2]=m[0][0]*m[1][1]-m[0][1]*m[1][0]; +} + +void adjoint_m4_m4(float out[][4], float in[][4]) /* out = ADJ(in) */ +{ + float a1, a2, a3, a4, b1, b2, b3, b4; + float c1, c2, c3, c4, d1, d2, d3, d4; + + a1= in[0][0]; + b1= in[0][1]; + c1= in[0][2]; + d1= in[0][3]; + + a2= in[1][0]; + b2= in[1][1]; + c2= in[1][2]; + d2= in[1][3]; + + a3= in[2][0]; + b3= in[2][1]; + c3= in[2][2]; + d3= in[2][3]; + + a4= in[3][0]; + b4= in[3][1]; + c4= in[3][2]; + d4= in[3][3]; + + + out[0][0] = determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4); + out[1][0] = - determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4); + out[2][0] = determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4); + out[3][0] = - determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4); + + out[0][1] = - determinant_m3(b1, b3, b4, c1, c3, c4, d1, d3, d4); + out[1][1] = determinant_m3(a1, a3, a4, c1, c3, c4, d1, d3, d4); + out[2][1] = - determinant_m3(a1, a3, a4, b1, b3, b4, d1, d3, d4); + out[3][1] = determinant_m3(a1, a3, a4, b1, b3, b4, c1, c3, c4); + + out[0][2] = determinant_m3(b1, b2, b4, c1, c2, c4, d1, d2, d4); + out[1][2] = - determinant_m3(a1, a2, a4, c1, c2, c4, d1, d2, d4); + out[2][2] = determinant_m3(a1, a2, a4, b1, b2, b4, d1, d2, d4); + out[3][2] = - determinant_m3(a1, a2, a4, b1, b2, b4, c1, c2, c4); + + out[0][3] = - determinant_m3(b1, b2, b3, c1, c2, c3, d1, d2, d3); + out[1][3] = determinant_m3(a1, a2, a3, c1, c2, c3, d1, d2, d3); + out[2][3] = - determinant_m3(a1, a2, a3, b1, b2, b3, d1, d2, d3); + out[3][3] = determinant_m3(a1, a2, a3, b1, b2, b3, c1, c2, c3); +} + +float determinant_m2(float a,float b,float c,float d) +{ + + return a*d - b*c; +} + +float determinant_m3(float a1, float a2, float a3, + float b1, float b2, float b3, + float c1, float c2, float c3) +{ + float ans; + + ans = a1 * determinant_m2(b2, b3, c2, c3) + - b1 * determinant_m2(a2, a3, c2, c3) + + c1 * determinant_m2(a2, a3, b2, b3); + + return ans; +} + +float determinant_m4(float m[][4]) +{ + float ans; + float a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4; + + a1= m[0][0]; + b1= m[0][1]; + c1= m[0][2]; + d1= m[0][3]; + + a2= m[1][0]; + b2= m[1][1]; + c2= m[1][2]; + d2= m[1][3]; + + a3= m[2][0]; + b3= m[2][1]; + c3= m[2][2]; + d3= m[2][3]; + + a4= m[3][0]; + b4= m[3][1]; + c4= m[3][2]; + d4= m[3][3]; + + ans = a1 * determinant_m3(b2, b3, b4, c2, c3, c4, d2, d3, d4) + - b1 * determinant_m3(a2, a3, a4, c2, c3, c4, d2, d3, d4) + + c1 * determinant_m3(a2, a3, a4, b2, b3, b4, d2, d3, d4) + - d1 * determinant_m3(a2, a3, a4, b2, b3, b4, c2, c3, c4); + + return ans; +} + +/****************************** Transformations ******************************/ + +void size_to_mat3(float mat[][3], float *size) +{ + mat[0][0]= size[0]; + mat[0][1]= 0.0f; + mat[0][2]= 0.0f; + mat[1][1]= size[1]; + mat[1][0]= 0.0f; + mat[1][2]= 0.0f; + mat[2][2]= size[2]; + mat[2][1]= 0.0f; + mat[2][0]= 0.0f; +} + +void size_to_mat4(float mat[][4], float *size) +{ + float tmat[3][3]; + + size_to_mat3(tmat,size); + unit_m4(mat); + copy_m4_m3(mat, tmat); +} + +void mat3_to_size(float *size, float mat[][3]) +{ + size[0]= len_v3(mat[0]); + size[1]= len_v3(mat[1]); + size[2]= len_v3(mat[2]); +} + +void mat4_to_size(float *size, float mat[][4]) +{ + size[0]= len_v3(mat[0]); + size[1]= len_v3(mat[1]); + size[2]= len_v3(mat[2]); +} + +/* this gets the average scale of a matrix, only use when your scaling + * data that has no idea of scale axis, examples are bone-envelope-radius + * and curve radius */ +float mat3_to_scale(float mat[][3]) +{ + /* unit length vector */ + float unit_vec[3] = {0.577350269189626f, 0.577350269189626f, 0.577350269189626f}; + mul_m3_v3(mat, unit_vec); + return len_v3(unit_vec); +} + +float mat4_to_scale(float mat[][4]) +{ + float tmat[3][3]; + copy_m3_m4(tmat, mat); + return mat3_to_scale(tmat); +} + +void scale_m3_fl(float m[][3], float scale) +{ + m[0][0]= m[1][1]= m[2][2]= scale; + m[0][1]= m[0][2]= 0.0; + m[1][0]= m[1][2]= 0.0; + m[2][0]= m[2][1]= 0.0; +} + +void scale_m4_fl(float m[][4], float scale) +{ + m[0][0]= m[1][1]= m[2][2]= scale; + m[3][3]= 1.0; + m[0][1]= m[0][2]= m[0][3]= 0.0; + m[1][0]= m[1][2]= m[1][3]= 0.0; + m[2][0]= m[2][1]= m[2][3]= 0.0; + m[3][0]= m[3][1]= m[3][2]= 0.0; +} + +void translate_m4(float mat[][4],float Tx, float Ty, float Tz) +{ + mat[3][0] += (Tx*mat[0][0] + Ty*mat[1][0] + Tz*mat[2][0]); + mat[3][1] += (Tx*mat[0][1] + Ty*mat[1][1] + Tz*mat[2][1]); + mat[3][2] += (Tx*mat[0][2] + Ty*mat[1][2] + Tz*mat[2][2]); +} + +void rotate_m4(float mat[][4], char axis,float angle) +{ + int col; + float temp[4]; + float cosine, sine; + + for(col=0; col<4 ; col++) /* init temp to zero matrix */ + temp[col] = 0; + + angle = (float)(angle*(3.1415926535/180.0)); + cosine = (float)cos(angle); + sine = (float)sin(angle); + switch(axis){ + case 'x': + case 'X': + for(col=0 ; col<4 ; col++) + temp[col] = cosine*mat[1][col] + sine*mat[2][col]; + for(col=0 ; col<4 ; col++) { + mat[2][col] = - sine*mat[1][col] + cosine*mat[2][col]; + mat[1][col] = temp[col]; + } + break; + + case 'y': + case 'Y': + for(col=0 ; col<4 ; col++) + temp[col] = cosine*mat[0][col] - sine*mat[2][col]; + for(col=0 ; col<4 ; col++) { + mat[2][col] = sine*mat[0][col] + cosine*mat[2][col]; + mat[0][col] = temp[col]; + } + break; + + case 'z': + case 'Z': + for(col=0 ; col<4 ; col++) + temp[col] = cosine*mat[0][col] + sine*mat[1][col]; + for(col=0 ; col<4 ; col++) { + mat[1][col] = - sine*mat[0][col] + cosine*mat[1][col]; + mat[0][col] = temp[col]; + } + break; + } +} + +void blend_m3_m3m3(float out[][3], float dst[][3], float src[][3], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float rmat[3][3], smat[3][3]; + + mat3_to_quat(dquat,dst); + mat3_to_size(dsize,dst); + + mat3_to_quat(squat,src); + mat3_to_size(ssize,src); + + /* do blending */ + interp_qt_qtqt(fquat, dquat, squat, srcweight); + interp_v3_v3v3(fsize, dsize, ssize, srcweight); + + /* compose new matrix */ + quat_to_mat3(rmat,fquat); + size_to_mat3(smat,fsize); + mul_m3_m3m3(out, rmat, smat); +} + +void blend_m4_m4m4(float out[][4], float dst[][4], float src[][4], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float sloc[3], dloc[3], floc[3]; + + mat4_to_quat(dquat,dst); + mat4_to_size(dsize,dst); + copy_v3_v3(dloc, dst[3]); + + mat4_to_quat(squat,src); + mat4_to_size(ssize,src); + copy_v3_v3(sloc, src[3]); + + /* do blending */ + interp_v3_v3v3(floc, dloc, sloc, srcweight); + interp_qt_qtqt(fquat, dquat, squat, srcweight); + interp_v3_v3v3(fsize, dsize, ssize, srcweight); + + /* compose new matrix */ + loc_quat_size_to_mat4(out, floc, fquat, fsize); +} + +/* make a 4x4 matrix out of 3 transform components */ +/* matrices are made in the order: scale * rot * loc */ +// TODO: need to have a version that allows for rotation order... +void loc_eul_size_to_mat4(float mat[4][4], float loc[3], float eul[3], float size[3]) +{ + float rmat[3][3], smat[3][3], tmat[3][3]; + + /* initialise new matrix */ + unit_m4(mat); + + /* make rotation + scaling part */ + eul_to_mat3(rmat,eul); + size_to_mat3(smat,size); + mul_m3_m3m3(tmat, rmat, smat); + + /* copy rot/scale part to output matrix*/ + copy_m4_m3(mat, tmat); + + /* copy location to matrix */ + mat[3][0] = loc[0]; + mat[3][1] = loc[1]; + mat[3][2] = loc[2]; +} + +/* make a 4x4 matrix out of 3 transform components */ +/* matrices are made in the order: scale * rot * loc */ +void loc_eulO_size_to_mat4(float mat[4][4], float loc[3], float eul[3], float size[3], short rotOrder) +{ + float rmat[3][3], smat[3][3], tmat[3][3]; + + /* initialise new matrix */ + unit_m4(mat); + + /* make rotation + scaling part */ + eulO_to_mat3(rmat,eul, rotOrder); + size_to_mat3(smat,size); + mul_m3_m3m3(tmat, rmat, smat); + + /* copy rot/scale part to output matrix*/ + copy_m4_m3(mat, tmat); + + /* copy location to matrix */ + mat[3][0] = loc[0]; + mat[3][1] = loc[1]; + mat[3][2] = loc[2]; +} + + +/* make a 4x4 matrix out of 3 transform components */ +/* matrices are made in the order: scale * rot * loc */ +void loc_quat_size_to_mat4(float mat[4][4], float loc[3], float quat[4], float size[3]) +{ + float rmat[3][3], smat[3][3], tmat[3][3]; + + /* initialise new matrix */ + unit_m4(mat); + + /* make rotation + scaling part */ + quat_to_mat3(rmat,quat); + size_to_mat3(smat,size); + mul_m3_m3m3(tmat, rmat, smat); + + /* copy rot/scale part to output matrix*/ + copy_m4_m3(mat, tmat); + + /* copy location to matrix */ + mat[3][0] = loc[0]; + mat[3][1] = loc[1]; + mat[3][2] = loc[2]; +} + +/*********************************** Other ***********************************/ + +void print_m3(char *str, float m[][3]) +{ + printf("%s\n", str); + printf("%f %f %f\n",m[0][0],m[1][0],m[2][0]); + printf("%f %f %f\n",m[0][1],m[1][1],m[2][1]); + printf("%f %f %f\n",m[0][2],m[1][2],m[2][2]); + printf("\n"); +} + +void print_m4(char *str, float m[][4]) +{ + printf("%s\n", str); + printf("%f %f %f %f\n",m[0][0],m[1][0],m[2][0],m[3][0]); + printf("%f %f %f %f\n",m[0][1],m[1][1],m[2][1],m[3][1]); + printf("%f %f %f %f\n",m[0][2],m[1][2],m[2][2],m[3][2]); + printf("%f %f %f %f\n",m[0][3],m[1][3],m[2][3],m[3][3]); + printf("\n"); +} + |