From c65afcbd497a1060e42b0ecee3fe0f1c307307ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christian=20Str=C3=B8mme?= <christian.stromme@qt.io>
Date: Thu, 19 Mar 2020 17:13:41 +0100
Subject: [PATCH] Make the ray intersection functions free
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Makes it easier to test the function without messing with the objects
state.

Change-Id: I0487146e8285c54572fe878bd356613fd1155079
Reviewed-by: Antti Määttä <antti.maatta@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
---
 .../graphobjects/qssgrendercamera.cpp         |  2 +-
 src/runtimerender/qssgrenderray.cpp           | 24 ++++++++++---------
 src/runtimerender/qssgrenderray_p.h           |  8 ++++---
 .../rendererimpl/qssgrendererimpl.cpp         |  6 ++---
 4 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/runtimerender/graphobjects/qssgrendercamera.cpp b/src/runtimerender/graphobjects/qssgrendercamera.cpp
index 79fba09d2..41eb77115 100644
--- a/src/runtimerender/graphobjects/qssgrendercamera.cpp
+++ b/src/runtimerender/graphobjects/qssgrendercamera.cpp
@@ -242,7 +242,7 @@ QVector3D QSSGRenderCamera::unprojectToPosition(const QVector3D &inGlobalPos, co
     QVector3D theObjGlobalPos = inGlobalPos;
     float theDistance = -1.0f * QVector3D::dotProduct(theObjGlobalPos, theCameraDir);
     QSSGPlane theCameraPlane(theCameraDir, theDistance);
-    return inRay.intersect(theCameraPlane);
+    return QSSGRenderRay::intersect(theCameraPlane, inRay);
 }
 
 float QSSGRenderCamera::verticalFov(float aspectRatio) const
diff --git a/src/runtimerender/qssgrenderray.cpp b/src/runtimerender/qssgrenderray.cpp
index 0cd07408e..cb99418d8 100644
--- a/src/runtimerender/qssgrenderray.cpp
+++ b/src/runtimerender/qssgrenderray.cpp
@@ -37,18 +37,20 @@ QT_BEGIN_NAMESPACE
 
 // http://www.siggraph.org/education/materials/HyperGraph/raytrace/rayplane_intersection.htm
 
-QSSGOption<QVector3D> QSSGRenderRay::intersect(const QSSGPlane &inPlane) const
+QSSGOption<QVector3D> QSSGRenderRay::intersect(const QSSGPlane &inPlane, const QSSGRenderRay &ray)
 {
-    float Vd = QVector3D::dotProduct(inPlane.n, direction);
+    float Vd = QVector3D::dotProduct(inPlane.n, ray.direction);
     if (std::abs(Vd) < .0001f)
         return QSSGEmpty();
-    float V0 = -1.0f * (QVector3D::dotProduct(inPlane.n, origin) + inPlane.d);
+    float V0 = -1.0f * (QVector3D::dotProduct(inPlane.n, ray.origin) + inPlane.d);
     float t = V0 / Vd;
-    return origin + (direction * t);
+    return ray.origin + (ray.direction * t);
 }
 
