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