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