src/gui/math3d/qmatrix4x4.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
--- a/src/gui/math3d/qmatrix4x4.cpp	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/gui/math3d/qmatrix4x4.cpp	Tue Feb 02 00:43:10 2010 +0200
@@ -58,6 +58,8 @@
     \sa QVector3D, QGenericMatrix
 */
 
+static const qreal inv_dist_to_plane = 1. / 1024.;
+
 /*!
     \fn QMatrix4x4::QMatrix4x4()
 
@@ -71,10 +73,10 @@
 
     If the matrix has a special type (identity, translate, scale, etc),
     the programmer should follow this constructor with a call to
-    inferSpecialType() if they wish QMatrix4x4 to optimize further
+    optimize() if they wish QMatrix4x4 to optimize further
     calls to translate(), scale(), etc.
 
-    \sa toValueArray(), inferSpecialType()
+    \sa copyDataTo(), optimize()
 */
 QMatrix4x4::QMatrix4x4(const qreal *values)
 {
@@ -94,10 +96,10 @@
 
     If the matrix has a special type (identity, translate, scale, etc),
     the programmer should follow this constructor with a call to
-    inferSpecialType() if they wish QMatrix4x4 to optimize further
+    optimize() if they wish QMatrix4x4 to optimize further
     calls to translate(), scale(), etc.
 
-    \sa inferSpecialType()
+    \sa optimize()
 */
 
 #if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
@@ -174,10 +176,10 @@
 
     If \a matrix has a special type (identity, translate, scale, etc),
     the programmer should follow this constructor with a call to
-    inferSpecialType() if they wish QMatrix4x4 to optimize further
+    optimize() if they wish QMatrix4x4 to optimize further
     calls to translate(), scale(), etc.
 
-    \sa toAffine(), inferSpecialType()
+    \sa toAffine(), optimize()
 */
 QMatrix4x4::QMatrix4x4(const QMatrix& matrix)
 {
@@ -206,10 +208,10 @@
 
     If \a transform has a special type (identity, translate, scale, etc),
     the programmer should follow this constructor with a call to
-    inferSpecialType() if they wish QMatrix4x4 to optimize further
+    optimize() if they wish QMatrix4x4 to optimize further
     calls to translate(), scale(), etc.
 
-    \sa toTransform(), inferSpecialType()
+    \sa toTransform(), optimize()
 */
 QMatrix4x4::QMatrix4x4(const QTransform& transform)
 {
@@ -247,7 +249,7 @@
     Returns a reference to the element at position (\a row, \a column)
     in this matrix so that the element can be assigned to.
 
-    \sa inferSpecialType(), setColumn(), setRow()
+    \sa optimize(), setColumn(), setRow()
 */
 
 /*!
@@ -287,11 +289,11 @@
 
     Returns true if this matrix is the identity; false otherwise.
 
-    \sa setIdentity()
+    \sa setToIdentity()
 */
 
 /*!
-    \fn void QMatrix4x4::setIdentity()
+    \fn void QMatrix4x4::setToIdentity()
 
     Sets this matrix to the identity.
 
@@ -692,11 +694,11 @@
 
 /*!
     Multiplies this matrix by another that scales coordinates by
-    the components of \a vector.  Returns this matrix.
+    the components of \a vector.
 
     \sa translate(), rotate()
 */
-QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector)
+void QMatrix4x4::scale(const QVector3D& vector)
 {
     qreal vx = vector.x();
     qreal vy = vector.y();
@@ -730,7 +732,6 @@
         m[2][3] *= vz;
         flagBits = General;
     }
-    return *this;
 }
 #endif
 
@@ -738,11 +739,11 @@
     \overload
 
     Multiplies this matrix by another that scales coordinates by the
-    components \a x, and \a y.  Returns this matrix.
+    components \a x, and \a y.
 
     \sa translate(), rotate()
 */
-QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y)
+void QMatrix4x4::scale(qreal x, qreal y)
 {
     if (flagBits == Identity) {
         m[0][0] = x;
@@ -766,18 +767,17 @@
         m[1][3] *= y;
         flagBits = General;
     }
-    return *this;
 }
 
 /*!
     \overload
 
     Multiplies this matrix by another that scales coordinates by the
-    components \a x, \a y, and \a z.  Returns this matrix.
+    components \a x, \a y, and \a z.
 
     \sa translate(), rotate()
 */
-QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y, qreal z)
+void QMatrix4x4::scale(qreal x, qreal y, qreal z)
 {
     if (flagBits == Identity) {
         m[0][0] = x;
@@ -808,18 +808,17 @@
         m[2][3] *= z;
         flagBits = General;
     }
-    return *this;
 }
 
 /*!
     \overload
 
     Multiplies this matrix by another that scales coordinates by the
-    given \a factor.  Returns this matrix.
+    given \a factor.
 
     \sa translate(), rotate()
 */
-QMatrix4x4& QMatrix4x4::scale(qreal factor)
+void QMatrix4x4::scale(qreal factor)
 {
     if (flagBits == Identity) {
         m[0][0] = factor;
@@ -850,17 +849,16 @@
         m[2][3] *= factor;
         flagBits = General;
     }
-    return *this;
 }
 
 #ifndef QT_NO_VECTOR3D
 /*!
     Multiplies this matrix by another that translates coordinates by
-    the components of \a vector.  Returns this matrix.
+    the components of \a vector.
 
     \sa scale(), rotate()
 */
-QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector)
+void QMatrix4x4::translate(const QVector3D& vector)
 {
     qreal vx = vector.x();
     qreal vy = vector.y();
@@ -893,7 +891,6 @@
         else if (flagBits != (Rotation | Translation))
             flagBits = General;
     }
-    return *this;
 }
 
 #endif
@@ -902,11 +899,11 @@
     \overload
 
     Multiplies this matrix by another that translates coordinates
-    by the components \a x, and \a y.  Returns this matrix.
+    by the components \a x, and \a y.
 
     \sa scale(), rotate()
 */
-QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y)
+void QMatrix4x4::translate(qreal x, qreal y)
 {
     if (flagBits == Identity) {
         m[3][0] = x;
@@ -933,18 +930,17 @@
         else if (flagBits != (Rotation | Translation))
             flagBits = General;
     }
-    return *this;
 }
 
 /*!
     \overload
 
     Multiplies this matrix by another that translates coordinates
-    by the components \a x, \a y, and \a z.  Returns this matrix.
+    by the components \a x, \a y, and \a z.
 
     \sa scale(), rotate()
 */
-QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y, qreal z)
+void QMatrix4x4::translate(qreal x, qreal y, qreal z)
 {
     if (flagBits == Identity) {
         m[3][0] = x;
@@ -974,20 +970,19 @@
         else if (flagBits != (Rotation | Translation))
             flagBits = General;
     }
-    return *this;
 }
 
 #ifndef QT_NO_VECTOR3D
 
 /*!
     Multiples this matrix by another that rotates coordinates through
-    \a angle degrees about \a vector.  Returns this matrix.
+    \a angle degrees about \a vector.
 
     \sa scale(), translate()
 */
-QMatrix4x4& QMatrix4x4::rotate(qreal angle, const QVector3D& vector)
+void QMatrix4x4::rotate(qreal angle, const QVector3D& vector)
 {
-    return rotate(angle, vector.x(), vector.y(), vector.z());
+    rotate(angle, vector.x(), vector.y(), vector.z());
 }
 
 #endif
@@ -996,14 +991,14 @@
     \overload
 
     Multiplies this matrix by another that rotates coordinates through
-    \a angle degrees about the vector (\a x, \a y, \a z).  Returns this matrix.
+    \a angle degrees about the vector (\a x, \a y, \a z).
 
     \sa scale(), translate()
 */
-QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
+void QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
 {
     if (angle == 0.0f)
-        return *this;
+        return;
     QMatrix4x4 m(1); // The "1" says to not load the identity.
     qreal c, s, ic;
     if (angle == 90.0f || angle == -270.0f) {
@@ -1025,7 +1020,7 @@
         if (y == 0.0f) {
             if (z != 0.0f) {
                 // Rotate around the Z axis.
-                m.setIdentity();
+                m.setToIdentity();
                 m.m[0][0] = c;
                 m.m[1][1] = c;
                 if (z < 0.0f) {
@@ -1040,7 +1035,7 @@
             }
         } else if (z == 0.0f) {
             // Rotate around the Y axis.
-            m.setIdentity();
+            m.setToIdentity();
             m.m[0][0] = c;
             m.m[2][2] = c;
             if (y < 0.0f) {
@@ -1055,7 +1050,7 @@
         }
     } else if (y == 0.0f && z == 0.0f) {
         // Rotate around the X axis.
-        m.setIdentity();
+        m.setToIdentity();
         m.m[1][1] = c;
         m.m[2][2] = c;
         if (x < 0.0f) {
@@ -1100,19 +1095,121 @@
         flagBits = flags | Rotation;
     else
         flagBits = Rotation;
-    return *this;
 }
 
-#ifndef QT_NO_VECTOR4D
+/*!
+    \internal
+*/
+void QMatrix4x4::projectedRotate(qreal angle, qreal x, qreal y, qreal z)
+{
+    // Used by QGraphicsRotation::applyTo() to perform a rotation
+    // and projection back to 2D in a single step.
+    if (angle == 0.0f)
+        return;
+    QMatrix4x4 m(1); // The "1" says to not load the identity.
+    qreal c, s, ic;
+    if (angle == 90.0f || angle == -270.0f) {
+        s = 1.0f;
+        c = 0.0f;
+    } else if (angle == -90.0f || angle == 270.0f) {
+        s = -1.0f;
+        c = 0.0f;
+    } else if (angle == 180.0f || angle == -180.0f) {
+        s = 0.0f;
+        c = -1.0f;
+    } else {
+        qreal a = angle * M_PI / 180.0f;
+        c = qCos(a);
+        s = qSin(a);
+    }
+    bool quick = false;
+    if (x == 0.0f) {
+        if (y == 0.0f) {
+            if (z != 0.0f) {
+                // Rotate around the Z axis.
+                m.setToIdentity();
+                m.m[0][0] = c;
+                m.m[1][1] = c;
+                if (z < 0.0f) {
+                    m.m[1][0] = s;
+                    m.m[0][1] = -s;
+                } else {
+                    m.m[1][0] = -s;
+                    m.m[0][1] = s;
+                }
+                m.flagBits = General;
+                quick = true;
+            }
+        } else if (z == 0.0f) {
+            // Rotate around the Y axis.
+            m.setToIdentity();
+            m.m[0][0] = c;
+            m.m[2][2] = 1.0f;
+            if (y < 0.0f) {
+                m.m[0][3] = -s * inv_dist_to_plane;
+            } else {
+                m.m[0][3] = s * inv_dist_to_plane;
+            }
+            m.flagBits = General;
+            quick = true;
+        }
+    } else if (y == 0.0f && z == 0.0f) {
+        // Rotate around the X axis.
+        m.setToIdentity();
+        m.m[1][1] = c;
+        m.m[2][2] = 1.0f;
+        if (x < 0.0f) {
+            m.m[1][3] = s * inv_dist_to_plane;
+        } else {
+            m.m[1][3] = -s * inv_dist_to_plane;
+        }
+        m.flagBits = General;
+        quick = true;
+    }
+    if (!quick) {
+        qreal len = x * x + y * y + z * z;
+        if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
+            len = qSqrt(len);
+            x /= len;
+            y /= len;
+            z /= len;
+        }
+        ic = 1.0f - c;
+        m.m[0][0] = x * x * ic + c;
+        m.m[1][0] = x * y * ic - z * s;
+        m.m[2][0] = 0.0f;
+        m.m[3][0] = 0.0f;
+        m.m[0][1] = y * x * ic + z * s;
+        m.m[1][1] = y * y * ic + c;
+        m.m[2][1] = 0.0f;
+        m.m[3][1] = 0.0f;
+        m.m[0][2] = 0.0f;
+        m.m[1][2] = 0.0f;
+        m.m[2][2] = 1.0f;
+        m.m[3][2] = 0.0f;
+        m.m[0][3] = (x * z * ic - y * s) * -inv_dist_to_plane;
+        m.m[1][3] = (y * z * ic + x * s) * -inv_dist_to_plane;
+        m.m[2][3] = 0.0f;
+        m.m[3][3] = 1.0f;
+    }
+    int flags = flagBits;
+    *this *= m;
+    if (flags != Identity)
+        flagBits = flags | Rotation;
+    else
+        flagBits = Rotation;
+}
+
+#ifndef QT_NO_QUATERNION
 
 /*!
     Multiples this matrix by another that rotates coordinates according
     to a specified \a quaternion.  The \a quaternion is assumed to have
-    been normalized.  Returns this matrix.
+    been normalized.
 
     \sa scale(), translate(), QQuaternion
 */
-QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion)
+void QMatrix4x4::rotate(const QQuaternion& quaternion)
 {
     // Algorithm from:
     // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
@@ -1148,7 +1245,6 @@
         flagBits = flags | Rotation;
     else
         flagBits = Rotation;
-    return *this;
 }
 
 #endif
@@ -1159,17 +1255,16 @@
     Multiplies this matrix by another that applies an orthographic
     projection for a window with boundaries specified by \a rect.
     The near and far clipping planes will be -1 and 1 respectively.
-    Returns this matrix.
 
     \sa frustum(), perspective()
 */
-QMatrix4x4& QMatrix4x4::ortho(const QRect& rect)
+void QMatrix4x4::ortho(const QRect& rect)
 {
     // Note: rect.right() and rect.bottom() subtract 1 in QRect,
     // which gives the location of a pixel within the rectangle,
     // instead of the extent of the rectangle.  We want the extent.
     // QRectF expresses the extent properly.
-    return ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
+    ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
 }
 
 /*!
@@ -1178,28 +1273,27 @@
     Multiplies this matrix by another that applies an orthographic
     projection for a window with boundaries specified by \a rect.
     The near and far clipping planes will be -1 and 1 respectively.
-    Returns this matrix.
 
     \sa frustum(), perspective()
 */
-QMatrix4x4& QMatrix4x4::ortho(const QRectF& rect)
+void QMatrix4x4::ortho(const QRectF& rect)
 {
-    return ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
+    ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
 }
 
 /*!
     Multiplies this matrix by another that applies an orthographic
     projection for a window with lower-left corner (\a left, \a bottom),
     upper-right corner (\a right, \a top), and the specified \a nearPlane
-    and \a farPlane clipping planes.  Returns this matrix.
+    and \a farPlane clipping planes.
 
     \sa frustum(), perspective()
 */
-QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+void QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
 {
     // Bail out if the projection volume is zero-sized.
     if (left == right || bottom == top || nearPlane == farPlane)
-        return *this;
+        return;
 
     // Construct the projection.
     qreal width = right - left;
@@ -1218,7 +1312,7 @@
             (2.0f / width,
              2.0f / invheight,
              -1.0f));
-        return *this;
+        return;
     }
 #endif
     QMatrix4x4 m(1);
@@ -1241,22 +1335,22 @@
 
     // Apply the projection.
     *this *= m;
-    return *this;
+    return;
 }
 
 /*!
     Multiplies this matrix by another that applies a perspective
     frustum projection for a window with lower-left corner (\a left, \a bottom),
     upper-right corner (\a right, \a top), and the specified \a nearPlane
-    and \a farPlane clipping planes.  Returns this matrix.
+    and \a farPlane clipping planes.
 
     \sa ortho(), perspective()
 */
-QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+void QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
 {
     // Bail out if the projection volume is zero-sized.
     if (left == right || bottom == top || nearPlane == farPlane)
-        return *this;
+        return;
 
     // Construct the projection.
     QMatrix4x4 m(1);
@@ -1282,7 +1376,6 @@
 
     // Apply the projection.
     *this *= m;
-    return *this;
 }
 
 /*!
@@ -1290,22 +1383,21 @@
     projection.  The field of view will be \a angle degrees within
     a window with a given \a aspect ratio.  The projection will
     have the specified \a nearPlane and \a farPlane clipping planes.
-    Returns this matrix.
 
     \sa ortho(), frustum()
 */
-QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
+void QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
 {
     // Bail out if the projection volume is zero-sized.
     if (nearPlane == farPlane || aspect == 0.0f)
-        return *this;
+        return;
 
     // Construct the projection.
     QMatrix4x4 m(1);
     qreal radians = (angle / 2.0f) * M_PI / 180.0f;
     qreal sine = qSin(radians);
     if (sine == 0.0f)
-        return *this;
+        return;
     qreal cotan = qCos(radians) / sine;
     qreal clip = farPlane - nearPlane;
     m.m[0][0] = cotan / aspect;
@@ -1327,7 +1419,6 @@
 
     // Apply the projection.
     *this *= m;
-    return *this;
 }
 
 #ifndef QT_NO_VECTOR3D
