Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlCore/Matrix4.hpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
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   // Matrix4
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)) // avoid fabs/abs
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   // OPERATORS
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) + /*1**/m.e(0,3),
00712       v.x()*m.e(1,0) + v.y()*m.e(1,1) + v.z()*m.e(1,2) + /*1**/m.e(1,3),
00713       v.x()*m.e(2,0) + v.y()*m.e(2,1) + v.z()*m.e(2,2) + /*1**/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) + /*0*m.e(0,2) +*/ /*1**/m.e(0,3),
00724       v.x()*m.e(1,0) + v.y()*m.e(1,1) + /*0*m.e(1,2) +*/ /*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) + /*1**/m.e(3,0),
00747       v.x()*m.e(0,1) + v.y()*m.e(1,1) + v.z()*m.e(2,1) + /*1**/m.e(3,1),
00748       v.x()*m.e(0,2) + v.y()*m.e(1,2) + v.z()*m.e(2,2) + /*1**/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) + /*0*m.e(2,0) +*/ /*1**/m.e(3,0),
00759       v.x()*m.e(0,1) + v.y()*m.e(1,1) + /*0*m.e(2,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     // look at modeling
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     // look at view
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     // look.normalize();
00808 
00809     up = getY();
00810     // up.normalize();
00811 
00812     right = getX();
00813     // right.normalize();
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     // simple cases
00919     if (x == 0) 
00920     {
00921       if (y == 0) 
00922       {
00923         if (z != 0) 
00924         {
00925           // rotate only around z-axis
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         // rotate only around y-axis
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         // rotate only around x-axis
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     // Beginning of general axisa to matrix conversion
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     // | 0 | 4 | 8  | 12 |
01015     // | 1 | 5 | 9  | 13 |
01016     // | 2 | 6 | 10 | 14 |
01017     // | 3 | 7 | 11 | 15 |
01018 
01019     // | a | b | c | d |
01020     // | e | f | g | h |
01021     // | i | l | m | n |
01022     // | o | p | q | r |
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     // 3x3 determinant:
01030     //
01031     //   [ a b c ]
01032     //   [ d e f ] = aei - ahf + dhc - dbi + gbf - gec = (aei + dhc + gbf) - (ahf + dbi + gec)
01033     //   [ g h i ]
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     // | f | g | h |
01057     // | l | m | n |
01058     // | p | q | r |
01059     T_Scalar Ca = +(( f*mr + gn*p + hl*q ) - ( h*mp + nq*f + r*gl ));
01060 
01061     // | e | g | h |
01062     // | i | m | n |
01063     // | o | q | r |
01064     T_Scalar Cb = -(( e*mr + gn*o + i*qh ) - ( h*mo + gi*r + nq*e ));
01065 
01066     // | e | f | h |
01067     // | i | l | n |
01068     // | o | p | r |
01069     T_Scalar Cc = +(( el*r + ip*h + f*no ) - ( hl*o + np*e + fi*r ));
01070 
01071     // | e | f | g |
01072     // | i | l | m |
01073     // | o | p | q |
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     // singular matrix
01079     if (det == 0)
01080       return det;
01081 
01082     // | b | c | d |
01083     // | l | m | n |
01084     // | p | q | r |
01085     T_Scalar Ce = -(( b*mr + c*np + d*l*q ) - ( d*mp + nq*b + rc*l ));
01086 
01087     // | a | c | d |
01088     // | i | m | n |
01089     // | o | q | r |
01090     T_Scalar Cf = +(( a*mr + c*no + d*i*q ) - ( d*mo + nq*a + rc*i ));
01091 
01092     // | a | b | d |
01093     // | i | l | n |
01094     // | o | p | r |
01095     T_Scalar Cg = -(( a*l*r + b*no + d*ip ) - ( d*l*o + np*a + r*b*i ));
01096 
01097     // | a | b | c |
01098     // | i | l | m |
01099     // | o | p | q |
01100     T_Scalar Ch = +(( a*l*q + b*mo + c*ip ) - ( c*l*o + mp*a + q*b*i ));
01101 
01102 
01103     // | b | c | d |
01104     // | f | g | h |
01105     // | p | q | r |
01106     T_Scalar Ci = +(( b*g*r + ch*p + df*q ) - ( d*g*p + q*h*b + rc*f ));
01107 
01108     // | a | c | d |
01109     // | e | g | h |
01110     // | o | q | r |
01111     T_Scalar Cl = -(( a*g*r + ch*o + de*q ) - ( d*g*o  + qh*a + rc*e ));
01112 
01113     // | a | b | d |
01114     // | e | f | h |
01115     // | o | p | r |
01116     T_Scalar Cm = +(( af*r + b*h*o + de*p ) - ( df*o + h*p*a + r*be ));
01117 
01118     // | a | b | c |
01119     // | e | f | g |
01120     // | o | p | q |
01121     T_Scalar Cn = -(( af*q + b*g*o + c*e*p ) - ( c*f*o + g*p*a + q*be ));
01122 
01123 
01124     // | b | c | d |
01125     // | f | g | h |
01126     // | l | m | n |
01127     T_Scalar Co = -(( b*gn + c*hl + df*m ) - ( d*gl + h*m*b + n*c*f ));
01128 
01129     // | a | c | d |
01130     // | e | g | h |
01131     // | i | m | n |
01132     T_Scalar Cp = +(( a*gn + ch*i + de*m ) - ( d*gi + h*m*a + n*c*e ));
01133 
01134     // | a | b | d |
01135     // | e | f | h |
01136     // | i | l | n |
01137     T_Scalar Cq = -(( af*n + b*h*i + d*el ) - ( d*fi + hl*a + n*be ));
01138 
01139     // | a | b | c |
01140     // | e | f | g |
01141     // | i | l | m |
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

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:29.
Permission is granted to use this page to write and publish articles regarding Visualization Library.