00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <math.h>
00024 #include <string.h>
00025 #include <stdio.h>
00026 #include "Matrix4.h"
00027 #include "utilities.h"
00028
00029
00030 Matrix4::Matrix4(const float *m) {
00031 memcpy((void *)mat, (const void *)m, 16*sizeof(float));
00032 }
00033
00034
00035 void Matrix4::multpoint3d(const float opoint[3], float npoint[3]) const {
00036 #if 0
00037
00038
00039 float tmp[3];
00040 float itmp3 = 1.0f / (opoint[0]*mat[3] + opoint[1]*mat[7] +
00041 opoint[2]*mat[11] + mat[15]);
00042 npoint[0]=itmp3 * (opoint[0]*mat[0] + opoint[1]*mat[4] + opoint[2]*mat[ 8] + mat[12]);
00043 npoint[1]=itmp3 * (opoint[0]*mat[1] + opoint[1]*mat[5] + opoint[2]*mat[ 9] + mat[13]);
00044 npoint[2]=itmp3 * (opoint[0]*mat[2] + opoint[1]*mat[6] + opoint[2]*mat[10] + mat[14]);
00045 #else
00046 float tmp[3];
00047 float itmp3 = 1.0f / (opoint[0]*mat[3] + opoint[1]*mat[7] +
00048 opoint[2]*mat[11] + mat[15]);
00049 tmp[0] = itmp3*opoint[0];
00050 tmp[1] = itmp3*opoint[1];
00051 tmp[2] = itmp3*opoint[2];
00052 npoint[0]=tmp[0]*mat[0] + tmp[1]*mat[4] + tmp[2]*mat[ 8] + itmp3*mat[12];
00053 npoint[1]=tmp[0]*mat[1] + tmp[1]*mat[5] + tmp[2]*mat[ 9] + itmp3*mat[13];
00054 npoint[2]=tmp[0]*mat[2] + tmp[1]*mat[6] + tmp[2]*mat[10] + itmp3*mat[14];
00055 #endif
00056 }
00057
00058
00059
00060
00061
00062 void Matrix4::multnorm3d(const float onorm[3], float nnorm[3]) const {
00063 float tmp[4];
00064
00065 tmp[0]=onorm[0]*mat[0] + onorm[1]*mat[4] + onorm[2]*mat[8];
00066 tmp[1]=onorm[0]*mat[1] + onorm[1]*mat[5] + onorm[2]*mat[9];
00067 tmp[2]=onorm[0]*mat[2] + onorm[1]*mat[6] + onorm[2]*mat[10];
00068 tmp[3]=onorm[0]*mat[3] + onorm[1]*mat[7] + onorm[2]*mat[11];
00069 float itmp = 1.0f / sqrtf(tmp[0]*tmp[0] + tmp[1]*tmp[1] + tmp[2]*tmp[2]);
00070 nnorm[0]=tmp[0]*itmp;
00071 nnorm[1]=tmp[1]*itmp;
00072 nnorm[2]=tmp[2]*itmp;
00073 }
00074
00075
00076
00077 void Matrix4::multpoint4d(const float opoint[4], float npoint[4]) const {
00078 npoint[0]=opoint[0]*mat[0]+opoint[1]*mat[4]+opoint[2]*mat[8]+opoint[3]*mat[12];
00079 npoint[1]=opoint[0]*mat[1]+opoint[1]*mat[5]+opoint[2]*mat[9]+opoint[3]*mat[13];
00080 npoint[2]=opoint[0]*mat[2]+opoint[1]*mat[6]+opoint[2]*mat[10]+opoint[3]*mat[14];
00081 npoint[3]=opoint[0]*mat[3]+opoint[1]*mat[7]+opoint[2]*mat[11]+opoint[3]*mat[15];
00082 }
00083
00084
00085
00086 void Matrix4::identity(void) {
00087 memset((void *)mat, 0, 16*sizeof(float));
00088 mat[0]=1.0f;
00089 mat[5]=1.0f;
00090 mat[10]=1.0f;
00091 mat[15]=1.0f;
00092 }
00093
00094
00095
00096 void Matrix4::constant(float f) {
00097 for (int i=0; i<16; mat[i++] = f);
00098 }
00099
00100
00101
00102
00103 #define MATSWAP(a,b) {temp=(a);(a)=(b);(b)=temp;}
00104 int Matrix4::inverse(void) {
00105
00106 float matr[4][4], ident[4][4];
00107 int i, j, k, l, ll;
00108 int icol=0, irow=0;
00109 int indxc[4], indxr[4], ipiv[4];
00110 float big, dum, pivinv, temp;
00111
00112 for (i=0; i<4; i++) {
00113 for (j=0; j<4; j++) {
00114 matr[i][j] = mat[4*i+j];
00115 ident[i][j] = 0.0f;
00116 }
00117 ident[i][i]=1.0f;
00118 }
00119
00120
00121
00122
00123
00124
00125 for(j=0;j<=3;j++) ipiv[j] = 0;
00126 for(i=0;i<=3;i++) {
00127 big=0.0;
00128 for (j=0;j<=3;j++) {
00129 if(ipiv[j] != 1) {
00130 for (k=0;k<=3;k++) {
00131 if(ipiv[k] == 0) {
00132 if(fabs(matr[j][k]) >= big) {
00133 big = (float) fabs(matr[j][k]);
00134 irow=j;
00135 icol=k;
00136 }
00137 } else if (ipiv[k] > 1) return 1;
00138 }
00139 }
00140 }
00141 ++(ipiv[icol]);
00142 if (irow != icol) {
00143 for (l=0;l<=3;l++) MATSWAP(matr[irow][l],matr[icol][l]);
00144 for (l=0;l<=3;l++) MATSWAP(ident[irow][l],ident[icol][l]);
00145 }
00146 indxr[i]=irow;
00147 indxc[i]=icol;
00148 if(matr[icol][icol] == 0.0f) return 1;
00149 pivinv = 1.0f / matr[icol][icol];
00150 matr[icol][icol]=1.0f;
00151 for (l=0;l<=3;l++) matr[icol][l] *= pivinv;
00152 for (l=0;l<=3;l++) ident[icol][l] *= pivinv;
00153 for (ll=0;ll<=3;ll++) {
00154 if (ll != icol) {
00155 dum=matr[ll][icol];
00156 matr[ll][icol]=0.0f;
00157 for (l=0;l<=3;l++) matr[ll][l] -= matr[icol][l]*dum;
00158 for (l=0;l<=3;l++) ident[ll][l] -= ident[icol][l]*dum;
00159 }
00160 }
00161 }
00162 for (l=3;l>=0;l--) {
00163 if (indxr[l] != indxc[l]) {
00164 for (k=0;k<=3;k++) {
00165 MATSWAP(matr[k][indxr[l]],matr[k][indxc[l]]);
00166 }
00167 }
00168 }
00169 for (i=0; i<4; i++)
00170 for (j=0; j<4; j++)
00171 mat[4*i+j] = matr[i][j];
00172 return 0;
00173 }
00174
00175 void Matrix4::transpose() {
00176 float tmp[16];
00177 int i,j;
00178 for(i=0;i<4;i++) {
00179 for(j=0;j<4;j++) {
00180 tmp[4*i+j] = mat[i+4*j];
00181 }
00182 }
00183 for(i=0;i<16;i++)
00184 mat[i] = tmp[i];
00185 }
00186
00187
00188 void Matrix4::loadmatrix(const Matrix4& m) {
00189 memcpy((void *)mat, (const void *)m.mat, 16*sizeof(float));
00190 }
00191
00192
00193 void Matrix4::multmatrix(const Matrix4& m) {
00194 float tmp[4];
00195 for (int j=0; j<4; j++) {
00196 tmp[0] = mat[j];
00197 tmp[1] = mat[4+j];
00198 tmp[2] = mat[8+j];
00199 tmp[3] = mat[12+j];
00200 for (int i=0; i<4; i++) {
00201 mat[4*i+j] = m.mat[4*i]*tmp[0] + m.mat[4*i+1]*tmp[1] +
00202 m.mat[4*i+2]*tmp[2] + m.mat[4*i+3]*tmp[3];
00203 }
00204 }
00205 }
00206
00207
00208
00209 void Matrix4::rot(float a, char axis) {
00210 Matrix4 m;
00211 double angle;
00212
00213 angle = (double)DEGTORAD(a);
00214
00215 if (axis == 'x') {
00216 m.mat[0]=1.0;
00217 m.mat[5]=(float)cos(angle);
00218 m.mat[10]=m.mat[5];
00219 m.mat[6] = (float)sin(angle);
00220 m.mat[9] = -m.mat[6];
00221 } else if (axis == 'y') {
00222 m.mat[0] = (float)cos(angle);
00223 m.mat[5] = 1.0;
00224 m.mat[10] = m.mat[0];
00225 m.mat[2] = (float) -sin(angle);
00226 m.mat[8] = -m.mat[2];
00227 } else if (axis == 'z') {
00228 m.mat[0] = (float)cos(angle);
00229 m.mat[5] = m.mat[0];
00230 m.mat[10] = 1.0;
00231 m.mat[1] = (float)sin(angle);
00232 m.mat[4] = -m.mat[1];
00233 }
00234
00235 multmatrix(m);
00236 }
00237
00238
00239 void Matrix4::rotate_axis(const float axis[3], float angle) {
00240 transvec(axis[0], axis[1], axis[2]);
00241 rot((float) (RADTODEG(angle)), 'x');
00242 transvecinv(axis[0], axis[1], axis[2]);
00243 }
00244
00245
00246 void Matrix4::transvec(float x, float y, float z) {
00247 double theta = atan2(y,x);
00248 double length = sqrt(y*y + x*x);
00249 double phi = atan2((double) z, length);
00250 rot((float) RADTODEG(theta), 'z');
00251 rot((float) RADTODEG(-phi), 'y');
00252 }
00253
00254
00255 void Matrix4::transvecinv(float x, float y, float z) {
00256 double theta = atan2(y,x);
00257 double length = sqrt(y*y + x*x);
00258 double phi = atan2((double) z, length);
00259 rot((float) RADTODEG(phi), 'y');
00260 rot((float) RADTODEG(-theta), 'z');
00261 }
00262
00263
00264 void Matrix4::translate(float x, float y, float z) {
00265 Matrix4 m;
00266 m.mat[12] = x;
00267 m.mat[13] = y;
00268 m.mat[14] = z;
00269 multmatrix(m);
00270 }
00271
00272
00273 void Matrix4::scale(float x, float y, float z) {
00274 Matrix4 m;
00275 m.mat[0] = x;
00276 m.mat[5] = y;
00277 m.mat[10] = z;
00278 multmatrix(m);
00279 }
00280
00281
00282 void Matrix4::window(float left, float right, float bottom,
00283 float top, float nearval, float farval) {
00284
00285 constant(0.0);
00286 mat[0] = (2.0f*nearval) / (right-left);
00287 mat[5] = (2.0f*nearval) / (top-bottom);
00288 mat[8] = (right+left) / (right-left);
00289 mat[9] = (top+bottom) / (top-bottom);
00290 mat[10] = -(farval+nearval) / (farval-nearval);
00291 mat[11] = -1.0f;
00292 mat[14] = -(2.0f*farval*nearval) / (farval-nearval);
00293 }
00294
00295
00296
00297 void Matrix4::ortho(float left, float right, float bottom,
00298 float top, float nearval, float farval) {
00299
00300 constant(0.0);
00301 mat[0] = 2.0f / (right-left);
00302 mat[5] = 2.0f / (top-bottom);
00303 mat[10] = -2.0f / (farval-nearval);
00304 mat[12] = -(right+left) / (right-left);
00305 mat[13] = -(top+bottom) / (top-bottom);
00306 mat[14] = -(farval+nearval) / (farval-nearval);
00307 mat[15] = 1.0;
00308 }
00309
00310
00311
00312 void Matrix4::ortho2(float left, float right, float bottom, float top) {
00313
00314 constant(0.0);
00315 mat[0] = 2.0f / (right-left);
00316 mat[5] = 2.0f / (top-bottom);
00317 mat[10] = -1.0f;
00318 mat[12] = -(right+left) / (right-left);
00319 mat[13] = -(top+bottom) / (top-bottom);
00320 mat[15] = 1.0f;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
00330 void Matrix4::lookat(float vx, float vy, float vz, float px, float py,
00331 float pz, short twist) {
00332 Matrix4 m(0.0);
00333 float tmp;
00334
00335
00336 rot(-twist / 10.0f,'z');
00337
00338 tmp = sqrtf((px-vx)*(px-vx) + (py-vy)*(py-vy) + (pz-vz)*(pz-vz));
00339 m.mat[0] = 1.0;
00340 m.mat[5] = sqrtf((px-vx)*(px-vx) + (pz-vz)*(pz-vz)) / tmp;
00341 m.mat[6] = (vy-py) / tmp;
00342 m.mat[9] = -m.mat[6];
00343 m.mat[10] = m.mat[5];
00344 m.mat[15] = 1.0;
00345 multmatrix(m);
00346
00347
00348 m.constant(0.0);
00349 tmp = sqrtf((px-vx)*(px-vx) + (pz-vz)*(pz-vz));
00350 m.mat[0] = (vz-pz) / tmp;
00351 m.mat[5] = 1.0;
00352 m.mat[10] = m.mat[0];
00353 m.mat[15] = 1.0;
00354 m.mat[2] = -(px-vx) / tmp;
00355 m.mat[8] = -m.mat[2];
00356 multmatrix(m);
00357
00358
00359 translate(-vx,-vy,-vz);
00360 }
00361
00362
00363 void trans_from_rotate(const float mat3[9], Matrix4 *mat4) {
00364 int i;
00365 for (i=0; i<3; i++) {
00366 mat4->mat[0+i] = mat3[3*i];
00367 mat4->mat[4+i] = mat3[3*i+1];
00368 mat4->mat[8+i] = mat3[3*i+2];
00369 }
00370 }
00371
00372
00373 void print_Matrix4(const Matrix4 *mat4) {
00374 int i, j;
00375 for (i=0; i<4; i++) {
00376 for (j=0; j<4; j++) {
00377 printf("%f ", mat4->mat[4*j+i]);
00378 }
00379 printf("\n");
00380 }
00381 printf("\n");
00382 }
00383