@@ -1337,9 +1428,8 @@
     transformation.  The \a center value indicates the center of the
     view that the \a eye is looking at.  The \a up value indicates
     which direction should be considered up with respect to the \a eye.
-    Returns this matrix.
 */
-QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
+void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
 {
     QVector3D forward = (center - eye).normalized();
     QVector3D side = QVector3D::crossProduct(forward, up).normalized();
@@ -1365,7 +1455,7 @@
     m.m[3][3] = 1.0f;
 
     *this *= m;
-    return translate(-eye);
+    translate(-eye);
 }
 
 #endif
@@ -1374,11 +1464,11 @@
     Flips between right-handed and left-handed coordinate systems
     by multiplying the y and z co-ordinates by -1.  This is normally
     used to create a left-handed orthographic view without scaling
-    the viewport as ortho() does.  Returns this matrix.
+    the viewport as ortho() does.
 
     \sa ortho()
 */
-QMatrix4x4& QMatrix4x4::flipCoordinates()
+void QMatrix4x4::flipCoordinates()
 {
     if (flagBits == Scale || flagBits == (Scale | Translation)) {
         m[1][1] = -m[1][1];
@@ -1402,14 +1492,13 @@
         m[2][3] = -m[2][3];
         flagBits = General;
     }
-    return *this;
 }
 
 /*!
-    Retrieves the 16 items in this matrix and writes them to \a values
+    Retrieves the 16 items in this matrix and copies them to \a values
     in row-major order.
 */
-void QMatrix4x4::toValueArray(qreal *values) const
+void QMatrix4x4::copyDataTo(qreal *values) const
 {
     for (int row = 0; row < 4; ++row)
         for (int col = 0; col < 4; ++col)
@@ -1430,15 +1519,31 @@
                    m[3][0], m[3][1]);
 }
 
