00001
00002
00003
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
00030
00031
00032 #ifndef Matrix4_INCLUDE_ONCE
00033 #define Matrix4_INCLUDE_ONCE
00034
00035 #include <vlCore/Vector4.hpp>
00036 #include <vlCore/Matrix3.hpp>
00037
00038 namespace vl
00039 {
00040
00041
00042
00047 template<typename T_Scalar>
00048 class Matrix4
00049 {
00050 public:
00051 typedef T_Scalar scalar_type;
00052
00053 template<typename T>
00054 explicit Matrix4(const Matrix4<T>& m)
00055 {
00056 e(0,0) = (T_Scalar)m.e(0,0); e(1,0) = (T_Scalar)m.e(1,0); e(2,0) = (T_Scalar)m.e(2,0); e(3,0) = (T_Scalar)m.e(3,0);
00057 e(0,1) = (T_Scalar)m.e(0,1); e(1,1) = (T_Scalar)m.e(1,1); e(2,1) = (T_Scalar)m.e(2,1); e(3,1) = (T_Scalar)m.e(3,1);
00058 e(0,2) = (T_Scalar)m.e(0,2); e(1,2) = (T_Scalar)m.e(1,2); e(2,2) = (T_Scalar)m.e(2,2); e(3,2) = (T_Scalar)m.e(3,2);
00059 e(0,3) = (T_Scalar)m.e(0,3); e(1,3) = (T_Scalar)m.e(1,3); e(2,3) = (T_Scalar)m.e(2,3); e(3,3) = (T_Scalar)m.e(3,3);
00060 }
00061
00062 Matrix4()
00063 {
00064 setIdentity();
00065 }
00066
00067 explicit Matrix4(T_Scalar n)
00068 {
00069 setIdentity();
00070 e(0,0) = e(1,1) = e(2,2) = e(3,3) = n;
00071 }
00072
00073 explicit Matrix4( T_Scalar e00, T_Scalar e01, T_Scalar e02, T_Scalar e03,
00074 T_Scalar e10, T_Scalar e11, T_Scalar e12, T_Scalar e13,
00075 T_Scalar e20, T_Scalar e21, T_Scalar e22, T_Scalar e23,
00076 T_Scalar e30, T_Scalar e31, T_Scalar e32, T_Scalar e33)
00077 {
00078 e(0,0) = e00; e(0,1) = e01; e(0,2) = e02; e(0,3) = e03;
00079 e(1,0) = e10; e(1,1) = e11; e(1,2) = e12; e(1,3) = e13;
00080 e(2,0) = e20; e(2,1) = e21; e(2,2) = e22; e(2,3) = e23;
00081 e(3,0) = e30; e(3,1) = e31; e(3,2) = e32; e(3,3) = e33;
00082 }
00083
00084 Matrix4& fill(T_Scalar val)
00085 {
00086 e(0,0) = e(1,0) = e(2,0) = e(3,0) =
00087 e(0,1) = e(1,1) = e(2,1) = e(3,1) =
00088 e(0,2) = e(1,2) = e(2,2) = e(3,2) =
00089 e(0,3) = e(1,3) = e(2,3) = e(3,3) = val;
00090 return *this;
00091 }
00092
00093 T_Scalar diff(const Matrix4& other) const
00094 {
00095 T_Scalar err = 0;
00096 for(int i=0; i<4; ++i)
00097 for(int j=0; j<4; ++j)
00098 if (e(j,i) > other.e(j,i))
00099 err += e(j,i) - other.e(j,i);
00100 else
00101 err += other.e(j,i) - e(j,i);
00102 return err;
00103 }
00104
00105 Vector3<T_Scalar> getX() const
00106 {
00107 return Vector3<T_Scalar>(mVec[0].x(), mVec[0].y(), mVec[0].z());
00108 }
00109
00110 Vector3<T_Scalar> getY() const
00111 {
00112 return Vector3<T_Scalar>(mVec[1].x(), mVec[1].y(), mVec[1].z());
00113 }
00114
00115 Vector3<T_Scalar> getZ() const
00116 {
00117 return Vector3<T_Scalar>(mVec[2].x(), mVec[2].y(), mVec[2].z());
00118 }
00119
00120 Vector3<T_Scalar> getT() const
00121 {
00122 return Vector3<T_Scalar>(mVec[3].x(), mVec[3].y(), mVec[3].z());
00123 }
00124
00125 Matrix4& setX(const Vector3<T_Scalar>& v)
00126 {
00127 mVec[0].x() = v.x();
00128 mVec[0].y() = v.y();
00129 mVec[0].z() = v.z();
00130 return *this;
00131 }
00132
00133 Matrix4& setY(const Vector3<T_Scalar>& v)
00134 {
00135 mVec[1].x() = v.x();
00136 mVec[1].y() = v.y();
00137 mVec[1].z() = v.z();
00138 return *this;
00139 }
00140
00141 Matrix4& setZ(const Vector3<T_Scalar>& v)
00142 {
00143 mVec[2].x() = v.x();
00144 mVec[2].y() = v.y();
00145 mVec[2].z() = v.z();
00146 return *this;
00147 }
00148
00149 Matrix4& setT(const Vector3<T_Scalar>& v)
00150 {
00151 mVec[3].x() = v.x();
00152 mVec[3].y() = v.y();
00153 mVec[3].z() = v.z();
00154 return *this;
00155 }
00156
00157 bool operator==(const Matrix4& m) const
00158 {
00159 return memcmp(m.mVec, mVec, sizeof(T_Scalar)*4*4) == 0;
00160 }
00161
00162 bool operator!=(const Matrix4& m) const
00163 {
00164 return !operator==(m);
00165 }
00166
00167 Matrix4& operator=(const Matrix4& m)
00168 {
00169 memcpy(mVec, m.mVec, sizeof(T_Scalar)*16);
00170 return *this;
00171 }
00172
00173 Matrix4 operator+(const Matrix4& m) const
00174 {
00175 Matrix4 t;
00176 for(int i=0; i<4; ++i)
00177 for(int j=0; j<4; ++j)
00178 t.e(j,i) = e(j,i) + m.e(j,i);
00179
00180 return t;
00181 }
00182
00183 Matrix4& operator+=(const Matrix4& m)
00184 {
00185 for(int i=0; i<4; ++i)
00186 for(int j=0; j<4; ++j)
00187 e(j,i) += m.e(i,j);
00188 return *this;
00189 }
00190
00191 Matrix4 operator-(const Matrix4& m) const
00192 {
00193 Matrix4 t;
00194 for(int i=0; i<4; ++i)
00195 for(int j=0; j<4; ++j)
00196 t.e(j,i) = e(j,i) - m.e(j,i);
00197
00198 return t;
00199 }
00200
00201 Matrix4& operator-=(const Matrix4& m)
00202 {
00203 for(int i=0; i<4; ++i)
00204 for(int j=0; j<4; ++j)
00205 e(j,i) -= m.e(i,j);
00206 return *this;
00207 }
00208
00209 Matrix4& operator*=(const Matrix4& m)
00210 {
00211 return postMultiply(m);
00212 }
00213
00214 Matrix4 operator-() const
00215 {
00216 Matrix4 t;
00217 for(int i=0; i<4; ++i)
00218 for(int j=0; j<4; ++j)
00219 t.e(j,i) = -e(j,i);
00220 return t;
00221 }
00222
00223 Matrix4 operator+(T_Scalar d) const
00224 {
00225 Matrix4 t;
00226 for(int i=0; i<4; ++i)
00227 for(int j=0; j<4; ++j)
00228 t.e(j,i) = e(j,i) + d;
00229 return t;
00230 }
00231
00232 Matrix4& operator+=(T_Scalar d)
00233 {
00234 for(int i=0; i<4; ++i)
00235 for(int j=0; j<4; ++j)
00236 e(j,i) += d;
00237 return *this;
00238 }
00239
00240 Matrix4 operator-(T_Scalar d) const
00241 {
00242 Matrix4 t;
00243 for(int i=0; i<4; ++i)
00244 for(int j=0; j<4; ++j)
00245 t.e(j,i) = e(j,i) - d;
00246 return t;
00247 }
00248
00249 Matrix4& operator-=(T_Scalar d)
00250 {
00251 for(int i=0; i<4; ++i)
00252 for(int j=0; j<4; ++j)
00253 e(j,i) -= d;
00254 return *this;
00255 }
00256
00257 Matrix4 operator*(T_Scalar d) const
00258 {
00259 Matrix4 t;
00260 for(int i=0; i<4; ++i)
00261 for(int j=0; j<4; ++j)
00262 t.e(j,i) = e(j,i) * d;
00263 return t;
00264 }
00265
00266 Matrix4& operator*=(T_Scalar d)
00267 {
00268 for(int i=0; i<4; ++i)
00269 for(int j=0; j<4; ++j)
00270 e(j,i) *= d;
00271 return *this;
00272 }
00273
00274 Matrix4 operator/(T_Scalar d) const
00275 {
00276 d = (T_Scalar)1 / d;
00277 Matrix4 t;
00278 for(int i=0; i<4; ++i)
00279 for(int j=0; j<4; ++j)
00280 t.e(j,i) = e(j,i) * d;
00281 return t;
00282 }
00283
00284 Matrix4& operator/=(T_Scalar d)
00285 {
00286 d = (T_Scalar)1 / d;
00287 for(int i=0; i<4; ++i)
00288 for(int j=0; j<4; ++j)
00289 e(j,i) *= d;
00290 return *this;
00291 }
00292
00293 bool isIdentity() const
00294 {
00295 Matrix4 i;
00296 return memcmp(ptr(), i.ptr(), sizeof(T_Scalar)*16) == 0;
00297 }
00298
00299 Matrix4 as3x3() const
00300 {
00301 Matrix4 t = *this;
00302 t[0][3] = 0;
00303 t[1][3] = 0;
00304 t[2][3] = 0;
00305 t[3][3] = 1;
00306 t[3][0] = 0;
00307 t[3][1] = 0;
00308 t[3][2] = 0;
00309 return t;
00310 }
00311
00312 Matrix3<T_Scalar> get3x3() const
00313 {
00314 Matrix3<T_Scalar> t;
00315 t.e(0,0) = e(0,0); t.e(1,0) = e(1,0); t.e(2,0) = e(2,0);
00316 t.e(0,1) = e(0,1); t.e(1,1) = e(1,1); t.e(2,1) = e(2,1);
00317 t.e(0,2) = e(0,2); t.e(1,2) = e(1,2); t.e(2,2) = e(2,2);
00318 return t;
00319 }
00320
00322 void set3x3(const Matrix3<T_Scalar>& m)
00323 {
00324 e(0,0) = m.e(0,0); e(1,0) = m.e(1,0); e(2,0) = m.e(2,0);
00325 e(0,1) = m.e(0,1); e(1,1) = m.e(1,1); e(2,1) = m.e(2,1);
00326 e(0,2) = m.e(0,2); e(1,2) = m.e(1,2); e(2,2) = m.e(2,2);
00327 }
00328
00329 T_Scalar* ptr()
00330 {
00331 return &e(0,0);
00332 }
00333
00334 const T_Scalar* ptr() const
00335 {
00336 return &e(0,0);
00337 }
00338
00339 Matrix4& transpose()
00340 {
00341 T_Scalar tmp;
00342 for(int i=0; i<4; ++i)
00343 for(int j=i; j<4; ++j)
00344 {
00345 tmp = e(j,i);
00346 e(j,i) = e(i,j);
00347 e(i,j) = tmp;
00348 }
00349 return *this;
00350 }
00351
00352 Matrix4 getTransposed() const
00353 {
00354 Matrix4 m;
00355 for(int i=0; i<4; ++i)
00356 for(int j=0; j<4; ++j)
00357 m.e(j,i) = e(i,j);
00358 return m;
00359 }
00360
00361 Matrix4& getTransposed(Matrix4& dest) const
00362 {
00363 for(int i=0; i<4; ++i)
00364 for(int j=0; j<4; ++j)
00365 dest.e(j,i) = e(i,j);
00366 return dest;
00367 }
00368
00369 bool isNull() const
00370 {
00371 for(int i=0; i<4; ++i)
00372 for(int j=0; j<4; ++j)
00373 if(e(i,j) != 0)
00374 return false;
00375 return true;
00376 }
00377
00378 Matrix4& setNull()
00379 {
00380 fill(0);
00381 return *this;
00382 }
00383
00384 static Matrix4& getNull(Matrix4& out)
00385 {
00386 out.fill(0);
00387 return out;
00388 }
00389
00390 static Matrix4 getNull()
00391 {
00392 return Matrix4().fill(0);
00393 }
00394
00395 Matrix4& setIdentity()
00396 {
00397 static const T_Scalar I4d[] =
00398 {
00399 (T_Scalar)1, (T_Scalar)0, (T_Scalar)0, (T_Scalar)0,
00400 (T_Scalar)0, (T_Scalar)1, (T_Scalar)0, (T_Scalar)0,
00401 (T_Scalar)0, (T_Scalar)0, (T_Scalar)1, (T_Scalar)0,
00402 (T_Scalar)0, (T_Scalar)0, (T_Scalar)0, (T_Scalar)1
00403 };
00404 memcpy(mVec, I4d, sizeof(T_Scalar)*16);
00405 return *this;
00406 }
00407
00408 static Matrix4 getIdentity()
00409 {
00410 return Matrix4();
00411 }
00412
00413 static Matrix4& getIdentity(Matrix4& out)
00414 {
00415 out.setIdentity();
00416 return out;
00417 }
00418
00419 T_Scalar getInverse(Matrix4& dest) const;
00420
00421 Matrix4 getInverse(T_Scalar *determinant=NULL) const
00422 {
00423 Matrix4 tmp;
00424 T_Scalar det = getInverse(tmp);
00425 if (determinant)
00426 *determinant = det;
00427 return tmp;
00428 }
00429
00430 Matrix4& invert(T_Scalar *determinant=NULL)
00431 {
00432 T_Scalar det = getInverse(*this);
00433 if (determinant)
00434 *determinant = det;
00435 return *this;
00436 }
00437
00438 static Matrix4 getPerspective(T_Scalar fovy, T_Scalar aspect_ratio, T_Scalar znear, T_Scalar zfar);
00439
00440 static Matrix4 getFrustum(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop, T_Scalar pnear, T_Scalar pfar);
00441
00442 static Matrix4 getOrtho(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop, T_Scalar pnear, T_Scalar pfar);
00443
00444 static Matrix4 getOrtho2D(T_Scalar pleft, T_Scalar pright, T_Scalar pbottom, T_Scalar ptop);
00445
00446 static Matrix4 getLookAt(const Vector3<T_Scalar>& eye, const Vector3<T_Scalar>& look, const Vector3<T_Scalar>& up);
00447
00448 void getAsLookAt(Vector3<T_Scalar>& eye, Vector3<T_Scalar>& look, Vector3<T_Scalar>& up, Vector3<T_Scalar>& right) const;
00449
00450 void getYXRotationAngles(T_Scalar& degrees_y, T_Scalar& degrees_x) const;
00451
00452 static Matrix4& getRotation(Matrix4& out, T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z);
00453
00454 static Matrix4 getRotation(T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
00455 {
00456 Matrix4 m;
00457 return getRotation(m, degrees, x, y, z);
00458 }
00459
00460 static Matrix4 getRotation(T_Scalar degrees, const Vector3<T_Scalar>& v)
00461 {
00462 return getRotation(degrees, v.x(), v.y(), v.z());
00463 }
00464
00465 static Matrix4 getRotation(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2)
00466 {
00467 return getRotation(degrees1, v1.x(), v1.y(), v1.z()) * getRotation(degrees2, v2.x(), v2.y(), v2.z());
00468 }
00469
00470 static Matrix4 getRotation(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2, T_Scalar degrees3, const Vector3<T_Scalar>& v3)
00471 {
00472 return getRotation(degrees1, v1.x(), v1.y(), v1.z()) * getRotation(degrees2, v2.x(), v2.y(), v2.z()) * getRotation(degrees3, v3.x(), v3.y(), v3.z());
00473 }
00474
00475 Matrix4& rotate(T_Scalar degrees, const Vector3<T_Scalar>& v)
00476 {
00477 return rotate(degrees, v.x(), v.y(), v.z());
00478 }
00479
00480 Matrix4& rotate(T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
00481 {
00482 return preMultiply(getRotation(degrees, x, y, z));
00483 }
00484
00485 Matrix4& rotate(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2)
00486 {
00487 return preMultiply(getRotation(degrees1, v1, degrees2, v2));
00488 }
00489
00490 Matrix4& rotate(T_Scalar degrees1, const Vector3<T_Scalar>& v1, T_Scalar degrees2, const Vector3<T_Scalar>& v2, T_Scalar degrees3, const Vector3<T_Scalar>& v3)
00491 {
00492 return preMultiply(getRotation(degrees1, v1, degrees2, v2, degrees3, v3));
00493 }
00494
00495 static Matrix4 getRotationXYZ(T_Scalar degX, T_Scalar degY, T_Scalar degZ)
00496 {
00497 return getRotation(degX, 1,0,0) * getRotation(degY, 0,1,0) * getRotation(degZ, 0,0,1);
00498 }
00499
00500 Matrix4& rotateXYZ(T_Scalar degX, T_Scalar degY, T_Scalar degZ)
00501 {
00502 return preMultiply(getRotationXYZ(degX, degY, degZ));
00503 }
00504
00505 static Matrix4 getRotationZYX(T_Scalar degZ, T_Scalar degY, T_Scalar degX)
00506 {
00507 return getRotation(degZ, 0,0,1) * getRotation(degY, 0,1,0) * getRotation(degX, 1,0,0);
00508 }
00509
00510 Matrix4& rotateZYX(T_Scalar degZ, T_Scalar degY, T_Scalar degX)
00511 {
00512 return preMultiply(getRotationZYX(degZ, degY, degX));
00513 }
00514
00515 static Matrix4& getRotation(Matrix4& out, const Vector3<T_Scalar>& from, const Vector3<T_Scalar>& to);
00516
00517 static Matrix4 getRotation(const Vector3<T_Scalar>& from, const Vector3<T_Scalar>& to)
00518 {
00519 Matrix4 m;
00520 return getRotation(m, from, to);
00521 }
00522
00523 Matrix4& rotate(const Vector4<T_Scalar>& from, const Vector4<T_Scalar>& to)
00524 {
00525 return preMultiply(getRotation(from, to));
00526 }
00527
00528 Matrix4& rotate(const Vector3<T_Scalar>& from, const Vector3<T_Scalar>& to)
00529 {
00530 return preMultiply(getRotation(from, to));
00531 }
00532
00533 static Matrix4& getTranslation(Matrix4&out, const Vector3<T_Scalar>& v)
00534 {
00535 return getTranslation(out, v.x(), v.y(), v.z());
00536 }
00537
00538 static Matrix4 getTranslation(const Vector3<T_Scalar>& v)
00539 {
00540 Matrix4 m;
00541 return getTranslation(m, v.x(), v.y(), v.z());
00542 }
00543
00544 static Matrix4 getTranslation(T_Scalar x, T_Scalar y, T_Scalar z)
00545 {
00546 Matrix4 m;
00547 return getTranslation(m, x, y, z);
00548 }
00549
00550 static Matrix4& getTranslation(Matrix4& out, T_Scalar x, T_Scalar y, T_Scalar z)
00551 {
00552 out.setIdentity();
00553 out.e(0,3) = x;
00554 out.e(1,3) = y;
00555 out.e(2,3) = z;
00556 return out;
00557 }
00558
00559 Matrix4& translate(T_Scalar x, T_Scalar y, T_Scalar z)
00560 {
00561 return preMultiply(getTranslation(x,y,z));
00562 }
00563
00564 Matrix4& translate(const Vector3<T_Scalar>& v)
00565 {
00566 return preMultiply(getTranslation(v));
00567 }
00568
00569 static Matrix4& getScaling(Matrix4& out, const Vector3<T_Scalar>& v)
00570 {
00571 return getScaling(out, v.x(), v.y(), v.z());
00572 }
00573
00574 static Matrix4 getScaling(const Vector3<T_Scalar>& v)
00575 {
00576 Matrix4 m;
00577 return getScaling(m, v.x(), v.y(), v.z());
00578 }
00579
00580 static Matrix4 getScaling(T_Scalar x, T_Scalar y, T_Scalar z)
00581 {
00582 Matrix4 m;
00583 return getScaling(m, x, y, z);
00584 }
00585
00586 static Matrix4& getScaling(Matrix4& out, T_Scalar x, T_Scalar y, T_Scalar z)
00587 {
00588 out.setIdentity();
00589 out.e(0,0) = x;
00590 out.e(1,1) = y;
00591 out.e(2,2) = z;
00592 return out;
00593 }
00594
00595 Matrix4& scale(T_Scalar x, T_Scalar y, T_Scalar z)
00596 {
00597 return preMultiply(getScaling(x,y,z));
00598 }
00599
00600 Matrix4& scale(const Vector3<T_Scalar> v)
00601 {
00602 return preMultiply(getScaling(v.x(), v.y(), v.z()));
00603 }
00604
00605 static Matrix4& multiply(Matrix4& out, const Matrix4& p, const Matrix4& q)
00606 {
00607 VL_CHECK(out.ptr() != p.ptr() && out.ptr() != q.ptr());
00608
00609 out.e(0,0) = q.e(0,0)*p.e(0,0) + q.e(1,0)*p.e(0,1) + q.e(2,0)*p.e(0,2) + q.e(3,0)*p.e(0,3);
00610 out.e(0,1) = q.e(0,1)*p.e(0,0) + q.e(1,1)*p.e(0,1) + q.e(2,1)*p.e(0,2) + q.e(3,1)*p.e(0,3);
00611 out.e(0,2) = q.e(0,2)*p.e(0,0) + q.e(1,2)*p.e(0,1) + q.e(2,2)*p.e(0,2) + q.e(3,2)*p.e(0,3);
00612 out.e(0,3) = q.e(0,3)*p.e(0,0) + q.e(1,3)*p.e(0,1) + q.e(2,3)*p.e(0,2) + q.e(3,3)*p.e(0,3);
00613
00614 out.e(1,0) = q.e(0,0)*p.e(1,0) + q.e(1,0)*p.e(1,1) + q.e(2,0)*p.e(1,2) + q.e(3,0)*p.e(1,3);
00615 out.e(1,1) = q.e(0,1)*p.e(1,0) + q.e(1,1)*p.e(1,1) + q.e(2,1)*p.e(1,2) + q.e(3,1)*p.e(1,3);
00616 out.e(1,2) = q.e(0,2)*p.e(1,0) + q.e(1,2)*p.e(1,1) + q.e(2,2)*p.e(1,2) + q.e(3,2)*p.e(1,3);
00617 out.e(1,3) = q.e(0,3)*p.e(1,0) + q.e(1,3)*p.e(1,1) + q.e(2,3)*p.e(1,2) + q.e(3,3)*p.e(1,3);
00618
00619 out.e(2,0) = q.e(0,0)*p.e(2,0) + q.e(1,0)*p.e(2,1) + q.e(2,0)*p.e(2,2) + q.e(3,0)*p.e(2,3);
00620 out.e(2,1) = q.e(0,1)*p.e(2,0) + q.e(1,1)*p.e(2,1) + q.e(2,1)*p.e(2,2) + q.e(3,1)*p.e(2,3);
00621 out.e(2,2) = q.e(0,2)*p.e(2,0) + q.e(1,2)*p.e(2,1) + q.e(2,2)*p.e(2,2) + q.e(3,2)*p.e(2,3);
00622 out.e(2,3) = q.e(0,3)*p.e(2,0) + q.e(1,3)*p.e(2,1) + q.e(2,3)*p.e(2,2) + q.e(3,3)*p.e(2,3);
00623
00624 out.e(3,0) = q.e(0,0)*p.e(3,0) + q.e(1,0)*p.e(3,1) + q.e(2,0)*p.e(3,2) + q.e(3,0)*p.e(3,3);
00625 out.e(3,1) = q.e(0,1)*p.e(3,0) + q.e(1,1)*p.e(3,1) + q.e(2,1)*p.e(3,2) + q.e(3,1)*p.e(3,3);
00626 out.e(3,2) = q.e(0,2)*p.e(3,0) + q.e(1,2)*p.e(3,1) + q.e(2,2)*p.e(3,2) + q.e(3,2)*p.e(3,3);
00627 out.e(3,3) = q.e(0,3)*p.e(3,0) + q.e(1,3)*p.e(3,1) + q.e(2,3)*p.e(3,2) + q.e(3,3)*p.e(3,3);
00628
00629 return out;
00630 }
00631
00632 Matrix4& postMultiply(const Matrix4& m)
00633 {
00634 Matrix4<T_Scalar> t;
00635 return *this = multiply(t, *this, m);
00636 }
00637
00638 Matrix4& preMultiply(const Matrix4& m)
00639 {
00640 Matrix4<T_Scalar> t;
00641 return *this = multiply(t, m, *this);
00642 }
00643
00644
00645 const T_Scalar& e(int i, int j) const { return mVec[j][i]; }
00646 T_Scalar& e(int i, int j) { return mVec[j][i]; }
00647
00648 private:
00649 const Vector4<T_Scalar>& operator[](unsigned int i) const { VL_CHECK(i<4); return mVec[i]; }
00650 Vector4<T_Scalar>& operator[](unsigned int i) { VL_CHECK(i<4); return mVec[i]; }
00651
00652 protected:
00653 Vector4<T_Scalar> mVec[4];
00654 };
00655
00656
00657
00658 template<typename T_Scalar>
00659 inline Matrix4<T_Scalar> operator*(const Matrix4<T_Scalar>& p, const Matrix4<T_Scalar>& q)
00660 {
00661 Matrix4<T_Scalar> t;
00662 Matrix4<T_Scalar>::multiply(t, p, q);
00663 return t;
00664 }
00665
00666 template<typename T_Scalar>
00667 inline Matrix4<T_Scalar> operator+(T_Scalar d, const Matrix4<T_Scalar>& m)
00668 {
00669 return m + d;
00670 }
00671
00672 template<typename T_Scalar>
00673 inline Matrix4<T_Scalar> operator*(T_Scalar d, const Matrix4<T_Scalar>& m)
00674 {
00675 return m * d;
00676 }
00677
00679 template<typename T_Scalar>
00680 inline Vector4<T_Scalar> operator*(const Matrix4<T_Scalar>& m, const Vector4<T_Scalar>& v)
00681 {
00682 return Vector4<T_Scalar>(
00683 v.x()*m.e(0,0) + v.y()*m.e(0,1) + v.z()*m.e(0,2) + v.w()*m.e(0,3),
00684 v.x()*m.e(1,0) + v.y()*m.e(1,1) + v.z()*m.e(1,2) + v.w()*m.e(1,3),
00685 v.x()*m.e(2,0) + v.y()*m.e(2,1) + v.z()*m.e(2,2) + v.w()*m.e(2,3),
00686 v.x()*m.e(3,0) + v.y()*m.e(3,1) + v.z()*m.e(3,2) + v.w()*m.e(3,3)
00687 );
00688 }
00689
00692 template<typename T_Scalar>
00693 inline Vector3<T_Scalar> operator*(const Matrix4<T_Scalar>& m, const Vector3<T_Scalar>& v)
00694 {
00695 return Vector3<T_Scalar>(
00696 v.x()*m.e(0,0) + v.y()*m.e(0,1) + v.z()*m.e(0,2) + m.e(0,3),
00697 v.x()*m.e(1,0) + v.y()*m.e(1,1) + v.z()*m.e(1,2) + m.e(1,3),
00698 v.x()*m.e(2,0) + v.y()*m.e(2,1) + v.z()*m.e(2,2) + m.e(2,3)
00699 );
00700 }
00701
00704 template<typename T_Scalar>
00705 inline Vector2<T_Scalar> operator*(const Matrix4<T_Scalar>& m, const Vector2<T_Scalar>& v)
00706 {
00707 return Vector2<T_Scalar>(
00708 v.x()*m.e(0,0) + v.y()*m.e(0,1) + m.e(0,3),
00709 v.x()*m.e(1,0) + v.y()*m.e(1,1) + m.e(1,3)
00710 );
00711 }
00712
00714 template<typename T_Scalar>
00715 inline Vector4<T_Scalar> operator*(const Vector4<T_Scalar>& v, const Matrix4<T_Scalar>& m)
00716 {
00717 return Vector4<T_Scalar>(
00718 v.x()*m.e(0,0) + v.y()*m.e(1,0) + v.z()*m.e(2,0) + v.w()*m.e(3,0),
00719 v.x()*m.e(0,1) + v.y()*m.e(1,1) + v.z()*m.e(2,1) + v.w()*m.e(3,1),
00720 v.x()*m.e(0,2) + v.y()*m.e(1,2) + v.z()*m.e(2,2) + v.w()*m.e(3,2),
00721 v.x()*m.e(0,3) + v.y()*m.e(1,3) + v.z()*m.e(2,3) + v.w()*m.e(3,3)
00722 );
00723 }
00724
00727 template<typename T_Scalar>
00728 inline Vector3<T_Scalar> operator*(const Vector3<T_Scalar>& v, const Matrix4<T_Scalar>& m)
00729 {
00730 return Vector3<T_Scalar>(
00731 v.x()*m.e(0,0) + v.y()*m.e(1,0) + v.z()*m.e(2,0) + m.e(3,0),
00732 v.x()*m.e(0,1) + v.y()*m.e(1,1) + v.z()*m.e(2,1) + m.e(3,1),
00733 v.x()*m.e(0,2) + v.y()*m.e(1,2) + v.z()*m.e(2,2) + m.e(3,2)
00734 );
00735 }
00736
00739 template<typename T_Scalar>
00740 inline Vector2<T_Scalar> operator*(const Vector2<T_Scalar>& v, const Matrix4<T_Scalar>& m)
00741 {
00742 return Vector2<T_Scalar>(
00743 v.x()*m.e(0,0) + v.y()*m.e(1,0) + m.e(3,0),
00744 v.x()*m.e(0,1) + v.y()*m.e(1,1) + m.e(3,1)
00745 );
00746 }
00747
00748 template<typename T_Scalar>
00749 Matrix4<T_Scalar> Matrix4<T_Scalar>::getLookAt(const Vector3<T_Scalar>& eye, const Vector3<T_Scalar>& look, const Vector3<T_Scalar>& up)
00750 {
00751 Vector3<T_Scalar> y = Vector3<T_Scalar>(up).normalize();
00752 Vector3<T_Scalar> z = (eye - look).normalize();
00753 Vector3<T_Scalar> x = cross(y,z).normalize();
00754 y = cross(z, x).normalize();
00755
00756 Matrix4<T_Scalar> m;
00757
00758 m.setT(eye);
00759 m.setX(x);
00760 m.setY(y);
00761 m.setZ(z);
00762
00763 return m;
00764 }
00765
00766 template<typename T_Scalar>
00767 void Matrix4<T_Scalar>::getAsLookAt(Vector3<T_Scalar>& eye, Vector3<T_Scalar>& look, Vector3<T_Scalar>& up, Vector3<T_Scalar>& right) const
00768 {
00769 eye = getT();
00770
00771 look = -getZ();
00772 look.normalize();
00773
00774 up = getY();
00775 up.normalize();
00776
00777 right = getX();
00778 right.normalize();
00779 }
00780
00781 template<typename T_Scalar>
00782 Matrix4<T_Scalar> Matrix4<T_Scalar>::getPerspective(T_Scalar fovy, T_Scalar aspect_ratio, T_Scalar znear, T_Scalar zfar)
00783 {
00784 Matrix4<T_Scalar> m;
00785
00786 T_Scalar rads = (fovy / ((T_Scalar)2)) * (T_Scalar)dDEG_TO_RAD;
00787 T_Scalar dz = zfar - znear;
00788 T_Scalar sa = sin(rads);
00789 if ((dz == 0) || (sa == 0) || (aspect_ratio == 0))
00790 return m * 0;
00791 T_Scalar ctan = cos(rads) / sa;
00792
00793 m.e(0,0) = (T_Scalar)(ctan / aspect_ratio);
00794 m.e(1,1) = (T_Scalar)(ctan);
00795 m.e(2,2) = (T_Scalar)(-(zfar + znear) / dz);
00796 m.e(3,2) = -((T_Scalar)1);
00797 m.e(2,3) = (T_Scalar)(-((T_Scalar)2) * znear * zfar / dz);
00798 m.e(3,3) = 0;
00799
00800 return m;
00801 }
00802
00803 template<typename T_Scalar>
00804 Matrix4<T_Scalar> Matrix4<T_Scalar>::getFrustum(T_Scalar left, T_Scalar right, T_Scalar bottom, T_Scalar top, T_Scalar pnear, T_Scalar pfar)
00805 {
00806 Matrix4<T_Scalar> m;
00807
00808 if (pnear <= 0 || pfar <= 0 || pnear == pfar || left == right || top == bottom)
00809 return m * 0;
00810
00811 T_Scalar x = (((T_Scalar)2)*pnear) / (right-left);
00812 T_Scalar y = (((T_Scalar)2)*pnear) / (top-bottom);
00813 T_Scalar a = (right+left) / (right-left);
00814 T_Scalar b = (top+bottom) / (top-bottom);
00815 T_Scalar c = -(pfar+pnear) / (pfar-pnear);
00816 T_Scalar d = -(((T_Scalar)2)*pfar*pnear) / (pfar-pnear);
00817
00818 m.e(0,0) = x; m.e(0,1) = 0; m.e(0,2) = a; m.e(0,3) = 0;
00819 m.e(1,0) = 0; m.e(1,1) = y; m.e(1,2) = b; m.e(1,3) = 0;
00820 m.e(2,0) = 0; m.e(2,1) = 0; m.e(2,2) = c; m.e(2,3) = d;
00821 m.e(3,0) = 0; m.e(3,1) = 0; m.e(3,2) = -((T_Scalar)1); m.e(3,3) = 0;
00822
00823 return m;
00824 }
00825
00826 template<typename T_Scalar>
00827 Matrix4<T_Scalar> Matrix4<T_Scalar>::getOrtho(T_Scalar left, T_Scalar right, T_Scalar bottom, T_Scalar top, T_Scalar pnear, T_Scalar pfar)
00828 {
00829 Matrix4<T_Scalar> m;
00830
00831 m.e(0,0) = ((T_Scalar)2) / (right-left);
00832 m.e(0,1) = 0;
00833 m.e(0,2) = 0;
00834 m.e(0,3) = -(right+left) / (right-left);
00835
00836 m.e(1,0) = 0;
00837 m.e(1,1) = ((T_Scalar)2) / (top-bottom);
00838 m.e(1,2) = 0;
00839 m.e(1,3) = -(top+bottom) / (top-bottom);
00840
00841 m.e(2,0) = 0;
00842 m.e(2,1) = 0;
00843 m.e(2,2) = -((T_Scalar)2) / (pfar-pnear);
00844 m.e(2,3) = -(pfar+pnear) / (pfar-pnear);
00845
00846 m.e(3,0) = 0;
00847 m.e(3,1) = 0;
00848 m.e(3,2) = 0;
00849 m.e(3,3) = ((T_Scalar)1);
00850
00851 return m;
00852 }
00853
00854 template<typename T_Scalar>
00855 Matrix4<T_Scalar> Matrix4<T_Scalar>::getOrtho2D(T_Scalar left, T_Scalar right, T_Scalar bottom, T_Scalar top)
00856 {
00857 return getOrtho(left, right, bottom, top, -1, +1);
00858 }
00859
00860 template<typename T_Scalar>
00861 Matrix4<T_Scalar>& Matrix4<T_Scalar>::getRotation(Matrix4<T_Scalar>& out, T_Scalar degrees, T_Scalar x, T_Scalar y, T_Scalar z)
00862 {
00863 out.setIdentity();
00864
00865 if (degrees == 0 || (x == 0 && y ==0 && z == 0))
00866 return out;
00867
00868 degrees = T_Scalar(degrees * dDEG_TO_RAD);
00869
00870 T_Scalar xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
00871
00872 s = (T_Scalar) sin(degrees);
00873 c = (T_Scalar) cos(degrees);
00874
00875
00876 if (x == 0)
00877 {
00878 if (y == 0)
00879 {
00880 if (z != 0)
00881 {
00882
00883 out.e(0,0) = (T_Scalar)c;
00884 out.e(1,1) = (T_Scalar)c;
00885 if (z < 0)
00886 {
00887 out.e(1,0) = -(T_Scalar)s;
00888 out.e(0,1) = (T_Scalar)s;
00889 }
00890 else
00891 {
00892 out.e(1,0) = (T_Scalar)s;
00893 out.e(0,1) = -(T_Scalar)s;
00894 }
00895 return out;
00896 }
00897 }
00898 else if (z == 0)
00899 {
00900
00901 out.e(0,0) = (T_Scalar)c;
00902 out.e(2,2) = (T_Scalar)c;
00903 if (y < 0)
00904 {
00905 out.e(2,0) = (T_Scalar)s;
00906 out.e(0,2) = -(T_Scalar)s;
00907 }
00908 else
00909 {
00910 out.e(2,0) = -(T_Scalar)s;
00911 out.e(0,2) = (T_Scalar)s;
00912 }
00913 return out;
00914 }
00915 }
00916 else if (y == 0)
00917 {
00918 if (z == 0)
00919 {
00920
00921 out.e(1,1) = (T_Scalar)c;
00922 out.e(2,2) = (T_Scalar)c;
00923 if (x < 0)
00924 {
00925 out.e(2,1) = -(T_Scalar)s;
00926 out.e(1,2) = (T_Scalar)s;
00927 }
00928 else
00929 {
00930 out.e(2,1) = (T_Scalar)s;
00931 out.e(1,2) = -(T_Scalar)s;
00932 }
00933 return out;
00934 }
00935 }
00936
00937
00938 T_Scalar dot = x*x + y*y + z*z;
00939
00940 if (dot > (T_Scalar)((T_Scalar)1.0001) || dot < (T_Scalar)0.99999)
00941 {
00942 T_Scalar mag = (T_Scalar) sqrt(dot);
00943 x /= mag;
00944 y /= mag;
00945 z /= mag;
00946 }
00947
00948 xx = x *x;
00949 yy = y * y;
00950 zz = z * z;
00951 xy = x * y;
00952 yz = y * z;
00953 zx = z * x;
00954 xs = x * s;
00955 ys = y * s;
00956 zs = z * s;
00957 one_c = ((T_Scalar)1) - c;
00958
00959 out.e(0,0) = (T_Scalar)((one_c * xx) + c); out.e(1,0) = (T_Scalar)((one_c * xy) + zs); out.e(2,0) = (T_Scalar)((one_c * zx) - ys);
00960 out.e(0,1) = (T_Scalar)((one_c * xy) - zs); out.e(1,1) = (T_Scalar)((one_c * yy) + c); out.e(2,1) = (T_Scalar)((one_c * yz) + xs);
00961 out.e(0,2) = (T_Scalar)((one_c * zx) + ys); out.e(1,2) = (T_Scalar)((one_c * yz) - xs); out.e(2,2) = (T_Scalar)((one_c * zz) + c);
00962 return out;
00963 }
00964
00965 template<typename T_Scalar>
00966 T_Scalar Matrix4<T_Scalar>::getInverse(Matrix4<T_Scalar>& dest) const
00967 {
00968 const T_Scalar* in = ptr();
00969 T_Scalar* out = dest.ptr();
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 const T_Scalar a = in[0]; const T_Scalar b = in[4]; const T_Scalar c = in[ 8]; const T_Scalar d = in[12];
00982 const T_Scalar e = in[1]; const T_Scalar f = in[5]; const T_Scalar g = in[ 9]; const T_Scalar h = in[13];
00983 const T_Scalar i = in[2]; const T_Scalar l = in[6]; const T_Scalar m = in[10]; const T_Scalar n = in[14];
00984 const T_Scalar o = in[3]; const T_Scalar p = in[7]; const T_Scalar q = in[11]; const T_Scalar r = in[15];
00985
00986
00987
00988
00989
00990
00991
00992 const T_Scalar mr = m*r;
00993 const T_Scalar gn = g*n;
00994 const T_Scalar el = e*l;
00995 const T_Scalar ip = i*p;
00996 const T_Scalar mo = m*o;
00997 const T_Scalar hl = h*l;
00998 const T_Scalar mp = m*p;
00999 const T_Scalar nq = n*q;
01000 const T_Scalar gl = g*l;
01001 const T_Scalar no = n*o;
01002 const T_Scalar gi = g*i;
01003 const T_Scalar np = n*p;
01004 const T_Scalar fi = f*i;
01005 const T_Scalar rc = r*c;
01006 const T_Scalar be = b*e;
01007 const T_Scalar af = a*f;
01008 const T_Scalar de = d*e;
01009 const T_Scalar df = d*f;
01010 const T_Scalar ch = c*h;
01011 const T_Scalar qh = q*h;
01012
01013
01014
01015
01016 T_Scalar Ca = +(( f*mr + gn*p + hl*q ) - ( h*mp + nq*f + r*gl ));
01017
01018
01019
01020
01021 T_Scalar Cb = -(( e*mr + gn*o + i*qh ) - ( h*mo + gi*r + nq*e ));
01022
01023
01024
01025
01026 T_Scalar Cc = +(( el*r + ip*h + f*no ) - ( hl*o + np*e + fi*r ));
01027
01028
01029
01030
01031 T_Scalar Cd = -(( el*q + f*mo + g*ip ) - ( gl*o + mp*e + q*fi ));
01032
01033 T_Scalar det = a*Ca + b*Cb + c*Cc + d*Cd;
01034
01035
01036 if (det == 0)
01037 return det;
01038
01039
01040
01041
01042 T_Scalar Ce = -(( b*mr + c*np + d*l*q ) - ( d*mp + nq*b + rc*l ));
01043
01044
01045
01046
01047 T_Scalar Cf = +(( a*mr + c*no + d*i*q ) - ( d*mo + nq*a + rc*i ));
01048
01049
01050
01051
01052 T_Scalar Cg = -(( a*l*r + b*no + d*ip ) - ( d*l*o + np*a + r*b*i ));
01053
01054
01055
01056
01057 T_Scalar Ch = +(( a*l*q + b*mo + c*ip ) - ( c*l*o + mp*a + q*b*i ));
01058
01059
01060
01061
01062
01063 T_Scalar Ci = +(( b*g*r + ch*p + df*q ) - ( d*g*p + q*h*b + rc*f ));
01064
01065
01066
01067
01068 T_Scalar Cl = -(( a*g*r + ch*o + de*q ) - ( d*g*o + qh*a + rc*e ));
01069
01070
01071
01072
01073 T_Scalar Cm = +(( af*r + b*h*o + de*p ) - ( df*o + h*p*a + r*be ));
01074
01075
01076
01077
01078 T_Scalar Cn = -(( af*q + b*g*o + c*e*p ) - ( c*f*o + g*p*a + q*be ));
01079
01080
01081
01082
01083
01084 T_Scalar Co = -(( b*gn + c*hl + df*m ) - ( d*gl + h*m*b + n*c*f ));
01085
01086
01087
01088
01089 T_Scalar Cp = +(( a*gn + ch*i + de*m ) - ( d*gi + h*m*a + n*c*e ));
01090
01091
01092
01093
01094 T_Scalar Cq = -(( af*n + b*h*i + d*el ) - ( d*fi + hl*a + n*be ));
01095
01096
01097
01098
01099 T_Scalar Cr = +(( af*m + b*gi + c*el ) - ( c*fi + gl*a + m*be ));
01100
01101 #if 0
01102 T_Scalar det2 = e*Ce + f*Cf + g*Cg + h*Ch;
01103 T_Scalar det3 = i*Ci + l*Cl + m*Cm + n*Cn;
01104 T_Scalar det4 = o*Co + p*Cp + q*Cq + r*Cr;
01105 VL_CHECK( fabs(det - det1) < 0.0001 );
01106 VL_CHECK( fabs(det - det3) < 0.0001 );
01107 VL_CHECK( fabs(det - det4) < 0.0001 );
01108 #endif
01109
01110 T_Scalar inv_det = 1 / det;
01111
01112 out[0] = inv_det * Ca;
01113 out[1] = inv_det * Cb;
01114 out[2] = inv_det * Cc;
01115 out[3] = inv_det * Cd;
01116 out[4] = inv_det * Ce;
01117 out[5] = inv_det * Cf;
01118 out[6] = inv_det * Cg;
01119 out[7] = inv_det * Ch;
01120 out[8] = inv_det * Ci;
01121 out[9] = inv_det * Cl;
01122 out[10] = inv_det * Cm;
01123 out[11] = inv_det * Cn;
01124 out[12] = inv_det * Co;
01125 out[13] = inv_det * Cp;
01126 out[14] = inv_det * Cq;
01127 out[15] = inv_det * Cr;
01128
01129 return det;
01130 }
01131
01132 template<typename T_Scalar>
01133 Matrix4<T_Scalar>& Matrix4<T_Scalar>::getRotation(Matrix4<T_Scalar>& out, const Vector3<T_Scalar>& from, const Vector3<T_Scalar>& to)
01134 {
01135 Vector3<T_Scalar> a,b;
01136 a = from;
01137 b = to;
01138 a.normalize();
01139 b.normalize();
01140 T_Scalar cosa = dot(a,b);
01141 cosa = clamp(cosa,-((T_Scalar)1),+((T_Scalar)1));
01142 Vector3<T_Scalar> axis,n2;
01143 axis = cross(a,b);
01144 axis.normalize();
01145 T_Scalar alpha = acos(cosa);
01146 return getRotation(out, alpha*(T_Scalar)dRAD_TO_DEG, axis.x(), axis.y(), axis.z());
01147 }
01148
01155 template<typename T_Scalar>
01156 void Matrix4<T_Scalar>::getYXRotationAngles(T_Scalar& degrees_y, T_Scalar& degrees_x) const
01157 {
01158 Vector3<T_Scalar> vx = getX();
01159 Vector3<T_Scalar> vy = getY();
01160 Vector3<T_Scalar> vz = getZ();
01161
01162 vx.normalize();
01163 vy.normalize();
01164 vz.normalize();
01165
01166 T_Scalar kx = dot(vy,Vector3<T_Scalar>(0,1,0));
01167 kx = clamp(kx,-((T_Scalar)1),+((T_Scalar)1));
01168 degrees_x = acos(kx) * (T_Scalar)dRAD_TO_DEG;
01169 if(dot(vz, Vector3<T_Scalar>(0,1,0)) > 0)
01170 degrees_x = -degrees_x;
01171
01172 T_Scalar ky = dot(vx, Vector3<T_Scalar>(1,0,0));
01173 ky = clamp(ky,-((T_Scalar)1),+((T_Scalar)1));
01174 degrees_y = acos(ky) * (T_Scalar)dRAD_TO_DEG;
01175 if(dot(vz, Vector3<T_Scalar>(1,0,0)) < 0)
01176 degrees_y = -degrees_y;
01177 if (fabs(degrees_x) > (T_Scalar)90)
01178 degrees_y = -degrees_y;
01179 }
01180
01181
01182
01184 typedef Matrix4<double> dmat4;
01186 typedef Matrix4<float> fmat4;
01188 typedef Matrix4<int> imat4;
01190 typedef Matrix4<unsigned int> umat4;
01191
01192 #if VL_PIPELINE_PRECISION == 2
01193
01194 typedef dmat4 mat4;
01195 #else
01196
01197 typedef fmat4 mat4;
01198 #endif
01199 }
01200
01201 #endif