1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#ifndef QSSG_RENDER_RAY_H
6#define QSSG_RENDER_RAY_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtQuick3DUtils/private/qssgbounds3_p.h>
20#include <QtQuick3DUtils/private/qssgplane_p.h>
21
22#include <QtGui/QVector2D>
23#include <QtGui/QVector3D>
24#include <QtGui/QMatrix4x4>
25
26#include <optional>
27
28QT_BEGIN_NAMESPACE
29struct QSSGMeshBVHNode;
30struct QSSGRenderMesh;
31struct QSSGMeshBVHTriangle;
32enum class QSSGRenderBasisPlanes
33{
34 XY,
35 YZ,
36 XZ,
37};
38
39struct Q_AUTOTEST_EXPORT QSSGRenderRay
40{
41 QVector3D origin;
42 QVector3D direction;
43 QSSGRenderRay() = default;
44 QSSGRenderRay(const QVector3D &inOrigin, const QVector3D &inDirection)
45 : origin(inOrigin), direction(inDirection)
46 {
47 }
48 // If we are parallel, then no intersection of course.
49 static std::optional<QVector3D> intersect(const QSSGPlane &inPlane, const QSSGRenderRay &ray);
50
51 // Perform an intersection aslo returning Barycentric Coordinates
52 static bool triangleIntersect(const QSSGRenderRay &ray,
53 const QVector3D &v0,
54 const QVector3D &v1,
55 const QVector3D &v2,
56 float &u,
57 float &v,
58 QVector3D &normal);
59
60 struct IntersectionResult
61 {
62 bool intersects = false;
63 float rayLengthSquared = 0.; // Length of the ray in world coordinates for the hit.
64 QVector2D relXY; // UV coords for further mouse picking against a offscreen-rendered object.
65 QVector3D scenePosition;
66 QVector3D localPosition;
67 QVector3D faceNormal;
68 IntersectionResult() = default;
69 inline constexpr IntersectionResult(float rl,
70 const QVector2D &relxy,
71 const QVector3D &scenePosition,
72 const QVector3D &localPosition,
73 const QVector3D &normal)
74 : intersects(true)
75 , rayLengthSquared(rl)
76 , relXY(relxy)
77 , scenePosition(scenePosition)
78 , localPosition(localPosition)
79 , faceNormal(normal)
80 {}
81 };
82
83 struct HitResult
84 {
85 float min;
86 float max;
87 const QSSGBounds3 *bounds;
88 inline bool intersects() const { return bounds && max >= std::max(a: min, b: 0.0f); }
89 };
90
91 struct RayData
92 {
93 enum class DirectionOp : quint8
94 {
95 Normal,
96 Swap,
97 Zero = 0x10
98 };
99
100 const QMatrix4x4 &globalTransform;
101 const QSSGRenderRay &ray;
102 // Cached data calculated from the global transform and the ray
103 const QVector3D origin;
104 const QVector3D directionInvers;
105 const QVector3D direction;
106 const DirectionOp dirOp[3];
107 };
108
109 static RayData createRayData(const QMatrix4x4 &globalTransform,
110 const QSSGRenderRay &ray);
111 static IntersectionResult createIntersectionResult(const RayData &data,
112 const HitResult &hit);
113
114 static HitResult intersectWithAABBv2(const RayData &data,
115 const QSSGBounds3 &bounds);
116
117 static void intersectWithBVH(const RayData &data,
118 const QSSGMeshBVHNode *bvh,
119 const QSSGRenderMesh *mesh,
120 QVector<IntersectionResult> &intersections,
121 int depth = 0);
122
123 static QVector<IntersectionResult> intersectWithBVHTriangles(const RayData &data,
124 const QVector<QSSGMeshBVHTriangle *> &bvhTriangles,
125 int triangleOffset,
126 int triangleCount);
127
128 std::optional<QVector2D> relative(const QMatrix4x4 &inGlobalTransform,
129 const QSSGBounds3 &inBounds,
130 QSSGRenderBasisPlanes inPlane) const;
131
132 std::optional<QVector2D> relativeXY(const QMatrix4x4 &inGlobalTransform, const QSSGBounds3 &inBounds) const
133 {
134 return relative(inGlobalTransform, inBounds, inPlane: QSSGRenderBasisPlanes::XY);
135 }
136};
137QT_END_NAMESPACE
138#endif
139

source code of qtquick3d/src/runtimerender/qssgrenderray_p.h