00001 #ifndef MAT4_H_IS_INCLUDED
00002 #define MAT4_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010 #include "mlib/vec4.H"
00011 #include "mlib/point3.H"
00012 #include "mlib/line.H"
00013
00014 namespace mlib {
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 class Mat4 {
00031
00032 protected:
00033
00034 Vec4 row[4];
00035 bool perspective;
00036
00037 public:
00038
00039
00040
00041
00042
00043 inline Mat4()
00044 : perspective(false)
00045 {
00046 row[0] = row[1] = row[2] = row[3] = Vec4(0.0, 0.0, 0.0, 0.0);
00047 row[0][0] = row[1][1] = row[2][2] = row[3][3] = 1.0;
00048 }
00049
00050
00051
00052 inline Mat4(Vec4 row0, Vec4 row1, Vec4 row2, Vec4 row3, bool perspec = false)
00053 : perspective(perspec)
00054 { row[0] = row0; row[1] = row1; row[2] = row2; row[3] = row3; }
00055
00056
00057
00058 Mat4(const P &origin, const V &x_dir, const V &y_dir, const V &z_dir);
00059
00060
00061
00062 Mat4(const V &col0, const V &col1, const V &col2);
00063
00064
00065
00066
00067 Mat4(const P &origin, const V &xDir, const V &yDir);
00068
00069
00070
00071
00072
00073 Mat4(const L& axis);
00074
00075
00076
00077 Mat4(const P& origin);
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 double& operator ()(int i1, int i2) { return row[i1][i2]; }
00089
00090
00091 double operator ()(int i1, int i2) const { return row[i1][i2]; }
00092
00093
00094
00095 Vec4& operator [](int i) { return row[i]; }
00096
00097
00098 Vec4 operator [](int i) const { return row[i]; }
00099
00100
00101
00102 V get_scale() const
00103 { return V(X().length(),Y().length(),Z().length()); }
00104
00105
00106
00107 void get_coord_system(P& o, V& x, V& y, V& z) const
00108 { x = X(); y = Y(); z = Z(); o = origin(); }
00109
00110
00111
00112 V X() const { return V(row[0][0], row[1][0], row[2][0]); }
00113
00114
00115 V Y() const { return V(row[0][1], row[1][1], row[2][1]); }
00116
00117
00118 V Z() const { return V(row[0][2], row[1][2], row[2][2]); }
00119
00120
00121 P origin() const { return P(row[0][3], row[1][3], row[2][3]); }
00122
00123
00124
00125
00126
00127 const double *matrix() const { return row[0]; }
00128
00129
00130 void set_X(const V& x)
00131 { row[0][0] = x[0]; row[1][0] = x[1]; row[2][0] = x[2]; }
00132
00133 void set_Y(const V& y)
00134 { row[0][1] = y[0]; row[1][1] = y[1]; row[2][1] = y[2]; }
00135
00136 void set_Z(const V& z)
00137 { row[0][2] = z[0]; row[1][2] = z[1]; row[2][2] = z[2]; }
00138
00139 void set_origin(const P& o)
00140 { row[0][3] = o[0]; row[1][3] = o[1]; row[2][3] = o[2]; }
00141
00142
00143 M rotation() const { return M(P(0,0,0), X(), Y(), Z()); }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static M rotation (const Q& quat);
00155
00156
00157 static M rotation (const L& axis, double angle);
00158
00159
00160 static M rotation (const V& axis, double angle);
00161
00162
00163 static M shear (const V& normal, const V& shear_vec);
00164
00165
00166
00167 static M scaling (const P& fixed_pt, double factor);
00168
00169
00170
00171 static M scaling (const P& fixed_pt, const V& xyz_factors);
00172
00173
00174 static M scaling (const V& xyz_factors);
00175
00176
00177 static M scaling (double x, double y, double z)
00178 { return scaling(V(x,y,z)); }
00179
00180 static M scaling (double factor);
00181
00182
00183
00184 static M stretching (const L& axis);
00185
00186
00187 static M translation(const V& vec);
00188
00189
00190
00191
00192 static M anchor_scale_rot(const P& anchor,
00193 const P& old_pt,
00194 const P& new_pt);
00195
00196
00197
00198
00199
00200 static M align(const P& src1, const P& src2, const P& src3,
00201 const P& dst1, const P& dst2, const P& dst3);
00202
00203 static M align(const P& src1, const V& src2, const V& src3,
00204 const P& dst1, const V& dst2, const V& dst3);
00205
00206 static M align(const P& src1, const V& src2,
00207 const P& dst1, const V& dst2);
00208
00209 static M align_and_scale(const P& o, const V& x, const V& y, const V& z);
00210
00211
00212
00213 static M glu_perspective(double fovy, double aspect,
00214 double zmin=0.0, double zmax=0.0);
00215
00216
00217
00218 static M glu_lookat(const V& from, const V& at, const V& up);
00219
00220
00221
00222 static M gl_viewport(double w, double h);
00223
00224
00225
00226
00227
00228
00229
00230 M transpose () const;
00231
00232
00233
00234 double det () const
00235 { return row[0] * -cross(row[1], row[2], row[3]); }
00236
00237
00238
00239 double trace () const
00240 { return (*this)(0,0)+(*this)(1,1)+(*this)(2,2)+(*this)(3,3); }
00241
00242 M adjoint () const;
00243
00244
00245 M unscaled () const;
00246
00247 M normalized_basis() const;
00248
00249 M orthogonalized () const;
00250
00251
00252 M inverse(bool debug = false) const;
00253 double inverse(Mat4<M,P,V,L,Q> &inv) const;
00254
00255 M derivative(const P& p) const;
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 void set_perspective(bool p) { perspective = p; }
00266
00267 bool is_perspective() const { return perspective;}
00268
00269
00270 bool is_valid () const;
00271
00272 bool is_identity () const;
00273
00274 bool is_orthogonal () const;
00275
00276
00277 bool is_equal_scaling_orthogonal() const;
00278
00279 bool is_orthonormal() const
00280 { return (is_orthogonal() && get_scale().is_equal(V(1,1,1))); }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 int operator == (const M &m) const
00291 { return origin() == m.origin() &&
00292 X() == m.X() && Y() == m.Y() && Z() == m.Z(); }
00293
00294
00295
00296 };
00297
00298 }
00299
00300 namespace mlib {
00301
00302
00303
00304 template <typename M, typename P, typename V, typename L, typename Q>
00305 M operator*(const Mat4<M,P,V,L,Q> &m, const Mat4<M,P,V,L,Q> &m2);
00306
00307
00308
00309 template <typename M, typename P, typename V, typename L, typename Q>
00310 P operator*(const Mat4<M,P,V,L,Q> &m, const P &p);
00311
00312
00313
00314 template <typename M, typename P, typename V, typename L, typename Q>
00315 V operator*(const Mat4<M,P,V,L,Q> &m, const Vec3<V> &v);
00316
00317
00318
00319 template <typename M, typename P, typename V, typename L, typename Q>
00320 L operator*(const Mat4<M,P,V,L,Q> &m, const Line<L,P,V> &l);
00321
00322
00323
00324 template <typename M, typename P, typename V, typename L, typename Q>
00325 inline M operator+(const Mat4<M,P,V,L,Q>& n, const Mat4<M,P,V,L,Q>& m)
00326 { return M(n[0]+m[0], n[1]+m[1], n[2]+m[2], n[3]+m[3],
00327 n.is_perspective() || m.is_perspective()); }
00328
00329
00330
00331 template <typename M, typename P, typename V, typename L, typename Q>
00332 inline M operator-(const Mat4<M,P,V,L,Q>& n, const Mat4<M,P,V,L,Q>& m)
00333 { return M(n[0]-m[0], n[1]-m[1], n[2]-m[2], n[3]-m[3],
00334 n.is_perspective() || m.is_perspective()); }
00335
00336
00337
00338 template <typename M, typename P, typename V, typename L, typename Q>
00339 inline M operator-(const Mat4<M,P,V,L,Q>& n)
00340 { return M(-n[0], -n[1], -n[2], -n[3], n.is_perspective()); }
00341
00342
00343
00344 template <typename M, typename P, typename V, typename L, typename Q>
00345 inline M operator*(double s, const Mat4<M,P,V,L,Q>& m)
00346 { return M(m[0]*s, m[1]*s, m[2]*s, m[3]*s, m.is_perspective()); }
00347
00348
00349
00350 template <typename M, typename P, typename V, typename L, typename Q>
00351 inline M operator*(const Mat4<M,P,V,L,Q>& m, double s)
00352 { return s*m; }
00353
00354
00355
00356 template <typename M, typename P, typename V, typename L, typename Q>
00357 inline M operator/(const Mat4<M,P,V,L,Q>& m, double s)
00358 { return M(m[0]/s, m[1]/s, m[2]/s, m[3]/s, m.is_perspective()); }
00359
00360
00361
00362 template <typename M,typename P,typename V, typename L, typename Q>
00363 std::ostream &operator <<(std::ostream &os, const Mat4<M,P,V,L,Q> &x);
00364
00365 }
00366
00367 #ifdef JOT_NEEDS_TEMPLATES_IN_H_FILE
00368 #include "mat4.C"
00369 #endif
00370
00371 #endif // MAT4_H_IS_INCLUDED