qmatrix4x4.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the QtGui module of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:LGPL$
00010 ** Commercial Usage
00011 ** Licensees holding valid Qt Commercial licenses may use this file in
00012 ** accordance with the Qt Commercial License Agreement provided with the
00013 ** Software or, alternatively, in accordance with the terms contained in
00014 ** a written agreement between you and Nokia.
00015 **
00016 ** GNU Lesser General Public License Usage
00017 ** Alternatively, this file may be used under the terms of the GNU Lesser
00018 ** General Public License version 2.1 as published by the Free Software
00019 ** Foundation and appearing in the file LICENSE.LGPL included in the
00020 ** packaging of this file.  Please review the following information to
00021 ** ensure the GNU Lesser General Public License version 2.1 requirements
00022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00023 **
00024 ** In addition, as a special exception, Nokia gives you certain additional
00025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
00026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this module.
00027 **
00028 ** GNU General Public License Usage
00029 ** Alternatively, this file may be used under the terms of the GNU
00030 ** General Public License version 3.0 as published by the Free Software
00031 ** Foundation and appearing in the file LICENSE.GPL included in the
00032 ** packaging of this file.  Please review the following information to
00033 ** ensure the GNU General Public License version 3.0 requirements will be
00034 ** met: http://www.gnu.org/copyleft/gpl.html.
00035 **
00036 ** If you have questions regarding the use of this file, please contact
00037 ** Nokia at qt-info@nokia.com.
00038 ** $QT_END_LICENSE$
00039 **
00040 ****************************************************************************/
00041 
00042 #ifndef QMATRIX4X4_H
00043 #define QMATRIX4X4_H
00044 
00045 #include <QtGui/qvector3d.h>
00046 #include <QtGui/qvector4d.h>
00047 #include <QtGui/qquaternion.h>
00048 #include <QtGui/qgenericmatrix.h>
00049 #include <QtCore/qrect.h>
00050 
00051 QT_BEGIN_HEADER
00052 
00053 QT_BEGIN_NAMESPACE
00054 
00055 QT_MODULE(Gui)
00056 
00057 #ifndef QT_NO_MATRIX4X4
00058 
00059 class QMatrix;
00060 class QTransform;
00061 class QVariant;
00062 
00063 class Q_GUI_EXPORT QMatrix4x4
00064 {
00065 public:
00066     inline QMatrix4x4() { setToIdentity(); }
00067     explicit QMatrix4x4(const qreal *values);
00068     inline QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14,
00069                       qreal m21, qreal m22, qreal m23, qreal m24,
00070                       qreal m31, qreal m32, qreal m33, qreal m34,
00071                       qreal m41, qreal m42, qreal m43, qreal m44);
00072 #if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
00073     template <int N, int M>
00074     explicit QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix);
00075 #endif
00076     QMatrix4x4(const qreal *values, int cols, int rows);
00077     QMatrix4x4(const QTransform& transform);
00078     QMatrix4x4(const QMatrix& matrix);
00079 
00080     inline const qreal& operator()(int row, int column) const;
00081     inline qreal& operator()(int row, int column);
00082 
00083     inline QVector4D column(int index) const;
00084     inline void setColumn(int index, const QVector4D& value);
00085 
00086     inline QVector4D row(int index) const;
00087     inline void setRow(int index, const QVector4D& value);
00088 
00089     inline bool isIdentity() const;
00090     inline void setToIdentity();
00091 
00092     inline void fill(qreal value);
00093 
00094     qreal determinant() const;
00095     QMatrix4x4 inverted(bool *invertible = 0) const;
00096     QMatrix4x4 transposed() const;
00097     QMatrix3x3 normalMatrix() const;
00098 
00099     inline QMatrix4x4& operator+=(const QMatrix4x4& other);
00100     inline QMatrix4x4& operator-=(const QMatrix4x4& other);
00101     inline QMatrix4x4& operator*=(const QMatrix4x4& other);
00102     inline QMatrix4x4& operator*=(qreal factor);
00103     QMatrix4x4& operator/=(qreal divisor);
00104     inline bool operator==(const QMatrix4x4& other) const;
00105     inline bool operator!=(const QMatrix4x4& other) const;
00106 
00107     friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
00108     friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
00109     friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
00110 #ifndef QT_NO_VECTOR3D
00111     friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
00112     friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
00113 #endif
00114 #ifndef QT_NO_VECTOR4D
00115     friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
00116     friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
00117 #endif
00118     friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
00119     friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
00120     friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
00121     friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
00122     friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
00123     friend QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix);
00124     friend QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor);
00125     friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
00126 
00127     friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
00128 
00129 #ifndef QT_NO_VECTOR3D
00130     void scale(const QVector3D& vector);
00131     void translate(const QVector3D& vector);
00132     void rotate(qreal angle, const QVector3D& vector);
00133 #endif
00134     void scale(qreal x, qreal y);
00135     void scale(qreal x, qreal y, qreal z);
00136     void scale(qreal factor);
00137     void translate(qreal x, qreal y);
00138     void translate(qreal x, qreal y, qreal z);
00139     void rotate(qreal angle, qreal x, qreal y, qreal z = 0.0f);
00140 #ifndef QT_NO_QUATERNION
00141     void rotate(const QQuaternion& quaternion);
00142 #endif
00143 
00144     void ortho(const QRect& rect);
00145     void ortho(const QRectF& rect);
00146     void ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
00147     void frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
00148     void perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane);
00149 #ifndef QT_NO_VECTOR3D
00150     void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
00151 #endif
00152     void flipCoordinates();
00153 
00154     void copyDataTo(qreal *values) const;
00155 
00156     QMatrix toAffine() const;
00157     QTransform toTransform() const;
00158     QTransform toTransform(qreal distanceToPlane) const;
00159 
00160     QPoint map(const QPoint& point) const;
00161     QPointF map(const QPointF& point) const;
00162 #ifndef QT_NO_VECTOR3D
00163     QVector3D map(const QVector3D& point) const;
00164     QVector3D mapVector(const QVector3D& vector) const;
00165 #endif
00166 #ifndef QT_NO_VECTOR4D
00167     QVector4D map(const QVector4D& point) const;
00168 #endif
00169     QRect mapRect(const QRect& rect) const;
00170     QRectF mapRect(const QRectF& rect) const;
00171 
00172 #if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
00173     template <int N, int M>
00174     QGenericMatrix<N, M, qreal> toGenericMatrix() const;
00175 #endif
00176 
00177     inline qreal *data();
00178     inline const qreal *data() const { return m[0]; }
00179     inline const qreal *constData() const { return m[0]; }
00180 
00181     void optimize();
00182 
00183     operator QVariant() const;
00184 
00185 #ifndef QT_NO_DEBUG_STREAM
00186     friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
00187 #endif
00188 
00189 private:
00190     qreal m[4][4];          // Column-major order to match OpenGL.
00191     int flagBits;           // Flag bits from the enum below.
00192 
00193     enum {
00194         Identity        = 0x0001,   // Identity matrix
00195         General         = 0x0002,   // General matrix, unknown contents
00196         Translation     = 0x0004,   // Contains a simple translation
00197         Scale           = 0x0008,   // Contains a simple scale
00198         Rotation        = 0x0010    // Contains a simple rotation
00199     };
00200 
00201     // Construct without initializing identity matrix.
00202     QMatrix4x4(int) { flagBits = General; }
00203 
00204     QMatrix4x4 orthonormalInverse() const;
00205 
00206     void projectedRotate(qreal angle, qreal x, qreal y, qreal z);
00207 
00208     friend class QGraphicsRotation;
00209 };
00210 
00211 Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
00212 
00213 inline QMatrix4x4::QMatrix4x4
00214         (qreal m11, qreal m12, qreal m13, qreal m14,
00215          qreal m21, qreal m22, qreal m23, qreal m24,
00216          qreal m31, qreal m32, qreal m33, qreal m34,
00217          qreal m41, qreal m42, qreal m43, qreal m44)
00218 {
00219     m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
00220     m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
00221     m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
00222     m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
00223     flagBits = General;
00224 }
00225 
00226 #if !defined(QT_NO_MEMBER_TEMPLATES)
00227 
00228 template <int N, int M>
00229 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
00230     (const QGenericMatrix<N, M, qreal>& matrix)
00231 {
00232     const qreal *values = matrix.constData();
00233     for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
00234         for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
00235             if (matrixCol < N && matrixRow < M)
00236                 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
00237             else if (matrixCol == matrixRow)
00238                 m[matrixCol][matrixRow] = 1.0f;
00239             else
00240                 m[matrixCol][matrixRow] = 0.0f;
00241         }
00242     }
00243     flagBits = General;
00244 }
00245 
00246 template <int N, int M>
00247 QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const
00248 {
00249     QGenericMatrix<N, M, qreal> result;
00250     qreal *values = result.data();
00251     for (int matrixCol = 0; matrixCol < N; ++matrixCol) {
00252         for (int matrixRow = 0; matrixRow < M; ++matrixRow) {
00253             if (matrixCol < 4 && matrixRow < 4)
00254                 values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow];
00255             else if (matrixCol == matrixRow)
00256                 values[matrixCol * M + matrixRow] = 1.0f;
00257             else
00258                 values[matrixCol * M + matrixRow] = 0.0f;
00259         }
00260     }
00261     return result;
00262 }
00263 
00264 #endif
00265 
00266 inline const qreal& QMatrix4x4::operator()(int aRow, int aColumn) const
00267 {
00268     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
00269     return m[aColumn][aRow];
00270 }
00271 
00272 inline qreal& QMatrix4x4::operator()(int aRow, int aColumn)
00273 {
00274     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
00275     flagBits = General;
00276     return m[aColumn][aRow];
00277 }
00278 
00279 inline QVector4D QMatrix4x4::column(int index) const
00280 {
00281     Q_ASSERT(index >= 0 && index < 4);
00282     return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
00283 }
00284 
00285 inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
00286 {
00287     Q_ASSERT(index >= 0 && index < 4);
00288     m[index][0] = value.x();
00289     m[index][1] = value.y();
00290     m[index][2] = value.z();
00291     m[index][3] = value.w();
00292     flagBits = General;
00293 }
00294 
00295 inline QVector4D QMatrix4x4::row(int index) const
00296 {
00297     Q_ASSERT(index >= 0 && index < 4);
00298     return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
00299 }
00300 
00301 inline void QMatrix4x4::setRow(int index, const QVector4D& value)
00302 {
00303     Q_ASSERT(index >= 0 && index < 4);
00304     m[0][index] = value.x();
00305     m[1][index] = value.y();
00306     m[2][index] = value.z();
00307     m[3][index] = value.w();
00308     flagBits = General;
00309 }
00310 
00311 Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
00312 
00313 inline bool QMatrix4x4::isIdentity() const
00314 {
00315     if (flagBits == Identity)
00316         return true;
00317     if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
00318         return false;
00319     if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
00320         return false;
00321     if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
00322         return false;
00323     if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
00324         return false;
00325     if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
00326         return false;
00327     return (m[3][3] == 1.0f);
00328 }
00329 
00330 inline void QMatrix4x4::setToIdentity()
00331 {
00332     m[0][0] = 1.0f;
00333     m[0][1] = 0.0f;
00334     m[0][2] = 0.0f;
00335     m[0][3] = 0.0f;
00336     m[1][0] = 0.0f;
00337     m[1][1] = 1.0f;
00338     m[1][2] = 0.0f;
00339     m[1][3] = 0.0f;
00340     m[2][0] = 0.0f;
00341     m[2][1] = 0.0f;
00342     m[2][2] = 1.0f;
00343     m[2][3] = 0.0f;
00344     m[3][0] = 0.0f;
00345     m[3][1] = 0.0f;
00346     m[3][2] = 0.0f;
00347     m[3][3] = 1.0f;
00348     flagBits = Identity;
00349 }
00350 
00351 inline void QMatrix4x4::fill(qreal value)
00352 {
00353     m[0][0] = value;
00354     m[0][1] = value;
00355     m[0][2] = value;
00356     m[0][3] = value;
00357     m[1][0] = value;
00358     m[1][1] = value;
00359     m[1][2] = value;
00360     m[1][3] = value;
00361     m[2][0] = value;
00362     m[2][1] = value;
00363     m[2][2] = value;
00364     m[2][3] = value;
00365     m[3][0] = value;
00366     m[3][1] = value;
00367     m[3][2] = value;
00368     m[3][3] = value;
00369     flagBits = General;
00370 }
00371 
00372 inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
00373 {
00374     m[0][0] += other.m[0][0];
00375     m[0][1] += other.m[0][1];
00376     m[0][2] += other.m[0][2];
00377     m[0][3] += other.m[0][3];
00378     m[1][0] += other.m[1][0];
00379     m[1][1] += other.m[1][1];
00380     m[1][2] += other.m[1][2];
00381     m[1][3] += other.m[1][3];
00382     m[2][0] += other.m[2][0];
00383     m[2][1] += other.m[2][1];
00384     m[2][2] += other.m[2][2];
00385     m[2][3] += other.m[2][3];
00386     m[3][0] += other.m[3][0];
00387     m[3][1] += other.m[3][1];
00388     m[3][2] += other.m[3][2];
00389     m[3][3] += other.m[3][3];
00390     flagBits = General;
00391     return *this;
00392 }
00393 
00394 inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
00395 {
00396     m[0][0] -= other.m[0][0];
00397     m[0][1] -= other.m[0][1];
00398     m[0][2] -= other.m[0][2];
00399     m[0][3] -= other.m[0][3];
00400     m[1][0] -= other.m[1][0];
00401     m[1][1] -= other.m[1][1];
00402     m[1][2] -= other.m[1][2];
00403     m[1][3] -= other.m[1][3];
00404     m[2][0] -= other.m[2][0];
00405     m[2][1] -= other.m[2][1];
00406     m[2][2] -= other.m[2][2];
00407     m[2][3] -= other.m[2][3];
00408     m[3][0] -= other.m[3][0];
00409     m[3][1] -= other.m[3][1];
00410     m[3][2] -= other.m[3][2];
00411     m[3][3] -= other.m[3][3];
00412     flagBits = General;
00413     return *this;
00414 }
00415 
00416 inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
00417 {
00418     if (flagBits == Identity) {
00419         *this = other;
00420         return *this;
00421     } else if (other.flagBits == Identity) {
00422         return *this;
00423     } else {
00424         *this = *this * other;
00425         return *this;
00426     }
00427 }
00428 
00429 inline QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
00430 {
00431     m[0][0] *= factor;
00432     m[0][1] *= factor;
00433     m[0][2] *= factor;
00434     m[0][3] *= factor;
00435     m[1][0] *= factor;
00436     m[1][1] *= factor;
00437     m[1][2] *= factor;
00438     m[1][3] *= factor;
00439     m[2][0] *= factor;
00440     m[2][1] *= factor;
00441     m[2][2] *= factor;
00442     m[2][3] *= factor;
00443     m[3][0] *= factor;
00444     m[3][1] *= factor;
00445     m[3][2] *= factor;
00446     m[3][3] *= factor;
00447     flagBits = General;
00448     return *this;
00449 }
00450 
00451 inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
00452 {
00453     return m[0][0] == other.m[0][0] &&
00454            m[0][1] == other.m[0][1] &&
00455            m[0][2] == other.m[0][2] &&
00456            m[0][3] == other.m[0][3] &&
00457            m[1][0] == other.m[1][0] &&
00458            m[1][1] == other.m[1][1] &&
00459            m[1][2] == other.m[1][2] &&
00460            m[1][3] == other.m[1][3] &&
00461            m[2][0] == other.m[2][0] &&
00462            m[2][1] == other.m[2][1] &&
00463            m[2][2] == other.m[2][2] &&
00464            m[2][3] == other.m[2][3] &&
00465            m[3][0] == other.m[3][0] &&
00466            m[3][1] == other.m[3][1] &&
00467            m[3][2] == other.m[3][2] &&
00468            m[3][3] == other.m[3][3];
00469 }
00470 
00471 inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
00472 {
00473     return m[0][0] != other.m[0][0] ||
00474            m[0][1] != other.m[0][1] ||
00475            m[0][2] != other.m[0][2] ||
00476            m[0][3] != other.m[0][3] ||
00477            m[1][0] != other.m[1][0] ||
00478            m[1][1] != other.m[1][1] ||
00479            m[1][2] != other.m[1][2] ||
00480            m[1][3] != other.m[1][3] ||
00481            m[2][0] != other.m[2][0] ||
00482            m[2][1] != other.m[2][1] ||
00483            m[2][2] != other.m[2][2] ||
00484            m[2][3] != other.m[2][3] ||
00485            m[3][0] != other.m[3][0] ||
00486            m[3][1] != other.m[3][1] ||
00487            m[3][2] != other.m[3][2] ||
00488            m[3][3] != other.m[3][3];
00489 }
00490 
00491 inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
00492 {
00493     QMatrix4x4 m(1);
00494     m.m[0][0] = m1.m[0][0] + m2.m[0][0];
00495     m.m[0][1] = m1.m[0][1] + m2.m[0][1];
00496     m.m[0][2] = m1.m[0][2] + m2.m[0][2];
00497     m.m[0][3] = m1.m[0][3] + m2.m[0][3];
00498     m.m[1][0] = m1.m[1][0] + m2.m[1][0];
00499     m.m[1][1] = m1.m[1][1] + m2.m[1][1];
00500     m.m[1][2] = m1.m[1][2] + m2.m[1][2];
00501     m.m[1][3] = m1.m[1][3] + m2.m[1][3];
00502     m.m[2][0] = m1.m[2][0] + m2.m[2][0];
00503     m.m[2][1] = m1.m[2][1] + m2.m[2][1];
00504     m.m[2][2] = m1.m[2][2] + m2.m[2][2];
00505     m.m[2][3] = m1.m[2][3] + m2.m[2][3];
00506     m.m[3][0] = m1.m[3][0] + m2.m[3][0];
00507     m.m[3][1] = m1.m[3][1] + m2.m[3][1];
00508     m.m[3][2] = m1.m[3][2] + m2.m[3][2];
00509     m.m[3][3] = m1.m[3][3] + m2.m[3][3];
00510     return m;
00511 }
00512 
00513 inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
00514 {
00515     QMatrix4x4 m(1);
00516     m.m[0][0] = m1.m[0][0] - m2.m[0][0];
00517     m.m[0][1] = m1.m[0][1] - m2.m[0][1];
00518     m.m[0][2] = m1.m[0][2] - m2.m[0][2];
00519     m.m[0][3] = m1.m[0][3] - m2.m[0][3];
00520     m.m[1][0] = m1.m[1][0] - m2.m[1][0];
00521     m.m[1][1] = m1.m[1][1] - m2.m[1][1];
00522     m.m[1][2] = m1.m[1][2] - m2.m[1][2];
00523     m.m[1][3] = m1.m[1][3] - m2.m[1][3];
00524     m.m[2][0] = m1.m[2][0] - m2.m[2][0];
00525     m.m[2][1] = m1.m[2][1] - m2.m[2][1];
00526     m.m[2][2] = m1.m[2][2] - m2.m[2][2];
00527     m.m[2][3] = m1.m[2][3] - m2.m[2][3];
00528     m.m[3][0] = m1.m[3][0] - m2.m[3][0];
00529     m.m[3][1] = m1.m[3][1] - m2.m[3][1];
00530     m.m[3][2] = m1.m[3][2] - m2.m[3][2];
00531     m.m[3][3] = m1.m[3][3] - m2.m[3][3];
00532     return m;
00533 }
00534 
00535 inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
00536 {
00537     if (m1.flagBits == QMatrix4x4::Identity)
00538         return m2;
00539     else if (m2.flagBits == QMatrix4x4::Identity)
00540         return m1;
00541 
00542     QMatrix4x4 m(1);
00543     m.m[0][0] = m1.m[0][0] * m2.m[0][0] +
00544                 m1.m[1][0] * m2.m[0][1] +
00545                 m1.m[2][0] * m2.m[0][2] +
00546                 m1.m[3][0] * m2.m[0][3];
00547     m.m[0][1] = m1.m[0][1] * m2.m[0][0] +
00548                 m1.m[1][1] * m2.m[0][1] +
00549                 m1.m[2][1] * m2.m[0][2] +
00550                 m1.m[3][1] * m2.m[0][3];
00551     m.m[0][2] = m1.m[0][2] * m2.m[0][0] +
00552                 m1.m[1][2] * m2.m[0][1] +
00553                 m1.m[2][2] * m2.m[0][2] +
00554                 m1.m[3][2] * m2.m[0][3];
00555     m.m[0][3] = m1.m[0][3] * m2.m[0][0] +
00556                 m1.m[1][3] * m2.m[0][1] +
00557                 m1.m[2][3] * m2.m[0][2] +
00558                 m1.m[3][3] * m2.m[0][3];
00559     m.m[1][0] = m1.m[0][0] * m2.m[1][0] +
00560                 m1.m[1][0] * m2.m[1][1] +
00561                 m1.m[2][0] * m2.m[1][2] +
00562                 m1.m[3][0] * m2.m[1][3];
00563     m.m[1][1] = m1.m[0][1] * m2.m[1][0] +
00564                 m1.m[1][1] * m2.m[1][1] +
00565                 m1.m[2][1] * m2.m[1][2] +
00566                 m1.m[3][1] * m2.m[1][3];
00567     m.m[1][2] = m1.m[0][2] * m2.m[1][0] +
00568                 m1.m[1][2] * m2.m[1][1] +
00569                 m1.m[2][2] * m2.m[1][2] +
00570                 m1.m[3][2] * m2.m[1][3];
00571     m.m[1][3] = m1.m[0][3] * m2.m[1][0] +
00572                 m1.m[1][3] * m2.m[1][1] +
00573                 m1.m[2][3] * m2.m[1][2] +
00574                 m1.m[3][3] * m2.m[1][3];
00575     m.m[2][0] = m1.m[0][0] * m2.m[2][0] +
00576                 m1.m[1][0] * m2.m[2][1] +
00577                 m1.m[2][0] * m2.m[2][2] +
00578                 m1.m[3][0] * m2.m[2][3];
00579     m.m[2][1] = m1.m[0][1] * m2.m[2][0] +
00580                 m1.m[1][1] * m2.m[2][1] +
00581                 m1.m[2][1] * m2.m[2][2] +
00582                 m1.m[3][1] * m2.m[2][3];
00583     m.m[2][2] = m1.m[0][2] * m2.m[2][0] +
00584                 m1.m[1][2] * m2.m[2][1] +
00585                 m1.m[2][2] * m2.m[2][2] +
00586                 m1.m[3][2] * m2.m[2][3];
00587     m.m[2][3] = m1.m[0][3] * m2.m[2][0] +
00588                 m1.m[1][3] * m2.m[2][1] +
00589                 m1.m[2][3] * m2.m[2][2] +
00590                 m1.m[3][3] * m2.m[2][3];
00591     m.m[3][0] = m1.m[0][0] * m2.m[3][0] +
00592                 m1.m[1][0] * m2.m[3][1] +
00593                 m1.m[2][0] * m2.m[3][2] +
00594                 m1.m[3][0] * m2.m[3][3];
00595     m.m[3][1] = m1.m[0][1] * m2.m[3][0] +
00596                 m1.m[1][1] * m2.m[3][1] +
00597                 m1.m[2][1] * m2.m[3][2] +
00598                 m1.m[3][1] * m2.m[3][3];
00599     m.m[3][2] = m1.m[0][2] * m2.m[3][0] +
00600                 m1.m[1][2] * m2.m[3][1] +
00601                 m1.m[2][2] * m2.m[3][2] +
00602                 m1.m[3][2] * m2.m[3][3];
00603     m.m[3][3] = m1.m[0][3] * m2.m[3][0] +
00604                 m1.m[1][3] * m2.m[3][1] +
00605                 m1.m[2][3] * m2.m[3][2] +
00606                 m1.m[3][3] * m2.m[3][3];
00607     return m;
00608 }
00609 
00610 #ifndef QT_NO_VECTOR3D
00611 
00612 inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
00613 {
00614     qreal x, y, z, w;
00615     x = vector.x() * matrix.m[0][0] +
00616         vector.y() * matrix.m[0][1] +
00617         vector.z() * matrix.m[0][2] +
00618         matrix.m[0][3];
00619     y = vector.x() * matrix.m[1][0] +
00620         vector.y() * matrix.m[1][1] +
00621         vector.z() * matrix.m[1][2] +
00622         matrix.m[1][3];
00623     z = vector.x() * matrix.m[2][0] +
00624         vector.y() * matrix.m[2][1] +
00625         vector.z() * matrix.m[2][2] +
00626         matrix.m[2][3];
00627     w = vector.x() * matrix.m[3][0] +
00628         vector.y() * matrix.m[3][1] +
00629         vector.z() * matrix.m[3][2] +
00630         matrix.m[3][3];
00631     if (w == 1.0f)
00632         return QVector3D(x, y, z);
00633     else
00634         return QVector3D(x / w, y / w, z / w);
00635 }
00636 
00637 inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
00638 {
00639     qreal x, y, z, w;
00640     if (matrix.flagBits == QMatrix4x4::Identity) {
00641         return vector;
00642     } else if (matrix.flagBits == QMatrix4x4::Translation) {
00643         return QVector3D(vector.x() + matrix.m[3][0],
00644                          vector.y() + matrix.m[3][1],
00645                          vector.z() + matrix.m[3][2]);
00646     } else if (matrix.flagBits ==
00647                     (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
00648         return QVector3D(vector.x() * matrix.m[0][0] + matrix.m[3][0],
00649                          vector.y() * matrix.m[1][1] + matrix.m[3][1],
00650                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
00651     } else if (matrix.flagBits == QMatrix4x4::Scale) {
00652         return QVector3D(vector.x() * matrix.m[0][0],
00653                          vector.y() * matrix.m[1][1],
00654                          vector.z() * matrix.m[2][2]);
00655     } else {
00656         x = vector.x() * matrix.m[0][0] +
00657             vector.y() * matrix.m[1][0] +
00658             vector.z() * matrix.m[2][0] +
00659             matrix.m[3][0];
00660         y = vector.x() * matrix.m[0][1] +
00661             vector.y() * matrix.m[1][1] +
00662             vector.z() * matrix.m[2][1] +
00663             matrix.m[3][1];
00664         z = vector.x() * matrix.m[0][2] +
00665             vector.y() * matrix.m[1][2] +
00666             vector.z() * matrix.m[2][2] +
00667             matrix.m[3][2];
00668         w = vector.x() * matrix.m[0][3] +
00669             vector.y() * matrix.m[1][3] +
00670             vector.z() * matrix.m[2][3] +
00671             matrix.m[3][3];
00672         if (w == 1.0f)
00673             return QVector3D(x, y, z);
00674         else
00675             return QVector3D(x / w, y / w, z / w);
00676     }
00677 }
00678 
00679 #endif
00680 
00681 #ifndef QT_NO_VECTOR4D
00682 
00683 inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
00684 {
00685     qreal x, y, z, w;
00686     x = vector.x() * matrix.m[0][0] +
00687         vector.y() * matrix.m[0][1] +
00688         vector.z() * matrix.m[0][2] +
00689         vector.w() * matrix.m[0][3];
00690     y = vector.x() * matrix.m[1][0] +
00691         vector.y() * matrix.m[1][1] +
00692         vector.z() * matrix.m[1][2] +
00693         vector.w() * matrix.m[1][3];
00694     z = vector.x() * matrix.m[2][0] +
00695         vector.y() * matrix.m[2][1] +
00696         vector.z() * matrix.m[2][2] +
00697         vector.w() * matrix.m[2][3];
00698     w = vector.x() * matrix.m[3][0] +
00699         vector.y() * matrix.m[3][1] +
00700         vector.z() * matrix.m[3][2] +
00701         vector.w() * matrix.m[3][3];
00702     return QVector4D(x, y, z, w);
00703 }
00704 
00705 inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
00706 {
00707     qreal x, y, z, w;
00708     x = vector.x() * matrix.m[0][0] +
00709         vector.y() * matrix.m[1][0] +
00710         vector.z() * matrix.m[2][0] +
00711         vector.w() * matrix.m[3][0];
00712     y = vector.x() * matrix.m[0][1] +
00713         vector.y() * matrix.m[1][1] +
00714         vector.z() * matrix.m[2][1] +
00715         vector.w() * matrix.m[3][1];
00716     z = vector.x() * matrix.m[0][2] +
00717         vector.y() * matrix.m[1][2] +
00718         vector.z() * matrix.m[2][2] +
00719         vector.w() * matrix.m[3][2];
00720     w = vector.x() * matrix.m[0][3] +
00721         vector.y() * matrix.m[1][3] +
00722         vector.z() * matrix.m[2][3] +
00723         vector.w() * matrix.m[3][3];
00724     return QVector4D(x, y, z, w);
00725 }
00726 
00727 #endif
00728 
00729 inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
00730 {
00731     qreal xin, yin;
00732     qreal x, y, w;
00733     xin = point.x();
00734     yin = point.y();
00735     x = xin * matrix.m[0][0] +
00736         yin * matrix.m[0][1] +
00737         matrix.m[0][3];
00738     y = xin * matrix.m[1][0] +
00739         yin * matrix.m[1][1] +
00740         matrix.m[1][3];
00741     w = xin * matrix.m[3][0] +
00742         yin * matrix.m[3][1] +
00743         matrix.m[3][3];
00744     if (w == 1.0f)
00745         return QPoint(qRound(x), qRound(y));
00746     else
00747         return QPoint(qRound(x / w), qRound(y / w));
00748 }
00749 
00750 inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
00751 {
00752     qreal xin, yin;
00753     qreal x, y, w;
00754     xin = point.x();
00755     yin = point.y();
00756     x = xin * matrix.m[0][0] +
00757         yin * matrix.m[0][1] +
00758         matrix.m[0][3];
00759     y = xin * matrix.m[1][0] +
00760         yin * matrix.m[1][1] +
00761         matrix.m[1][3];
00762     w = xin * matrix.m[3][0] +
00763         yin * matrix.m[3][1] +
00764         matrix.m[3][3];
00765     if (w == 1.0f) {
00766         return QPointF(qreal(x), qreal(y));
00767     } else {
00768         return QPointF(qreal(x / w), qreal(y / w));
00769     }
00770 }
00771 
00772 inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
00773 {
00774     qreal xin, yin;
00775     qreal x, y, w;
00776     xin = point.x();
00777     yin = point.y();
00778     if (matrix.flagBits == QMatrix4x4::Identity) {
00779         return point;
00780     } else if (matrix.flagBits == QMatrix4x4::Translation) {
00781         return QPoint(qRound(xin + matrix.m[3][0]),
00782                       qRound(yin + matrix.m[3][1]));
00783     } else if (matrix.flagBits ==
00784                     (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
00785         return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
00786                       qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
00787     } else if (matrix.flagBits == QMatrix4x4::Scale) {
00788         return QPoint(qRound(xin * matrix.m[0][0]),
00789                       qRound(yin * matrix.m[1][1]));
00790     } else {
00791         x = xin * matrix.m[0][0] +
00792             yin * matrix.m[1][0] +
00793             matrix.m[3][0];
00794         y = xin * matrix.m[0][1] +
00795             yin * matrix.m[1][1] +
00796             matrix.m[3][1];
00797         w = xin * matrix.m[0][3] +
00798             yin * matrix.m[1][3] +
00799             matrix.m[3][3];
00800         if (w == 1.0f)
00801             return QPoint(qRound(x), qRound(y));
00802         else
00803             return QPoint(qRound(x / w), qRound(y / w));
00804     }
00805 }
00806 
00807 inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
00808 {
00809     qreal xin, yin;
00810     qreal x, y, w;
00811     xin = point.x();
00812     yin = point.y();
00813     if (matrix.flagBits == QMatrix4x4::Identity) {
00814         return point;
00815     } else if (matrix.flagBits == QMatrix4x4::Translation) {
00816         return QPointF(xin + matrix.m[3][0],
00817                        yin + matrix.m[3][1]);
00818     } else if (matrix.flagBits ==
00819                     (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
00820         return QPointF(xin * matrix.m[0][0] + matrix.m[3][0],
00821                        yin * matrix.m[1][1] + matrix.m[3][1]);
00822     } else if (matrix.flagBits == QMatrix4x4::Scale) {
00823         return QPointF(xin * matrix.m[0][0],
00824                        yin * matrix.m[1][1]);
00825     } else {
00826         x = xin * matrix.m[0][0] +
00827             yin * matrix.m[1][0] +
00828             matrix.m[3][0];
00829         y = xin * matrix.m[0][1] +
00830             yin * matrix.m[1][1] +
00831             matrix.m[3][1];
00832         w = xin * matrix.m[0][3] +
00833             yin * matrix.m[1][3] +
00834             matrix.m[3][3];
00835         if (w == 1.0f) {
00836             return QPointF(qreal(x), qreal(y));
00837         } else {
00838             return QPointF(qreal(x / w), qreal(y / w));
00839         }
00840     }
00841 }
00842 
00843 inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
00844 {
00845     QMatrix4x4 m(1);
00846     m.m[0][0] = -matrix.m[0][0];
00847     m.m[0][1] = -matrix.m[0][1];
00848     m.m[0][2] = -matrix.m[0][2];
00849     m.m[0][3] = -matrix.m[0][3];
00850     m.m[1][0] = -matrix.m[1][0];
00851     m.m[1][1] = -matrix.m[1][1];
00852     m.m[1][2] = -matrix.m[1][2];
00853     m.m[1][3] = -matrix.m[1][3];
00854     m.m[2][0] = -matrix.m[2][0];
00855     m.m[2][1] = -matrix.m[2][1];
00856     m.m[2][2] = -matrix.m[2][2];
00857     m.m[2][3] = -matrix.m[2][3];
00858     m.m[3][0] = -matrix.m[3][0];
00859     m.m[3][1] = -matrix.m[3][1];
00860     m.m[3][2] = -matrix.m[3][2];
00861     m.m[3][3] = -matrix.m[3][3];
00862     return m;
00863 }
00864 
00865 inline QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
00866 {
00867     QMatrix4x4 m(1);
00868     m.m[0][0] = matrix.m[0][0] * factor;
00869     m.m[0][1] = matrix.m[0][1] * factor;
00870     m.m[0][2] = matrix.m[0][2] * factor;
00871     m.m[0][3] = matrix.m[0][3] * factor;
00872     m.m[1][0] = matrix.m[1][0] * factor;
00873     m.m[1][1] = matrix.m[1][1] * factor;
00874     m.m[1][2] = matrix.m[1][2] * factor;
00875     m.m[1][3] = matrix.m[1][3] * factor;
00876     m.m[2][0] = matrix.m[2][0] * factor;
00877     m.m[2][1] = matrix.m[2][1] * factor;
00878     m.m[2][2] = matrix.m[2][2] * factor;
00879     m.m[2][3] = matrix.m[2][3] * factor;
00880     m.m[3][0] = matrix.m[3][0] * factor;
00881     m.m[3][1] = matrix.m[3][1] * factor;
00882     m.m[3][2] = matrix.m[3][2] * factor;
00883     m.m[3][3] = matrix.m[3][3] * factor;
00884     return m;
00885 }
00886 
00887 inline QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
00888 {
00889     QMatrix4x4 m(1);
00890     m.m[0][0] = matrix.m[0][0] * factor;
00891     m.m[0][1] = matrix.m[0][1] * factor;
00892     m.m[0][2] = matrix.m[0][2] * factor;
00893     m.m[0][3] = matrix.m[0][3] * factor;
00894     m.m[1][0] = matrix.m[1][0] * factor;
00895     m.m[1][1] = matrix.m[1][1] * factor;
00896     m.m[1][2] = matrix.m[1][2] * factor;
00897     m.m[1][3] = matrix.m[1][3] * factor;
00898     m.m[2][0] = matrix.m[2][0] * factor;
00899     m.m[2][1] = matrix.m[2][1] * factor;
00900     m.m[2][2] = matrix.m[2][2] * factor;
00901     m.m[2][3] = matrix.m[2][3] * factor;
00902     m.m[3][0] = matrix.m[3][0] * factor;
00903     m.m[3][1] = matrix.m[3][1] * factor;
00904     m.m[3][2] = matrix.m[3][2] * factor;
00905     m.m[3][3] = matrix.m[3][3] * factor;
00906     return m;
00907 }
00908 
00909 inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
00910 {
00911     return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
00912            qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
00913            qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
00914            qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
00915            qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
00916            qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
00917            qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
00918            qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
00919            qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
00920            qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
00921            qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
00922            qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
00923            qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
00924            qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
00925            qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
00926            qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
00927 }
00928 
00929 inline QPoint QMatrix4x4::map(const QPoint& point) const
00930 {
00931     return *this * point;
00932 }
00933 
00934 inline QPointF QMatrix4x4::map(const QPointF& point) const
00935 {
00936     return *this * point;
00937 }
00938 
00939 #ifndef QT_NO_VECTOR3D
00940 
00941 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
00942 {
00943     return *this * point;
00944 }
00945 
00946 inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
00947 {
00948     if (flagBits == Identity || flagBits == Translation) {
00949         return vector;
00950     } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
00951         return QVector3D(vector.x() * m[0][0],
00952                          vector.y() * m[1][1],
00953                          vector.z() * m[2][2]);
00954     } else {
00955         return QVector3D(vector.x() * m[0][0] +
00956                          vector.y() * m[1][0] +
00957                          vector.z() * m[2][0],
00958                          vector.x() * m[0][1] +
00959                          vector.y() * m[1][1] +
00960                          vector.z() * m[2][1],
00961                          vector.x() * m[0][2] +
00962                          vector.y() * m[1][2] +
00963                          vector.z() * m[2][2]);
00964     }
00965 }
00966 
00967 #endif
00968 
00969 #ifndef QT_NO_VECTOR4D
00970 
00971 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
00972 {
00973     return *this * point;
00974 }
00975 
00976 #endif
00977 
00978 inline qreal *QMatrix4x4::data()
00979 {
00980     // We have to assume that the caller will modify the matrix elements,
00981     // so we flip it over to "General" mode.
00982     flagBits = General;
00983     return m[0];
00984 }
00985 
00986 #ifndef QT_NO_DEBUG_STREAM
00987 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
00988 #endif
00989 
00990 #ifndef QT_NO_DATASTREAM
00991 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
00992 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
00993 #endif
00994 
00995 template <int N, int M>
00996 QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
00997 {
00998     return QMatrix4x4(matrix.constData(), N, M);
00999 }
01000 
01001 template <int N, int M>
01002 QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
01003 {
01004     QGenericMatrix<N, M, qreal> result;
01005     const qreal *m = matrix.constData();
01006     qreal *values = result.data();
01007     for (int col = 0; col < N; ++col) {
01008         for (int row = 0; row < M; ++row) {
01009             if (col < 4 && row < 4)
01010                 values[col * M + row] = m[col * 4 + row];
01011             else if (col == row)
01012                 values[col * M + row] = 1.0f;
01013             else
01014                 values[col * M + row] = 0.0f;
01015         }
01016     }
01017     return result;
01018 }
01019 
01020 #endif
01021 
01022 QT_END_NAMESPACE
01023 
01024 QT_END_HEADER
01025 
01026 #endif