From 2dfdd7d0f937f2d3fe7cb5327ac199f701de7890 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 21 Sep 2009 11:30:06 +1000 Subject: Increase precision when normalizing vectors QVector3D::normalize() and other similar functions were losing precision when qreal was float, causing vectors with small lengths to normalize to (0, 0, 0). Do the length calculations with double precision to avoid this problem. Reviewed-by: Sarah Smith --- src/gui/math3d/qquaternion.cpp | 12 ++++++++++-- src/gui/math3d/qvector2d.cpp | 8 ++++++-- src/gui/math3d/qvector3d.cpp | 10 ++++++++-- src/gui/math3d/qvector4d.cpp | 12 ++++++++++-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index e48bced..d5ec054 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -239,7 +239,11 @@ qreal QQuaternion::lengthSquared() const */ QQuaternion QQuaternion::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -256,7 +260,11 @@ QQuaternion QQuaternion::normalized() const */ void QQuaternion::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index f12bec0..2555a6f 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -190,7 +190,9 @@ qreal QVector2D::lengthSquared() const */ QVector2D QVector2D::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -207,7 +209,9 @@ QVector2D QVector2D::normalized() const */ void QVector2D::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 7d4ddf7..9552e3a 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -205,7 +205,10 @@ QVector3D::QVector3D(const QVector4D& vector) */ QVector3D QVector3D::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -222,7 +225,10 @@ QVector3D QVector3D::normalized() const */ void QVector3D::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index 17acfff..1691a6d 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -255,7 +255,11 @@ qreal QVector4D::lengthSquared() const */ QVector4D QVector4D::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -272,7 +276,11 @@ QVector4D QVector4D::normalized() const */ void QVector4D::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; -- cgit v0.12