1/****************************************************************************
2**
3** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the Qt3D module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include <Qt3DRender/private/qray3d_p.h>
42#include <QtCore/qdebug.h>
43
44QT_BEGIN_NAMESPACE
45
46namespace Qt3DRender {
47namespace RayCasting {
48
49/*!
50 \namespace Qt3DRender::RayCasting
51 \internal
52*/
53
54/*!
55 \internal
56 \class Qt3DRender::RayCasting::QRay3D
57 \inmodule Qt3DRender
58 \brief The QRay3D class defines a directional line in 3D space extending through an origin point.
59 \since 5.5
60 \ingroup qt3d
61 \ingroup qt3d::math
62
63 A ray is defined by the origin() point and the direction() vector.
64 Rays are infinite in length, extending out from origin() in
65 both directions. If the direction() is zero length, then the
66 behavior of the class is undefined.
67
68 A ray can be thought of as a one-dimensional co-ordinate system.
69 If the co-ordinate is \b t then the origin() point is at
70 \b t = 0, the point origin() + direction() is at \b t = 1,
71 and the point origin() - direction() is at \b t = -1.
72 The point() method can be used to obtain the position of a point
73 within this one-dimensional co-ordinate system. The projectedDistance()
74 method can be used to convert a point into a value in this
75 one-dimensional co-ordinate system.
76*/
77
78/*!
79 \fn Qt3DRender::RayCasting::QRay3D::QRay3D()
80
81 Construct a default ray with an origin() of (0, 0, 0), a
82 direction() of (0, 0, 1) and a distance of 1.
83*/
84QRay3D::QRay3D()
85 : m_direction(0.0f, 0.0f, 1.0f)
86 , m_distance(1.0f)
87{
88}
89
90/*!
91 \fn Qt3DRender::RayCasting::QRay3D::QRay3D(const Vector3D &origin, const Vector3D &direction, float distance)
92
93 Construct a ray given its defining \a origin, \a direction and \a distance.
94 The \a direction does not need to be normalized.
95
96 To construct a ray that passes through two points, use the following:
97
98 \code
99 QRay3D thruAB(pointA, pointB - pointA);
100 \endcode
101*/
102QRay3D::QRay3D(const Vector3D &origin, const Vector3D &direction, float distance)
103 : m_origin(origin)
104 , m_direction(direction.normalized())
105 , m_distance(distance)
106{}
107
108QRay3D::~QRay3D()
109{
110}
111
112/*!
113 \fn QVector3D Qt3DRender::RayCasting::QRay3D::origin() const
114
115 Returns the origin of this ray. The default value is (0, 0, 0).
116
117 \sa setOrigin(), direction()
118*/
119Vector3D QRay3D::origin() const
120{
121 return m_origin;
122}
123
124/*!
125 \fn void Qt3DRender::RayCasting::QRay3D::setOrigin(const Vector3D &value)
126
127 Sets the origin point of this ray to \a value.
128
129 \sa origin(), setDirection()
130 */
131void QRay3D::setOrigin(const Vector3D &value)
132{
133 m_origin = value;
134}
135
136/*!
137 \fn QVector3D Qt3DRender::RayCasting::QRay3D::direction() const
138
139 Returns the direction vector of this ray. The default value is (0, 0, 1).
140
141 \sa setDirection(), origin()
142*/
143Vector3D QRay3D::direction() const
144{
145 return m_direction;
146}
147
148/*!
149 \fn void Qt3DRender::RayCasting::QRay3D::setDirection(const Vector3D &direction)
150
151 Sets the direction vector of this ray to \a direction.
152
153 \sa direction(), setOrigin()
154*/
155void QRay3D::setDirection(const Vector3D &value)
156{
157 if (value.isNull())
158 return;
159
160 m_direction = value.normalized();
161}
162
163float QRay3D::distance() const
164{
165 return m_distance;
166}
167
168void QRay3D::setDistance(float distance)
169{
170 m_distance = distance;
171}
172
173Vector3D QRay3D::point(float t) const
174{
175 return m_origin + t * m_direction;
176}
177
178QRay3D &QRay3D::transform(const Matrix4x4 &matrix)
179{
180 m_origin = matrix * m_origin;
181 m_direction = matrix.mapVector(vector: m_direction).normalized();
182
183 return *this;
184}
185
186QRay3D QRay3D::transformed(const Matrix4x4 &matrix) const
187{
188 return QRay3D(matrix * m_origin, matrix.mapVector(vector: m_direction).normalized());
189}
190
191bool QRay3D::operator==(const QRay3D &other) const
192{
193 return m_origin == other.origin() && m_direction == other.direction();
194}
195
196bool QRay3D::operator!=(const QRay3D &other) const
197{
198 return !(*this == other);
199}
200
201/*!
202 Returns \c true if \a point lies on this ray; \c false otherwise.
203*/
204bool QRay3D::contains(const Vector3D &point) const
205{
206 Vector3D ppVec(point - m_origin);
207 if (ppVec.isNull()) // point coincides with origin
208 return true;
209 const float dot = Vector3D ::dotProduct(a: ppVec, b: m_direction);
210 if (qFuzzyIsNull(f: dot))
211 return false;
212 return qFuzzyCompare(p1: dot*dot, p2: ppVec.lengthSquared() * m_direction.lengthSquared());
213}
214
215/*!
216 Returns \c true if \a ray lies on this ray; \c false otherwise. If true,
217 this implies that the two rays are actually the same, but with
218 different origin() points or an inverted direction().
219*/
220bool QRay3D::contains(const QRay3D &ray) const
221{
222 const float dot = Vector3D ::dotProduct(a: m_direction, b: ray.direction());
223 if (!qFuzzyCompare(p1: dot*dot, p2: m_direction.lengthSquared() * ray.direction().lengthSquared()))
224 return false;
225 return contains(point: ray.origin());
226}
227
228/*!
229 \fn QVector3D Qt3DRender::RayCasting::QRay3D::point(float t) const
230
231 Returns the point on the ray defined by moving \a t units
232 along the ray in the direction of the direction() vector.
233 Note that \a t may be negative in which case the point returned
234 will lie behind the origin() point with respect to the
235 direction() vector.
236
237 The units for \a t are defined by direction(). The return value
238 is precisely origin() + t * direction().
239
240 \sa projectedDistance(), distance()
241*/
242
243/*!
244 Returns the number of direction() units along the ray from origin()
245 to \a point. Essentially, this function computes the value t, where
246 \a point = origin() + t * direction(). If \a point is not on the ray,
247 then the closest point that is on the ray will be used instead.
248
249 If the return value is positive, then \a point lies in front of
250 the origin() with respect to the direction() vector. If the return
251 value is negative, then \a point lies behind the origin() with
252 respect to the direction() vector.
253
254 \sa point(), project()
255*/
256float QRay3D::projectedDistance(const Vector3D &point) const
257{
258 Q_ASSERT(!m_direction.isNull());
259
260 return Vector3D ::dotProduct(a: point - m_origin, b: m_direction) /
261 m_direction.lengthSquared();
262}
263
264/*!
265 Returns the projection of \a vector onto this ray. In the
266 following diagram, the dotted line is the ray, and V is the
267 \a vector. The return value will be the vector V':
268
269 \image qray3d-project.png
270
271 \sa projectedDistance()
272*/
273Vector3D QRay3D::project(const Vector3D &vector) const
274{
275 Vector3D norm = m_direction.normalized();
276 return Vector3D ::dotProduct(a: vector, b: norm) * norm;
277}
278
279/*!
280 Returns the minimum distance from this ray to \a point, or equivalently
281 the length of a line perpendicular to this ray which passes through
282 \a point. If \a point is on the ray, then this function will return zero.
283
284 \sa point()
285*/
286float QRay3D::distance(const Vector3D &point) const
287{
288 float t = projectedDistance(point);
289 return (point - (m_origin + t * m_direction)).length();
290}
291
292/*!
293 \fn Qt3DRender::RayCasting::QRay3D &Qt3DRender::RayCasting::QRay3D::transform(const Matrix4x4 &matrix)
294
295 Transforms this ray using \a matrix, replacing origin() and
296 direction() with the transformed versions.
297
298 \sa transformed()
299*/
300
301/*!
302 \fn Qt3DRender::RayCasting::QRay3D Qt3DRender::RayCasting::QRay3D::transformed(const Matrix4x4 &matrix) const
303
304 Returns a new ray that is formed by transforming origin()
305 and direction() using \a matrix.
306
307 \sa transform()
308*/
309
310/*!
311 \fn bool Qt3DRender::RayCasting::QRay3D::operator==(const QRay3D &other) const
312
313 Returns \c true if this ray is the same as \a other; \c false otherwise.
314
315 \sa operator!=()
316*/
317
318/*!
319 \fn bool Qt3DRender::RayCasting::QRay3D::operator!=(const QRay3D &other) const
320
321 Returns \c true if this ray is not the same as \a other; \c false otherwise.
322
323 \sa operator==()
324*/
325
326/*!
327 \fn bool qFuzzyCompare(const Qt3DRender::RayCasting::QRay3D &ray1, const Qt3DRender::RayCasting::QRay3D &ray2)
328 \relates Qt3DRender::RayCasting::QRay3D
329
330 Returns \c true if \a ray1 and \a ray2 are almost equal; \c false
331 otherwise.
332*/
333
334#ifndef QT_NO_DEBUG_STREAM
335
336QDebug operator<<(QDebug dbg, const QRay3D &ray)
337{
338 QDebugStateSaver saver(dbg);
339 dbg.nospace() << "QRay3D(origin("
340 << ray.origin().x() << ", " << ray.origin().y() << ", "
341 << ray.origin().z() << ") - direction("
342 << ray.direction().x() << ", " << ray.direction().y() << ", "
343 << ray.direction().z() << ") - distance(" << ray.distance() << "))";
344 return dbg;
345}
346
347#endif
348
349#ifndef QT_NO_DATASTREAM
350
351/*!
352 \relates Qt3DRender::RayCasting::QRay3D
353
354 Writes the given \a ray to the given \a stream and returns a
355 reference to the stream.
356*/
357QDataStream &operator<<(QDataStream &stream, const QRay3D &ray)
358{
359 stream << convertToQVector3D(v: ray.origin());
360 stream << convertToQVector3D(v: ray.direction());
361 if (stream.version() >= QDataStream::Qt_5_11)
362 stream << ray.distance();
363 return stream;
364}
365
366/*!
367 \relates Qt3DRender::RayCasting::QRay3D
368
369 Reads a 3D ray from the given \a stream into the given \a ray
370 and returns a reference to the stream.
371*/
372QDataStream &operator>>(QDataStream &stream, QRay3D &ray)
373{
374 QVector3D origin, direction;
375 float distance = 1.f;
376
377 stream >> origin;
378 stream >> direction;
379 if (stream.version() >= QDataStream::Qt_5_11)
380 stream >> distance;
381 ray = QRay3D(Vector3D(origin), Vector3D(direction), distance);
382 return stream;
383}
384
385#endif // QT_NO_DATASTREAM
386
387} // namespace RayCasting
388} // namespace Qt3DRender
389
390QT_END_NAMESPACE
391

source code of qt3d/src/render/raycasting/qray3d.cpp