00001 /* 00002 File: Mat4.cc 00003 00004 Function: Implements Mat4.h 00005 00006 Author(s): Andrew Willmott 00007 00008 Copyright: (c) 1995-2000, Andrew Willmott 00009 00010 Notes: 00011 00012 */ 00013 00014 00015 #include "vl/Mat4.h" 00016 #include <ctype.h> 00017 #include <iomanip.h> 00018 00019 00020 TMat4::TMat4(TMReal a, TMReal b, TMReal c, TMReal d, 00021 TMReal e, TMReal f, TMReal g, TMReal h, 00022 TMReal i, TMReal j, TMReal k, TMReal l, 00023 TMReal m, TMReal n, TMReal o, TMReal p) 00024 { 00025 row[0][0] = a; row[0][1] = b; row[0][2] = c; row[0][3] = d; 00026 row[1][0] = e; row[1][1] = f; row[1][2] = g; row[1][3] = h; 00027 row[2][0] = i; row[2][1] = j; row[2][2] = k; row[2][3] = l; 00028 row[3][0] = m; row[3][1] = n; row[3][2] = o; row[3][3] = p; 00029 } 00030 00031 TMat4::TMat4(const TMat4 &m) 00032 { 00033 row[0] = m[0]; 00034 row[1] = m[1]; 00035 row[2] = m[2]; 00036 row[3] = m[3]; 00037 } 00038 00039 00040 TMat4 &TMat4::operator = (const TMat4 &m) 00041 { 00042 row[0] = m[0]; 00043 row[1] = m[1]; 00044 row[2] = m[2]; 00045 row[3] = m[3]; 00046 00047 return(SELF); 00048 } 00049 00050 TMat4 &TMat4::operator += (const TMat4 &m) 00051 { 00052 row[0] += m[0]; 00053 row[1] += m[1]; 00054 row[2] += m[2]; 00055 row[3] += m[3]; 00056 00057 return(SELF); 00058 } 00059 00060 TMat4 &TMat4::operator -= (const TMat4 &m) 00061 { 00062 row[0] -= m[0]; 00063 row[1] -= m[1]; 00064 row[2] -= m[2]; 00065 row[3] -= m[3]; 00066 00067 return(SELF); 00068 } 00069 00070 TMat4 &TMat4::operator *= (const TMat4 &m) 00071 { 00072 SELF = SELF * m; 00073 00074 return(SELF); 00075 } 00076 00077 TMat4 &TMat4::operator *= (TMReal s) 00078 { 00079 row[0] *= s; 00080 row[1] *= s; 00081 row[2] *= s; 00082 row[3] *= s; 00083 00084 return(SELF); 00085 } 00086 00087 TMat4 &TMat4::operator /= (TMReal s) 00088 { 00089 row[0] /= s; 00090 row[1] /= s; 00091 row[2] /= s; 00092 row[3] /= s; 00093 00094 return(SELF); 00095 } 00096 00097 00098 Bool TMat4::operator == (const TMat4 &m) const 00099 { 00100 return(row[0] == m[0] && row[1] == m[1] && row[2] == m[2] && row[3] == m[3]); 00101 } 00102 00103 Bool TMat4::operator != (const TMat4 &m) const 00104 { 00105 return(row[0] != m[0] || row[1] != m[1] || row[2] != m[2] || row[3] != m[3]); 00106 } 00107 00108 00109 TMat4 TMat4::operator + (const TMat4 &m) const 00110 { 00111 TMat4 result; 00112 00113 result[0] = row[0] + m[0]; 00114 result[1] = row[1] + m[1]; 00115 result[2] = row[2] + m[2]; 00116 result[3] = row[3] + m[3]; 00117 00118 return(result); 00119 } 00120 00121 TMat4 TMat4::operator - (const TMat4 &m) const 00122 { 00123 TMat4 result; 00124 00125 result[0] = row[0] - m[0]; 00126 result[1] = row[1] - m[1]; 00127 result[2] = row[2] - m[2]; 00128 result[3] = row[3] - m[3]; 00129 00130 return(result); 00131 } 00132 00133 TMat4 TMat4::operator - () const 00134 { 00135 TMat4 result; 00136 00137 result[0] = -row[0]; 00138 result[1] = -row[1]; 00139 result[2] = -row[2]; 00140 result[3] = -row[3]; 00141 00142 return(result); 00143 } 00144 00145 TMat4 TMat4::operator * (const TMat4 &m) const 00146 { 00147 #define N(x,y) row[x][y] 00148 #define M(x,y) m[x][y] 00149 #define R(x,y) result[x][y] 00150 00151 TMat4 result; 00152 00153 R(0,0) = N(0,0) * M(0,0) + N(0,1) * M(1,0) + N(0,2) * M(2,0) + N(0,3) * M(3,0); 00154 R(0,1) = N(0,0) * M(0,1) + N(0,1) * M(1,1) + N(0,2) * M(2,1) + N(0,3) * M(3,1); 00155 R(0,2) = N(0,0) * M(0,2) + N(0,1) * M(1,2) + N(0,2) * M(2,2) + N(0,3) * M(3,2); 00156 R(0,3) = N(0,0) * M(0,3) + N(0,1) * M(1,3) + N(0,2) * M(2,3) + N(0,3) * M(3,3); 00157 00158 R(1,0) = N(1,0) * M(0,0) + N(1,1) * M(1,0) + N(1,2) * M(2,0) + N(1,3) * M(3,0); 00159 R(1,1) = N(1,0) * M(0,1) + N(1,1) * M(1,1) + N(1,2) * M(2,1) + N(1,3) * M(3,1); 00160 R(1,2) = N(1,0) * M(0,2) + N(1,1) * M(1,2) + N(1,2) * M(2,2) + N(1,3) * M(3,2); 00161 R(1,3) = N(1,0) * M(0,3) + N(1,1) * M(1,3) + N(1,2) * M(2,3) + N(1,3) * M(3,3); 00162 00163 R(2,0) = N(2,0) * M(0,0) + N(2,1) * M(1,0) + N(2,2) * M(2,0) + N(2,3) * M(3,0); 00164 R(2,1) = N(2,0) * M(0,1) + N(2,1) * M(1,1) + N(2,2) * M(2,1) + N(2,3) * M(3,1); 00165 R(2,2) = N(2,0) * M(0,2) + N(2,1) * M(1,2) + N(2,2) * M(2,2) + N(2,3) * M(3,2); 00166 R(2,3) = N(2,0) * M(0,3) + N(2,1) * M(1,3) + N(2,2) * M(2,3) + N(2,3) * M(3,3); 00167 00168 R(3,0) = N(3,0) * M(0,0) + N(3,1) * M(1,0) + N(3,2) * M(2,0) + N(3,3) * M(3,0); 00169 R(3,1) = N(3,0) * M(0,1) + N(3,1) * M(1,1) + N(3,2) * M(2,1) + N(3,3) * M(3,1); 00170 R(3,2) = N(3,0) * M(0,2) + N(3,1) * M(1,2) + N(3,2) * M(2,2) + N(3,3) * M(3,2); 00171 R(3,3) = N(3,0) * M(0,3) + N(3,1) * M(1,3) + N(3,2) * M(2,3) + N(3,3) * M(3,3); 00172 00173 return(result); 00174 00175 #undef N 00176 #undef M 00177 #undef R 00178 } 00179 00180 TMat4 TMat4::operator * (TMReal s) const 00181 { 00182 TMat4 result; 00183 00184 result[0] = row[0] * s; 00185 result[1] = row[1] * s; 00186 result[2] = row[2] * s; 00187 result[3] = row[3] * s; 00188 00189 return(result); 00190 } 00191 00192 TMat4 TMat4::operator / (TMReal s) const 00193 { 00194 TMat4 result; 00195 00196 result[0] = row[0] / s; 00197 result[1] = row[1] / s; 00198 result[2] = row[2] / s; 00199 result[3] = row[3] / s; 00200 00201 return(result); 00202 } 00203 00204 TMVec4 operator * (const TMat4 &m, const TMVec4 &v) // m * v 00205 { 00206 TMVec4 result; 00207 00208 result[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2] + v[3] * m[0][3]; 00209 result[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2] + v[3] * m[1][3]; 00210 result[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2] + v[3] * m[2][3]; 00211 result[3] = v[0] * m[3][0] + v[1] * m[3][1] + v[2] * m[3][2] + v[3] * m[3][3]; 00212 00213 return(result); 00214 } 00215 00216 TMVec4 operator * (const TMVec4 &v, const TMat4 &m) // v * m 00217 { 00218 TMVec4 result; 00219 00220 result[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + v[3] * m[3][0]; 00221 result[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + v[3] * m[3][1]; 00222 result[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + v[3] * m[3][2]; 00223 result[3] = v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + v[3] * m[3][3]; 00224 00225 return(result); 00226 } 00227 00228 TMVec4 &operator *= (TMVec4 &v, const TMat4 &m) // v *= m 00229 { 00230 TMReal t0, t1, t2; 00231 00232 t0 = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + v[3] * m[3][0]; 00233 t1 = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + v[3] * m[3][1]; 00234 t2 = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + v[3] * m[3][2]; 00235 v[3] = v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + v[3] * m[3][3]; 00236 v[0] = t0; 00237 v[1] = t1; 00238 v[2] = t2; 00239 00240 return(v); 00241 } 00242 00243 TMat4 trans(const TMat4 &m) 00244 { 00245 #define M(x,y) m[x][y] 00246 #define R(x,y) result[x][y] 00247 00248 TMat4 result; 00249 00250 R(0,0) = M(0,0); R(0,1) = M(1,0); R(0,2) = M(2,0); R(0,3) = M(3,0); 00251 R(1,0) = M(0,1); R(1,1) = M(1,1); R(1,2) = M(2,1); R(1,3) = M(3,1); 00252 R(2,0) = M(0,2); R(2,1) = M(1,2); R(2,2) = M(2,2); R(2,3) = M(3,2); 00253 R(3,0) = M(0,3); R(3,1) = M(1,3); R(3,2) = M(2,3); R(3,3) = M(3,3); 00254 00255 return(result); 00256 00257 #undef M 00258 #undef R 00259 } 00260 00261 TMat4 adj(const TMat4 &m) 00262 { 00263 TMat4 result; 00264 00265 result[0] = cross(m[1], m[2], m[3]); 00266 result[1] = -cross(m[0], m[2], m[3]); 00267 result[2] = cross(m[0], m[1], m[3]); 00268 result[3] = -cross(m[0], m[1], m[2]); 00269 00270 return(result); 00271 } 00272 00273 TMReal trace(const TMat4 &m) 00274 { 00275 return(m[0][0] + m[1][1] + m[2][2] + m[3][3]); 00276 } 00277 00278 TMReal det(const TMat4 &m) 00279 { 00280 return(dot(m[0], cross(m[1], m[2], m[3]))); 00281 } 00282 00283 TMat4 inv(const TMat4 &m) 00284 { 00285 TMReal mDet; 00286 TMat4 adjoint; 00287 TMat4 result; 00288 00289 adjoint = adj(m); // Find the adjoint 00290 mDet = dot(adjoint[0], m[0]); 00291 00292 Assert(mDet != 0, "(Mat4::inv) matrix is non-singular"); 00293 00294 result = trans(adjoint); 00295 result /= mDet; 00296 00297 return(result); 00298 } 00299 00300 TMat4 oprod(const TMVec4 &a, const TMVec4 &b) 00301 // returns outerproduct of a and b: a * trans(b) 00302 { 00303 TMat4 result; 00304 00305 result[0] = a[0] * b; 00306 result[1] = a[1] * b; 00307 result[2] = a[2] * b; 00308 result[3] = a[3] * b; 00309 00310 return(result); 00311 } 00312 00313 Void TMat4::MakeZero() 00314 { 00315 Int i; 00316 00317 for (i = 0; i < 16; i++) 00318 ((TMReal *) row)[i] = vl_zero; 00319 } 00320 00321 Void TMat4::MakeDiag(TMReal k) 00322 { 00323 Int i, j; 00324 00325 for (i = 0; i < 4; i++) 00326 for (j = 0; j < 4; j++) 00327 if (i == j) 00328 row[i][j] = k; 00329 else 00330 row[i][j] = vl_zero; 00331 } 00332 00333 Void TMat4::MakeBlock(TMReal k) 00334 { 00335 Int i; 00336 00337 for (i = 0; i < 16; i++) 00338 ((TMReal *) row)[i] = k; 00339 } 00340 00341 ostream &operator << (ostream &s, const TMat4 &m) 00342 { 00343 Int w = s.width(); 00344 00345 return(s << '[' << m[0] << endl << setw(w) << m[1] << endl 00346 << setw(w) << m[2] << endl << setw(w) << m[3] << ']' << endl); 00347 } 00348 00349 istream &operator >> (istream &s, TMat4 &m) 00350 { 00351 TMat4 result; 00352 Char c; 00353 00354 // Expected format: [[1 2 3] [4 5 6] [7 8 9]] 00355 // Each vector is a column of the matrix. 00356 00357 while (s >> c && isspace(c)) // ignore leading white space 00358 ; 00359 00360 if (c == '[') 00361 { 00362 s >> result[0] >> result[1] >> result[2] >> result[3]; 00363 00364 if (!s) 00365 { 00366 cerr << "Expected number while reading matrix\n"; 00367 return(s); 00368 } 00369 00370 while (s >> c && isspace(c)) 00371 ; 00372 00373 if (c != ']') 00374 { 00375 s.clear(ios::failbit); 00376 cerr << "Expected ']' while reading matrix\n"; 00377 return(s); 00378 } 00379 } 00380 else 00381 { 00382 s.clear(ios::failbit); 00383 cerr << "Expected '[' while reading matrix\n"; 00384 return(s); 00385 } 00386 00387 m = result; 00388 return(s); 00389 } 00390 00391 00392 TMat4& TMat4::MakeHRot(const TQuaternion &q) 00393 { 00394 TMReal i2 = 2 * q[0], 00395 j2 = 2 * q[1], 00396 k2 = 2 * q[2], 00397 ij = i2 * q[1], 00398 ik = i2 * q[2], 00399 jk = j2 * q[2], 00400 ri = i2 * q[3], 00401 rj = j2 * q[3], 00402 rk = k2 * q[3]; 00403 00404 MakeDiag(); 00405 00406 i2 *= q[0]; 00407 j2 *= q[1]; 00408 k2 *= q[2]; 00409 00410 #if VL_ROW_ORIENT 00411 row[0][0] = 1 - j2 - k2; row[0][1] = ij + rk ; row[0][2] = ik - rj; 00412 row[1][0] = ij - rk ; row[1][1] = 1 - i2- k2; row[1][2] = jk + ri; 00413 row[2][0] = ik + rj ; row[2][1] = jk - ri ; row[2][2] = 1 - i2 - j2; 00414 #else 00415 row[0][0] = 1 - j2 - k2; row[0][1] = ij - rk ; row[0][2] = ik + rj; 00416 row[1][0] = ij + rk ; row[1][1] = 1 - i2- k2; row[1][2] = jk - ri; 00417 row[2][0] = ik - rj ; row[2][1] = jk + ri ; row[2][2] = 1 - i2 - j2; 00418 #endif 00419 00420 return(SELF); 00421 } 00422 00423 TMat4& TMat4::MakeHRot(const TMVec3 &axis, Real theta) 00424 { 00425 TMReal s; 00426 TMVec4 q; 00427 00428 theta /= 2.0; 00429 s = sin(theta); 00430 00431 q[0] = s * axis[0]; 00432 q[1] = s * axis[1]; 00433 q[2] = s * axis[2]; 00434 q[3] = cos(theta); 00435 00436 MakeHRot(q); 00437 00438 return(SELF); 00439 } 00440 00441 TMat4& TMat4::MakeHScale(const TMVec3 &s) 00442 { 00443 MakeDiag(); 00444 00445 row[0][0] = s[0]; 00446 row[1][1] = s[1]; 00447 row[2][2] = s[2]; 00448 00449 return(SELF); 00450 } 00451 00452 TMat4& TMat4::MakeHTrans(const TMVec3 &t) 00453 { 00454 MakeDiag(); 00455 00456 #ifdef VL_ROW_ORIENT 00457 row[3][0] = t[0]; 00458 row[3][1] = t[1]; 00459 row[3][2] = t[2]; 00460 #else 00461 row[0][3] = t[0]; 00462 row[1][3] = t[1]; 00463 row[2][3] = t[2]; 00464 #endif 00465 00466 return(SELF); 00467 } 00468 00469 TMat4& TMat4::Transpose() 00470 { 00471 row[0][1] = row[1][0]; row[0][2] = row[2][0]; row[0][3] = row[3][0]; 00472 row[1][0] = row[0][1]; row[1][2] = row[2][1]; row[1][3] = row[3][1]; 00473 row[2][0] = row[0][2]; row[2][1] = row[1][2]; row[2][3] = row[3][2]; 00474 row[3][0] = row[0][3]; row[3][1] = row[1][3]; row[3][2] = row[2][3]; 00475 00476 return(SELF); 00477 } 00478 00479 TMat4& TMat4::AddShift(const TMVec3 &t) 00480 { 00481 #ifdef VL_ROW_ORIENT 00482 row[3][0] += t[0]; 00483 row[3][1] += t[1]; 00484 row[3][2] += t[2]; 00485 #else 00486 row[0][3] += t[0]; 00487 row[1][3] += t[1]; 00488 row[2][3] += t[2]; 00489 #endif 00490 00491 return(SELF); 00492 }