00001 #include "mlib/mat4.H"
00002 #include "mlib/vec3.H"
00003 #include "mlib/global.H"
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 template <typename M, typename P, typename V, typename L, typename Q>
00030 MLIB_INLINE
00031 mlib::Mat4<M,P,V,L,Q>::Mat4(
00032    const P& origin, 
00033    const V& x_dir, 
00034    const V& y_dir, 
00035    const V& z_dir
00036    )
00037 {
00038    const V xx = x_dir.normalized();
00039    const V yy = y_dir.normalized();
00040    const V zz = z_dir.normalized();
00041 
00042    assert(!xx.is_null());
00043    assert(!yy.is_null());
00044    assert(!zz.is_null());
00045 
00046    Mat4<M,P,V,L,Q> t;
00047 
00048    for (int i = 0; i < 3; i++) {
00049       t(i,0) = xx    [i];
00050       t(i,1) = yy    [i];
00051       t(i,2) = zz    [i];
00052       t(i,3) = origin[i];
00053       t(3,i) = 0.0;
00054    }
00055    t(3,3) = 1.0;
00056 
00057    (*this) = t;
00058 } 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 template <typename M,typename P, typename V, typename L, typename Q>
00071 MLIB_INLINE
00072 mlib::Mat4<M,P,V,L,Q>::Mat4(const V& col0, const V& col1, const V& col2)
00073 {
00074    Mat4<M,P,V,L,Q> t;
00075 
00076    for (int i = 0; i < 3; i++) {
00077       t(i,0) = col0  [i];
00078       t(i,1) = col1  [i];
00079       t(i,2) = col2  [i];
00080       t(i,3) = t(3,i) = 0.0;
00081    }
00082    t(3,3) = 1.0;
00083 
00084    (*this) = t;
00085 } 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 template <typename M,typename P, typename V, typename L, typename Q>
00108 MLIB_INLINE
00109 mlib::Mat4<M,P,V,L,Q>::Mat4(const P& origin, const V& x_dir, const V& y_dir)
00110 {
00111    
00112 
00113    const V xx = x_dir.normalized();
00114    const V zz = cross(xx, y_dir).normalized();
00115 
00116    if (zz.is_null()) {
00117       *this = M();
00118       
00119       return;
00120    }
00121 
00122    const V yy = cross(zz, xx).normalized();
00123    *this = M(origin, xx, yy, zz);
00124 }
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 template <typename M,typename P, typename V, typename L, typename Q>
00138 MLIB_INLINE
00139 mlib::Mat4<M,P,V,L,Q>::Mat4(const L& axis)
00140 {
00141    
00142 
00143    const V zDir = axis.vector().normalized();
00144 
00145    if (zDir.is_null())
00146    {
00147        *this = M(axis.point(), V(1,0,0), V(0,1,0), V(0,0,1));
00148        
00149    } else {
00150       const V xDir = zDir.perpend();
00151       const V yDir = cross(zDir, xDir);
00152       *this = M(axis.point(), xDir, yDir, zDir);
00153    }
00154 }
00155 
00156 
00157 
00158 
00159 
00160 template <typename M,typename P, typename V, typename L, typename Q>
00161 MLIB_INLINE
00162 mlib::Mat4<M,P,V,L,Q>::Mat4(const P& origin) 
00163 {
00164    M t;
00165 
00166    t(0,3) = origin[0];
00167    t(1,3) = origin[1];
00168    t(2,3) = origin[2];
00169 
00170    (*this) = t;
00171 } 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 template <typename M,typename P, typename V, typename L, typename Q>
00180 MLIB_INLINE
00181 M 
00182 mlib::Mat4<M,P,V,L,Q>::translation(const V& vec)
00183 {
00184    M t;
00185 
00186    t(0,3) = vec[0]; 
00187    t(1,3) = vec[1];
00188    t(2,3) = vec[2];
00189 
00190    return t;
00191 }
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 template <typename M,typename P, typename V, typename L, typename Q>
00201 MLIB_INLINE
00202 M 
00203 mlib::Mat4<M,P,V,L,Q>::rotation(const V& axis, double angle)
00204 {
00205    return  rotation(L(P(), axis), angle); 
00206 }
00207 
00208 
00209 
00210 
00211 
00212 
00213 template <typename M,typename P, typename V, typename L, typename Q>
00214 MLIB_INLINE
00215 M
00216 mlib::Mat4<M,P,V,L,Q>::rotation(const L& axis, double angle)
00217 {
00218    const V      v  = axis.vector().normalized();
00219    const P      p  = axis.point();
00220    const double sa = sin(angle);
00221    const double ca = cos(angle);
00222 
00223    M t;
00224 
00225    t(0,0) = v[0]*v[0]  + ca*(1.0-v[0]*v[0]);
00226    t(0,1) = v[0]*v[1]*(1.0-ca) - v[2]*sa;
00227    t(0,2) = v[2]*v[0]*(1.0-ca) + v[1]*sa;
00228 
00229    t(1,0) = v[0]*v[1]*(1.0-ca) + v[2]*sa;
00230    t(1,1) = v[1]*v[1] + ca*(1.0-v[1]*v[1]);
00231    t(1,2) = v[1]*v[2]*(1.0-ca) - v[0]*sa;
00232 
00233    t(2,0) = v[0]*v[2]*(1.0-ca) - v[1]*sa;
00234    t(2,1) = v[1]*v[2]*(1.0-ca) + v[0]*sa;
00235    t(2,2) = v[2]*v[2] + ca*(1.0-v[2]*v[2]);
00236 
00237    t(0,3) = p[0] - (t(0,0)*p[0] + t(0,1)*p[1] + t(0,2)*p[2]);
00238    t(1,3) = p[1] - (t(1,0)*p[0] + t(1,1)*p[1] + t(1,2)*p[2]);
00239    t(2,3) = p[2] - (t(2,0)*p[0] + t(2,1)*p[1] + t(2,2)*p[2]);
00240 
00241    t(3,0) = t(3,1) = t(3,2) = 0;
00242    t(3,3) = 1.0;
00243 
00244    return t;
00245 } 
00246 
00247 
00248 
00249 
00250 
00251 
00252 template <typename M,typename P, typename V, typename L, typename Q>
00253 MLIB_INLINE
00254 M 
00255 mlib::Mat4<M,P,V,L,Q>::rotation(const Q& quat)
00256 {
00257    double angle = 2.0 * Acos(quat.w());
00258    const V axis = (angle != 0.0) ? quat.v()/sin(angle/2.0) : V(0,1,0);
00259    return rotation(axis, angle);
00260 }
00261 
00262 
00263 
00264 
00265 
00266 
00267 template <typename M,typename P, typename V, typename L, typename Q>
00268 MLIB_INLINE
00269 M 
00270 mlib::Mat4<M,P,V,L,Q>::scaling(const P& fixed_pt, double factor)
00271 {
00272    return scaling(fixed_pt, V(factor, factor, factor));
00273 }
00274 
00275 
00276 
00277 
00278  
00279 template <typename M,typename P, typename V, typename L, typename Q>
00280 MLIB_INLINE
00281 M 
00282 mlib::Mat4<M,P,V,L,Q>::scaling(double factor)
00283 {
00284    return scaling(P(), V(factor, factor, factor));
00285 }
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 template <typename M,typename P, typename V, typename L, typename Q>
00294 MLIB_INLINE
00295 M
00296 mlib::Mat4<M,P,V,L,Q>::scaling(const V& xyz_factors)
00297 {
00298    return scaling(P(), xyz_factors);
00299 } 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 template <typename M,typename P, typename V, typename L, typename Q>
00308 MLIB_INLINE
00309 M 
00310 mlib::Mat4<M,P,V,L,Q>::scaling(const P& fixed_pt, const V& xyz_factors)
00311 {
00312    M t;
00313 
00314    t(0,0) = xyz_factors[0];
00315    t(1,1) = xyz_factors[1];
00316    t(2,2) = xyz_factors[2];
00317 
00318    t(0,3) = fixed_pt[0] * (1.0-xyz_factors[0]);
00319    t(1,3) = fixed_pt[1] * (1.0-xyz_factors[1]);
00320    t(2,3) = fixed_pt[2] * (1.0-xyz_factors[2]);
00321 
00322    return t;
00323 } 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 template <typename M,typename P, typename V, typename L, typename Q>
00337 MLIB_INLINE
00338 M 
00339 mlib::Mat4<M,P,V,L,Q>::shear(const V& normal, const V& shear_vec)
00340 {
00341    M t;
00342 
00343    V      realShear = shear_vec;
00344    double dot       = normal * shear_vec;
00345 
00346    
00347    if (fabs(dot) > epsAbsSqrdMath()) 
00348       realShear = shear_vec - normal * dot;
00349 
00350    
00351    for (int j = 0; j < 3; j++) { 
00352       t(j, 0) += normal[0] * realShear[j];
00353       t(j, 1) += normal[1] * realShear[j];
00354       t(j, 2) += normal[2] * realShear[j];
00355    }
00356 
00357    return t;
00358 }
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 template <typename M,typename P, typename V, typename L, typename Q>
00369 MLIB_INLINE
00370 M 
00371 mlib::Mat4<M,P,V,L,Q>::stretching(const L& axis)
00372 {
00373    const M t    = M(axis);
00374    const M invt = t.inverse();
00375 
00376    P q = invt * axis.point();  
00377    M mat = scaling(q, V(1,1,axis.vector().length()));
00378 
00379    return t * mat * invt;
00380 }
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402  
00403 template <typename M,typename P, typename V, typename L, typename Q>
00404 MLIB_INLINE
00405 M 
00406 mlib::Mat4<M,P,V,L,Q>::anchor_scale_rot(
00407    const P& anchor,
00408    const P& old_pt,
00409    const P& new_pt)
00410 {                                                
00411 
00412    V   old_vec = (old_pt - anchor).normalized();
00413    V   new_vec = (new_pt - anchor).normalized();
00414    double old_len = anchor.dist(old_pt);
00415    double new_len = anchor.dist(new_pt);
00416 
00417    
00418    if (old_len < gEpsAbsMath) {
00419       err_msg("Mat4::anchor_scale_rot: Original segment too short");
00420       return M();
00421    }
00422 
00423    
00424    
00425    M z2old = M(L(anchor, old_vec));     
00426    M ret = (
00427       z2old *                                   
00428       M::scaling(V(1,1,new_len/old_len)) *      
00429       z2old.inverse()                        
00430       );
00431 
00432    
00433    V n = cross(new_vec, old_vec).normalized();
00434    if (n.is_null())
00435       return ret;       
00436 
00437    return M::rotation(L(anchor,n), -Acos(new_vec*old_vec)) * ret;
00438 }
00439 
00440 
00441 template <typename M, typename P, typename V, typename L, typename Q>
00442 MLIB_INLINE
00443 M 
00444 mlib::operator*(const Mat4<M,P,V,L,Q> &m, const Mat4<M,P,V,L,Q>& m2)
00445 {
00446    M        t;
00447 
00448    t(0,0) = m(0,0) * m2(0,0) +
00449             m(0,1) * m2(1,0) +
00450             m(0,2) * m2(2,0) +
00451             m(0,3) * m2(3,0) ;
00452 
00453    t(0,1) = m(0,0) * m2(0,1) +
00454             m(0,1) * m2(1,1) +
00455             m(0,2) * m2(2,1) +
00456             m(0,3) * m2(3,1) ;
00457 
00458    t(0,2) = m(0,0) * m2(0,2) +
00459             m(0,1) * m2(1,2) +
00460             m(0,2) * m2(2,2) +
00461             m(0,3) * m2(3,2) ;
00462 
00463    t(0,3) = m(0,0) * m2(0,3) +
00464             m(0,1) * m2(1,3) +
00465             m(0,2) * m2(2,3) +
00466             m(0,3) * m2(3,3) ;
00467 
00468    t(1,0) = m(1,0) * m2(0,0) +
00469             m(1,1) * m2(1,0) +
00470             m(1,2) * m2(2,0) +
00471             m(1,3) * m2(3,0) ;
00472 
00473    t(1,1) = m(1,0) * m2(0,1) +
00474             m(1,1) * m2(1,1) +
00475             m(1,2) * m2(2,1) +
00476             m(1,3) * m2(3,1) ;
00477 
00478    t(1,2) = m(1,0) * m2(0,2) +
00479             m(1,1) * m2(1,2) +
00480             m(1,2) * m2(2,2) +
00481             m(1,3) * m2(3,2) ;
00482 
00483    t(1,3) = m(1,0) * m2(0,3) +
00484             m(1,1) * m2(1,3) +
00485             m(1,2) * m2(2,3) +
00486             m(1,3) * m2(3,3) ;
00487 
00488    t(2,0) = m(2,0) * m2(0,0) +
00489             m(2,1) * m2(1,0) +
00490             m(2,2) * m2(2,0) +
00491             m(2,3) * m2(3,0) ;
00492 
00493    t(2,1) = m(2,0) * m2(0,1) +
00494             m(2,1) * m2(1,1) +
00495             m(2,2) * m2(2,1) +
00496             m(2,3) * m2(3,1) ;
00497 
00498    t(2,2) = m(2,0) * m2(0,2) +
00499             m(2,1) * m2(1,2) +
00500             m(2,2) * m2(2,2) +
00501             m(2,3) * m2(3,2) ;
00502 
00503    t(2,3) = m(2,0) * m2(0,3) +
00504             m(2,1) * m2(1,3) +
00505             m(2,2) * m2(2,3) +
00506             m(2,3) * m2(3,3) ;
00507 
00508    t(3,0) = m(3,0) * m2(0,0) +
00509             m(3,1) * m2(1,0) +
00510             m(3,2) * m2(2,0) +
00511             m(3,3) * m2(3,0) ;
00512 
00513    t(3,1) = m(3,0) * m2(0,1) +
00514             m(3,1) * m2(1,1) +
00515             m(3,2) * m2(2,1) +
00516             m(3,3) * m2(3,1) ;
00517 
00518    t(3,2) = m(3,0) * m2(0,2) +
00519             m(3,1) * m2(1,2) +
00520             m(3,2) * m2(2,2) +
00521             m(3,3) * m2(3,2) ;
00522 
00523    t(3,3) = m(3,0) * m2(0,3) +
00524             m(3,1) * m2(1,3) +
00525             m(3,2) * m2(2,3) +
00526             m(3,3) * m2(3,3) ;
00527 
00528    t.set_perspective(m.is_perspective() || m2.is_perspective());
00529 
00530    return t;
00531 
00532 } 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 template <typename M,typename P, typename V, typename L, typename Q>
00543 MLIB_INLINE
00544 M
00545 mlib::Mat4<M,P,V,L,Q>::inverse(bool debug) const
00546 {
00547    
00548    M ret;
00549    double det = inverse(ret); 
00550    if (debug && isZero(det)) {
00551       
00552       cerr << "Mat4::inverse: error: singular matrix" << endl;
00553       
00554       
00555       
00556       
00557       fn_gdb_will_recognize_so_i_can_set_a_fuggin_breakpoint();
00558    }
00559    return ret;
00560 }
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 template <typename M,typename P, typename V, typename L, typename Q>
00579 MLIB_INLINE
00580 double
00581 mlib::Mat4<M,P,V,L,Q>::inverse(Mat4<M,P,V,L,Q> &inv) const
00582 {
00583    Mat4<M,P,V,L,Q> A = *this;
00584    int i, j, k;
00585    double maxval, t, detr, pivot;
00586 
00587    
00588 
00589    for (i=0; i<4; i++)                
00590       for (j=0; j<4; j++)
00591          inv(i, j) = (double)(i==j);
00592 
00593    detr = 1.0;
00594    for (i=0; i<4; i++) {              
00595       maxval = -1.;
00596       for (k=i; k<4; k++)             
00597          if (fabs(A(k, i)) > maxval) {
00598             maxval = fabs(A(k, i));
00599             j = k;
00600          }
00601       if (maxval<=0.) return 0.;      
00602       if (j!=i) {                     
00603          for (k=i; k<4; k++)
00604             { t = A(i,k); A(i,k) = A(j,k); A(j,k) = t; }
00605          for (k=0; k<4; k++)
00606             { t = inv(i,k); inv(i,k) = inv(j,k); inv(j,k) = t; }
00607          detr = -detr;
00608       }
00609       pivot = A(i, i);
00610       detr *= pivot;
00611       for (k=i+1; k<4; k++)           
00612          A(i, k) /= pivot;
00613       for (k=0; k<4; k++)
00614          inv(i, k) /= pivot;
00615       
00616 
00617       for (j=i+1; j<4; j++) {         
00618          t = A(j, i);                 
00619          for (k=i+1; k<4; k++)        
00620             A(j, k) -= A(i, k)*t;     
00621          for (k=0; k<4; k++)
00622             inv(j, k) -= inv(i, k)*t;
00623       }
00624    }
00625 
00626    
00627 
00628    for (i=4-1; i>0; i--) {            
00629       for (j=0; j<i; j++) {           
00630          t = A(j, i);                 
00631          for (k=0; k<4; k++)          
00632              inv(j, k) -= inv(i, k)*t;
00633       }
00634    }
00635 
00636    inv.perspective = perspective;
00637    
00638    return detr;
00639 
00640 }
00641 
00642 
00643 
00644 
00645 
00646 
00647 
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 template <typename M,typename P, typename V, typename L, typename Q>
00657 MLIB_INLINE
00658 M 
00659 mlib::Mat4<M,P,V,L,Q>::derivative(const P& p) const
00660 {
00661    const M &t = (const M&)(*this);
00662    
00663    if (!perspective)
00664       return t;
00665 
00666    double h = t(3,0)*p[0] + t(3,1)*p[1] + t(3,2)*p[2] + t(3,3);
00667    if (fabs(h) < 1e-6) {
00668       cerr << "Mat4::derivative: bad homogeneous coordinate" << endl;
00669       return t;
00670    }
00671    P q = t * p;
00672    V px(q[0], q[1], q[2]);
00673 
00674    return M(
00675       (t.X() - t(3,0)*px)/h,
00676       (t.Y() - t(3,1)*px)/h,
00677       (t.Z() - t(3,2)*px)/h
00678       );
00679 }
00680 
00681 template <typename M,typename P, typename V, typename L, typename Q>
00682 MLIB_INLINE
00683 M
00684 mlib::Mat4<M,P,V,L,Q>::unscaled() const
00685 {
00686    P o;
00687    V x,y,z;
00688    get_coord_system(o,x,y,z);
00689 
00690    return M(o,x,y,z);
00691 }
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 template <typename M,typename P, typename V, typename L, typename Q>
00700 MLIB_INLINE
00701 M
00702 mlib::Mat4<M,P,V,L,Q>::normalized_basis() const
00703 {
00704    P o;
00705    V x,y,z;
00706    get_coord_system(o,x,y,z);
00707 
00708    return M(P(),x,y,z);
00709 }
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 template <typename M,typename P, typename V, typename L, typename Q>
00722 MLIB_INLINE
00723 M
00724 mlib::Mat4<M,P,V,L,Q>::orthogonalized() const
00725 {
00726    P o;
00727    V x,y,z;
00728    get_coord_system(o,x,y,z);
00729 
00730    V xn(x.normalized());
00731    y = (y - (xn * (xn*y))).normalized() * y.length();
00732    V yn(y.normalized());
00733    z = cross(xn,yn).normalized() * z.length();
00734 
00735    return align_and_scale(o,x,y,z);
00736 }
00737 
00738 template <typename M, typename P, typename V, typename L, typename Q>
00739 MLIB_INLINE
00740 P
00741 mlib::operator*(const Mat4<M,P,V,L,Q> &m, const P& p)
00742 {  
00743    Vec4 p4(p, 1.0);
00744    if (m.is_perspective()) {
00745       double hcoord = m(3,0)*p[0] + m(3,1)*p[1]
00746                     + m(3,2)*p[2] + m(3,3);
00747       if (hcoord != 0.0) {
00748          hcoord = 1.0/hcoord;
00749       } else {
00750          cerr << "Bad homogeneous coordinate - divide by zero" << endl;
00751          
00752       }
00753       
00754       
00755       
00756       
00757       return P(m[0] * p4 * hcoord, m[1] * p4 * hcoord, m[2] * p4 * hcoord);
00758    } else {
00759       return P(m[0] * p4, m[1] * p4, m[2] * p4);
00760    }
00761 }
00762 
00763 
00764 template <typename M, typename P, typename V, typename L, typename Q>
00765 MLIB_INLINE
00766 V
00767 mlib::operator*(const Mat4<M,P,V,L,Q> &m, const Vec3<V>& v)
00768 {     
00769    Vec4 v4(v, 0.0);
00770    return V(m[0] * v4, m[1] * v4, m[2] * v4);
00771 }
00772 
00773 
00774 template <typename M, typename P, typename V, typename L, typename Q>
00775 MLIB_INLINE
00776 L
00777 mlib::operator*(const Mat4<M,P,V,L,Q> &m, const Line<L,P,V>& l)
00778 {
00779    return L(m * l.point(), m * l.vector());
00780 }
00781 
00782 
00783 template <typename M, typename P, typename V, typename L, typename Q>
00784 MLIB_INLINE
00785 bool
00786 mlib::Mat4<M,P,V,L,Q>::is_identity() const
00787 {
00788    static const double EPS = gEpsAbsMath*1e2;
00789    return fabs(row[0][0]-1)<EPS && fabs(row[1][1]-1)<EPS && fabs(row[2][2]-1)<EPS&&
00790           fabs(row[3][3]-1)<EPS && fabs(row[0][1])<EPS && fabs(row[0][2])<EPS &&
00791           fabs(row[0][3])<EPS && fabs(row[1][0])<EPS && fabs(row[1][2])<EPS &&
00792           fabs(row[1][3])<EPS && fabs(row[2][0])<EPS && fabs(row[2][1])<EPS &&
00793           fabs(row[2][3])<EPS && fabs(row[3][0])<EPS && fabs(row[3][1])<EPS &&
00794           (row[3][2]==0);
00795 }
00796 
00797 
00798 template <typename M,typename P, typename V, typename L, typename Q>
00799 MLIB_INLINE
00800 bool 
00801 mlib::Mat4<M,P,V,L,Q>::is_orthogonal() const
00802 {
00803    P  origin;
00804    V x;
00805    V y;
00806    V z;
00807 
00808    get_coord_system(origin, x, y, z);
00809 
00810    return x.is_perpend(y) && y.is_perpend(z) && z.is_perpend(x);
00811 }
00812 
00813 template <typename M,typename P, typename V, typename L, typename Q>
00814 MLIB_INLINE
00815 bool 
00816 mlib::Mat4<M,P,V,L,Q>::is_equal_scaling_orthogonal() const
00817 {
00818    if (!is_orthogonal())
00819       return false;
00820 
00821    V s = get_scale();
00822 
00823    return fabs(s[0]/s[1] - 1) < epsNorMath() && 
00824           fabs(s[1]/s[2] - 1) < epsNorMath() &&
00825           fabs(s[2]/s[0] - 1) < epsNorMath();
00826 }
00827 
00828 
00829 template <typename M,typename P, typename V, typename L, typename Q>
00830 MLIB_INLINE
00831 M 
00832 mlib::Mat4<M,P,V,L,Q>::transpose() const
00833 {
00834    M  ret;
00835 
00836    for (int i = 0; i < 4; i++)
00837       for (int j = 0; j < 4; j++)
00838          ret(i,j) = row[j][i];
00839 
00840    return ret;
00841 }
00842 
00843 
00844 
00845 
00846 
00847 
00848 template <typename M,typename P, typename V, typename L, typename Q>
00849 MLIB_INLINE
00850 M
00851 mlib::Mat4<M,P,V,L,Q>::adjoint() const
00852 {
00853     M A;
00854 
00855     A[0] = -cross( row[1], row[2], row[3]);
00856     A[1] = -cross(-row[0], row[2], row[3]);
00857     A[2] = -cross( row[0], row[1], row[3]);
00858     A[3] = -cross(-row[0], row[1], row[2]);
00859         
00860     return A;
00861 }
00862 
00863 
00864 
00865 
00866 
00867 
00868 
00869 
00870 
00871 template <typename M,typename P, typename V, typename L, typename Q>
00872 MLIB_INLINE
00873 M 
00874 mlib::Mat4<M,P,V,L,Q>::align(
00875    const P&  src1,
00876    const V&  src2,
00877    const P&  dst1,
00878    const V&  dst2
00879    )
00880 {
00881    V planeNormal = cross(src2, dst2);
00882 
00883    if (planeNormal.is_null()) {
00884       if (src2 * dst2 < 0) {
00885          planeNormal = src2.perpend();
00886       } else {
00887          return translation(dst1 - src1);
00888       }
00889    }
00890 
00891    return align(src1, src2, planeNormal, dst1, dst2, planeNormal);
00892 }
00893 
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 
00902 
00903 
00904 
00905 
00906 template <typename M,typename P, typename V, typename L, typename Q>
00907 MLIB_INLINE
00908 M 
00909 mlib::Mat4<M,P,V,L,Q>::align(
00910    const P& src1,
00911    const V& src2,
00912    const V& src3,
00913    const P& dst1,
00914    const V& dst2,
00915    const V& dst3
00916    )
00917 {
00918     
00919 
00920    const M t1 = M(src1, src2, src3);
00921 
00922 
00923 
00924    const M t2 = M(dst1, dst2, dst3);
00925 
00926 
00927 
00928    return t2 * t1.inverse();
00929 }
00930 
00931 
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939 template <typename M,typename P, typename V, typename L, typename Q>
00940 MLIB_INLINE
00941 M 
00942 mlib::Mat4<M,P,V,L,Q>::align(
00943    const P& src1,
00944    const P& src2,
00945    const P& src3,
00946    const P& dst1,
00947    const P& dst2,
00948    const P& dst3
00949    )
00950 {
00951    return align(src1, src2-src1, src3-src1, dst1, dst2-dst1, dst3-dst1);
00952 }
00953 
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 template <typename M,typename P, typename V, typename L, typename Q>
00962 MLIB_INLINE
00963 M
00964 mlib::Mat4<M,P,V,L,Q>::align_and_scale(
00965    const P& origin,
00966    const V& xx,
00967    const V& yy,
00968    const V& zz
00969    )
00970 {
00971    assert(!xx.is_null());
00972    assert(!yy.is_null());
00973    assert(!zz.is_null());
00974 
00975    M t;
00976 
00977    for (int i = 0; i < 3; i++)       {
00978       t(i,0) = xx    [i];
00979       t(i,1) = yy    [i];
00980       t(i,2) = zz    [i];
00981       t(i,3) = origin[i];
00982       t(3,i) = 0.0;
00983    }
00984    t(3,3) = 1.0;
00985 
00986    return t;
00987 }
00988 
00989 
00990 
00991 
00992 
00993 
00994 template <typename M,typename P, typename V, typename L, typename Q>
00995 MLIB_INLINE
00996 M
00997 mlib::Mat4<M,P,V,L,Q>::glu_perspective(double fovy, double aspect, 
00998                                        double zmin, double zmax)
00999 {
01000    double A, B;
01001    M t;
01002    
01003    if( zmax==0.0 ){
01004       A = B = 1.0;
01005    } else {
01006       A = (zmax+zmin)/(zmin-zmax);
01007       B = (2*zmax*zmin)/(zmin-zmax);
01008    }
01009    
01010    double f = 1.0/tan(fovy*M_PI/180.0/2.0);
01011    t(0,0) = f/aspect;
01012    t(1,1) = f;
01013    t(2,2) = A;
01014    t(2,3) = B;
01015    t(3,2) = -1;
01016    t(3,3) = 0;
01017    
01018    t.perspective = true;
01019    
01020    return t;
01021 }
01022 
01023 
01024 
01025 
01026 
01027 
01028 template <typename M,typename P, typename V, typename L, typename Q>
01029 MLIB_INLINE
01030 M
01031 mlib::Mat4<M,P,V,L,Q>::glu_lookat(const V& from, const V& at, const V& v_up)
01032 {
01033     V up = v_up.normalized();
01034     V f = (at - from).normalized();
01035 
01036     
01037     V s = cross(f, up).normalized();
01038     V u = cross(s, f).normalized();
01039 
01040     M t(Vec4(s, 0), Vec4(u, 0), Vec4(-f, 0), Vec4(0, 0, 0, 1));
01041 
01042     return t * translation(-from);
01043 }
01044 
01045 
01046 
01047 
01048 
01049 
01050 template <typename M,typename P, typename V, typename L, typename Q>
01051 MLIB_INLINE
01052 M
01053 mlib::Mat4<M,P,V,L,Q>::gl_viewport(double w, double h)
01054 {
01055     return scaling(V(w/2.0, -h/2.0, 1)) * translation(V(1, -1, 0));
01056 }
01057 
01058 template <typename M,typename P, typename V, typename L, typename Q>
01059 MLIB_INLINE
01060 bool 
01061 mlib::Mat4<M,P,V,L,Q>::is_valid() const
01062 {
01063    const V x = V(row[0][0], row[1][0], row[2][0]).normalized();
01064    const V y = V(row[0][1], row[1][1], row[2][1]).normalized();
01065    const V z = V(row[0][2], row[1][2], row[2][2]).normalized();
01066 
01067    return (fabs(mlib::det(x, y, z)) > epsNorMath());
01068 }
01069 
01070 
01071 
01072 
01073 template <typename M,typename P, typename V, typename L, typename Q>
01074 MLIB_INLINE
01075 ostream &
01076 mlib::operator << (ostream &os, const Mat4<M,P,V,L,Q> &x) 
01077 {
01078    os<<"["<<
01079        "["<<x(0,0)<<","<<x(0,1)<<","<<x(0,2)<<","<<x(0,3)<<"]"<<endl<<
01080        "["<<x(1,0)<<","<<x(1,1)<<","<<x(1,2)<<","<<x(1,3)<<"]"<<endl<<
01081        "["<<x(2,0)<<","<<x(2,1)<<","<<x(2,2)<<","<<x(2,3)<<"]"<<endl<<
01082        "["<<x(3,0)<<","<<x(3,1)<<","<<x(3,2)<<","<<x(3,3)<<"]"<<endl<<
01083        "]"<<endl;
01084    return os; 
01085 }