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 }