-static const qreal inv_dist_to_plane = 1. / 1024.;
+/*!
+    Returns the conventional Qt 2D transformation matrix that
+    corresponds to this matrix.
+
+    The returned QTransform is formed by simply dropping the
+    third row and third column of the QMatrix4x4.  This is suitable
+    for implementing orthographic projections where the z co-ordinate
+    should be dropped rather than projected.
+
+    \sa toAffine()
+*/
+QTransform QMatrix4x4::toTransform() const
+{
+    return QTransform(m[0][0], m[0][1], m[0][3],
+                      m[1][0], m[1][1], m[1][3],
+                      m[3][0], m[3][1], m[3][3]);
+}
 
 /*!
     Returns the conventional Qt 2D transformation matrix that
     corresponds to this matrix.
 
     If \a distanceToPlane is non-zero, it indicates a projection
-    factor to use to adjust for the z co-ordinate.  The default
-    value of 1024 corresponds to the projection factor used
+    factor to use to adjust for the z co-ordinate.  The value of
+    1024 corresponds to the projection factor used
     by QTransform::rotate() for the x and y axes.
 
     If \a distanceToPlane is zero, then the returned QTransform
@@ -1617,7 +1722,7 @@
 
     Returns a pointer to the raw data of this matrix.
 
-    \sa constData(), inferSpecialType()
+    \sa constData(), optimize()
 */
 
 /*!
@@ -1666,94 +1771,8 @@
     return result;
 }
 
-#ifndef QT_NO_VECTOR3D
 /*!
-    Decomposes the current rotation matrix into an \a axis of rotation plus
-    an \a angle.  The result can be used to construct an equivalent rotation
-    matrix using glRotate().  It is assumed that the homogenous coordinate
-    is 1.0.  The returned vector is guaranteed to be normalized.
-
-    \code
-        qreal angle;
-        QVector3D axis;
-
-        matrix.extractAxisAngle(angle, axis);
-        glRotate(angle, axis[0], axis[1], axis[2]);
-    \endcode
-
-    \sa rotate()
-*/
-void QMatrix4x4::extractAxisRotation(qreal &angle, QVector3D &axis) const
-{
-    // Orientation is dependent on the upper 3x3 matrix; subtract the
-    // homogeneous scaling element from the trace of the 4x4 matrix
-    qreal tr = m[0][0] + m[1][1] + m[2][2];
-    qreal cosa = qreal(0.5f * (tr - 1.0f));
-    angle = acos(cosa) * 180.0f / M_PI;
-
-    // Any axis will work if r is zero (means no rotation)
-    if (qFuzzyIsNull(angle)) {
-        axis.setX(1.0f);
-        axis.setY(0.0f);
-        axis.setZ(0.0f);
-        return;
-    }
-
-    if (angle < 180.0f) {
-        axis.setX(m[1][2] - m[2][1]);
-        axis.setY(m[2][0] - m[0][2]);
-        axis.setZ(m[0][1] - m[1][0]);
-        axis.normalize();
-        return;
-    }
-
-    // rads == PI
-    qreal tmp;
-
-    // r00 is maximum
-    if ((m[0][0] >= m[2][2]) && (m[0][0] >= m[1][1])) {
-        axis.setX(0.5f * qSqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f));
-        tmp = 0.5f / axis.x();
-        axis.setY(m[1][0] * tmp);
-        axis.setZ(m[2][0] * tmp);
-    }
-
-    // r11 is maximum
-    if ((m[1][1] >= m[2][2]) && (m[1][1] >= m[0][0])) {
-        axis.setY(0.5f * qSqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f));
-        tmp = 0.5f / axis.y();
-        axis.setX(tmp * m[1][0]);
-        axis.setZ(tmp * m[2][1]);
-    }
-
-    // r22 is maximum
-    if ((m[2][2] >= m[1][1]) && (m[2][2] >= m[0][0])) {
-        axis.setZ(0.5f * qSqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f));
-        tmp = 0.5f / axis.z();
-        axis.setX(m[2][0]*tmp);
-        axis.setY(m[2][1]*tmp);
-    }
-}
-
-/*!
-    If this is an orthonormal transformation matrix (e.g. only rotations and
-    translations have been applied to the matrix, no scaling, or shearing)
-    then the world translational component can be obtained by calling this function.
-
-    This is most useful for camera matrices, where the negation of this vector
-    is effectively the camera world coordinates.
-*/
-QVector3D QMatrix4x4::extractTranslation() const
-{
-    return QVector3D
-        (m[0][0] * m[3][0] + m[0][1] * m[3][1] + m[0][2] * m[3][2],
-         m[1][0] * m[3][0] + m[1][1] * m[3][1] + m[1][2] * m[3][2],
-         m[2][0] * m[3][0] + m[2][1] * m[3][1] + m[2][2] * m[3][2]);
-}
-#endif
-
-/*!
-    Infers the special type of this matrix from its current elements.
+    Optimize the usage of this matrix from its current elements.
 
     Some operations such as translate(), scale(), and rotate() can be
     performed more efficiently if the matrix being modified is already
@@ -1766,13 +1785,13 @@
     the special type and will revert to the safest but least efficient
     operations thereafter.
 
-    By calling inferSpecialType() after directly modifying the matrix,
+    By calling optimize() after directly modifying the matrix,
     the programmer can force QMatrix4x4 to recover the special type if
     the elements appear to conform to one of the known optimized types.
 
     \sa operator()(), data(), translate()
 */
-void QMatrix4x4::inferSpecialType()
+void QMatrix4x4::optimize()
 {
     // If the last element is not 1, then it can never be special.
     if (m[3][3] != 1.0f) {
@@ -1889,7 +1908,7 @@
             matrix(row, col) = qreal(x);
         }
     }
-    matrix.inferSpecialType();
+    matrix.optimize();
     return stream;
 }