-QSSGRenderRay::IntersectionResult QSSGRenderRay::intersectWithAABB(const QMatrix4x4 &inGlobalTransform, const QSSGBounds3 &inBounds,
-                                                                       bool inForceIntersect) const
+QSSGRenderRay::IntersectionResult QSSGRenderRay::intersectWithAABB(const QMatrix4x4 &inGlobalTransform,
+                                                                   const QSSGBounds3 &inBounds,
+                                                                   const QSSGRenderRay &ray,
+                                                                   bool inForceIntersect)
 {
     // Intersect the origin with the AABB described by bounds.
 
@@ -63,11 +65,11 @@ QSSGRenderRay::IntersectionResult QSSGRenderRay::intersectWithAABB(const QMatrix
     // Transform pick origin and direction into the subset's space.
     QMatrix4x4 theOriginTransform = inGlobalTransform.inverted();
 
-    QVector3D theTransformedOrigin = mat44::transform(theOriginTransform, origin);
+    QVector3D theTransformedOrigin = mat44::transform(theOriginTransform, ray.origin);
     float *outOriginTransformPtr(theOriginTransform.data());
     outOriginTransformPtr[12] = outOriginTransformPtr[13] = outOriginTransformPtr[14] = 0.0f;
 
-    QVector3D theTransformedDirection = mat44::rotate(theOriginTransform, direction);
+    QVector3D theTransformedDirection = mat44::rotate(theOriginTransform, ray.direction);
 
     static const float KD_FLT_MAX = 3.40282346638528860e+38;
     static const float kEpsilon = 1e-5f;
@@ -107,7 +109,7 @@ QSSGRenderRay::IntersectionResult QSSGRenderRay::intersectWithAABB(const QMatrix
     QVector3D scaledDir = theTransformedDirection * theMinWinner;
     QVector3D newPosInLocal = theTransformedOrigin + scaledDir;
     QVector3D newPosInGlobal = mat44::transform(inGlobalTransform, newPosInLocal);
-    QVector3D cameraToLocal = origin - newPosInGlobal;
+    QVector3D cameraToLocal = ray.origin - newPosInGlobal;
 
     float rayLengthSquared = vec3::magnitudeSquared(cameraToLocal);
 
@@ -154,8 +156,8 @@ QSSGOption<QVector2D> QSSGRenderRay::relative(const QMatrix4x4 &inGlobalTransfor
                                  ? QVector3D::dotProduct(theDirection, inBounds.maximum)
                                  : QVector3D::dotProduct(theDirection, inBounds.minimum));
 
-    QSSGRenderRay relativeRay(theTransformedOrigin, theTransformedDirection);
-    QSSGOption<QVector3D> localIsect = relativeRay.intersect(thePlane);
+    const QSSGRenderRay relativeRay(theTransformedOrigin, theTransformedDirection);
+    QSSGOption<QVector3D> localIsect = QSSGRenderRay::intersect(thePlane, relativeRay);
     if (localIsect.hasValue()) {
         float xRange = QVector3D::dotProduct(theRight, inBounds.maximum) - QVector3D::dotProduct(theRight, inBounds.minimum);
         float yRange = QVector3D::dotProduct(theUp, inBounds.maximum) - QVector3D::dotProduct(theUp, inBounds.minimum);
diff --git a/src/runtimerender/qssgrenderray_p.h b/src/runtimerender/qssgrenderray_p.h
index 3b8ebd130..6f915e1e2 100644
--- a/src/runtimerender/qssgrenderray_p.h
+++ b/src/runtimerender/qssgrenderray_p.h
@@ -68,7 +68,7 @@ struct QSSGRenderRay
     {
     }
     // If we are parallel, then no intersection of course.
-    QSSGOption<QVector3D> intersect(const QSSGPlane &inPlane) const;
+    static QSSGOption<QVector3D> intersect(const QSSGPlane &inPlane, const QSSGRenderRay &ray);
 
     struct IntersectionResult
     {
@@ -85,8 +85,10 @@ struct QSSGRenderRay
         {}
     };
 
-    IntersectionResult intersectWithAABB(const QMatrix4x4 &inGlobalTransform, const QSSGBounds3 &inBounds,
-                                         bool inForceIntersect = false) const;
+    static IntersectionResult intersectWithAABB(const QMatrix4x4 &inGlobalTransform,
+                                                const QSSGBounds3 &inBounds,
+                                                const QSSGRenderRay &ray,
+                                                bool inForceIntersect = false);
 
     QSSGOption<QVector2D> relative(const QMatrix4x4 &inGlobalTransform,
                                         const QSSGBounds3 &inBounds,
diff --git a/src/runtimerender/rendererimpl/qssgrendererimpl.cpp b/src/runtimerender/rendererimpl/qssgrendererimpl.cpp
index bee98d9c5..24c3ec447 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimpl.cpp
+++ b/src/runtimerender/rendererimpl/qssgrendererimpl.cpp
@@ -888,14 +888,14 @@ void QSSGRendererImpl::intersectRayWithSubsetRenderable(const QSSGRef<QSSGBuffer
     if (modelBounds.isEmpty())
         return;
 
-    QSSGRenderRay::IntersectionResult intersectionResult = inRay.intersectWithAABB(globalTransform, modelBounds);
+    QSSGRenderRay::IntersectionResult intersectionResult = QSSGRenderRay::intersectWithAABB(globalTransform, modelBounds, inRay);
 
     // If we don't intersect with the model at all, then there's no need to go furher down!
     if (!intersectionResult.intersects)
         return;
 
     for (const auto &subMesh : subMeshes) {
-        intersectionResult = inRay.intersectWithAABB(globalTransform, subMesh.bounds);
+        intersectionResult = QSSGRenderRay::intersectWithAABB(globalTransform, subMesh.bounds, inRay);
         if (intersectionResult.intersects)
             break;
     }
@@ -914,7 +914,7 @@ void QSSGRendererImpl::intersectRayWithSubsetRenderable(const QSSGRenderRay &inR
                                                         QSSGRenderableObject &inRenderableObject,
                                                         TPickResultArray &outIntersectionResultList)
 {
-    QSSGRenderRay::IntersectionResult intersectionResult = inRay.intersectWithAABB(inRenderableObject.globalTransform, inRenderableObject.bounds);
+    QSSGRenderRay::IntersectionResult intersectionResult = QSSGRenderRay::intersectWithAABB(inRenderableObject.globalTransform, inRenderableObject.bounds, inRay);
     if (!intersectionResult.intersects)
         return;
 
-- 
GitLab