summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Benoit <remi.benoit@kdab.com>2015-07-08 17:31:53 +0200
committerPaul Lemire <paul.lemire@kdab.com>2015-08-09 21:08:24 +0000
commit7ecc1c72a1ad9d636b4314181e418e830d37e424 (patch)
tree3450b88488c4a6c475e2584aae49508e49962e93
parent4c5e74986b0e649e4aadbc76022ad18c17ef44dc (diff)
QRayCastingService implementation using bounding volumes
Bounding volumes are used to compute the collisions. Returns all hits or only first bounding volume hit. Change-Id: Ie40ffde56d126a63b1bdd498cdb7afae6eff1a9c Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/core/core.pri10
-rw-r--r--src/core/qboundingsphere.cpp53
-rw-r--r--src/core/qboundingsphere.h61
-rw-r--r--src/core/qboundingvolume.cpp53
-rw-r--r--src/core/qboundingvolume.h71
-rw-r--r--src/core/qboundingvolumeprovider.cpp52
-rw-r--r--src/core/qboundingvolumeprovider.h59
-rw-r--r--src/core/services/nullservices_p.h3
-rw-r--r--src/core/services/services.pri2
-rw-r--r--src/render/backend/qraycastingservice.cpp141
-rw-r--r--src/render/backend/qraycastingservice.h73
-rw-r--r--src/render/backend/qraycastingservice_p.h84
-rw-r--r--src/render/backend/render-backend.pri9
-rw-r--r--src/render/frontend/sphere.cpp57
-rw-r--r--src/render/frontend/sphere.h25
-rw-r--r--src/render/render.pro2
-rw-r--r--tests/auto/render/raycasting/raycasting.pro9
-rw-r--r--tests/auto/render/raycasting/tst_raycasting.cpp303
-rw-r--r--tests/auto/render/render.pro3
19 files changed, 1054 insertions, 16 deletions
diff --git a/src/core/core.pri b/src/core/core.pri
index dd9bb52ab..73c6035f7 100644
--- a/src/core/core.pri
+++ b/src/core/core.pri
@@ -40,7 +40,10 @@ HEADERS += \
$$PWD/qray3d.h \
$$PWD/qt3dcore_global_p.h \
$$PWD/qscene_p.h \
- $$PWD/qabstractfunctor.h
+ $$PWD/qabstractfunctor.h \
+ $$PWD/qboundingvolume.h \
+ $$PWD/qboundingsphere.h \
+ $$PWD/qboundingvolumeprovider.h
SOURCES += \
$$PWD/qtickclock.cpp \
@@ -58,4 +61,7 @@ SOURCES += \
$$PWD/qbackendscenepropertychange.cpp \
$$PWD/qbackendnodefactory.cpp \
$$PWD/qray3d.cpp \
- $$PWD/qabstractfunctor.cpp
+ $$PWD/qabstractfunctor.cpp \
+ $$PWD/qboundingvolume.cpp \
+ $$PWD/qboundingsphere.cpp \
+ $$PWD/qboundingvolumeprovider.cpp
diff --git a/src/core/qboundingsphere.cpp b/src/core/qboundingsphere.cpp
new file mode 100644
index 000000000..80af217c2
--- /dev/null
+++ b/src/core/qboundingsphere.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboundingsphere.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+QBoundingSphere::QBoundingSphere()
+{
+}
+
+QBoundingSphere::~QBoundingSphere()
+{
+}
+
+} // namespace Qt3D
+
+QT_END_NAMESPACE
diff --git a/src/core/qboundingsphere.h b/src/core/qboundingsphere.h
new file mode 100644
index 000000000..05f4b530c
--- /dev/null
+++ b/src/core/qboundingsphere.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QBOUDINGSPHERE_H
+#define QT3D_QBOUDINGSPHERE_H
+
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/qboundingvolume.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+class QT3DCORESHARED_EXPORT QBoundingSphere : public QBoundingVolume
+{
+public:
+ QBoundingSphere();
+ ~QBoundingSphere();
+
+ virtual QVector3D center() const = 0;
+ virtual float radius() const = 0;
+};
+
+} // namespace Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_QBOUDINGSPHERE_H
diff --git a/src/core/qboundingvolume.cpp b/src/core/qboundingvolume.cpp
new file mode 100644
index 000000000..caba96c79
--- /dev/null
+++ b/src/core/qboundingvolume.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboundingvolume.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+QBoundingVolume::QBoundingVolume()
+{
+}
+
+QBoundingVolume::~QBoundingVolume()
+{
+}
+
+} // namespace Qt3D
+
+QT_END_NAMESPACE
diff --git a/src/core/qboundingvolume.h b/src/core/qboundingvolume.h
new file mode 100644
index 000000000..f983b3ac9
--- /dev/null
+++ b/src/core/qboundingvolume.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QBOUDINGVOLUME_P_H
+#define QT3D_QBOUDINGVOLUME_P_H
+
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/qnodeid.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+class QRay3D;
+
+class QT3DCORESHARED_EXPORT QBoundingVolume
+{
+public:
+ QBoundingVolume();
+ virtual ~QBoundingVolume();
+
+ enum Type {
+ Sphere = 0
+ };
+
+ virtual QNodeId id() const = 0;
+ virtual bool intersects(const QRay3D &ray, QVector3D *q = Q_NULLPTR) const = 0;
+
+ virtual Type type() const = 0;
+};
+
+} // namespace Qt3D
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(Qt3D::QBoundingVolume*)
+
+#endif // QT3D_QBOUDINGVOLUME_P_H
diff --git a/src/core/qboundingvolumeprovider.cpp b/src/core/qboundingvolumeprovider.cpp
new file mode 100644
index 000000000..69091cacc
--- /dev/null
+++ b/src/core/qboundingvolumeprovider.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qboundingvolumeprovider.h"
+
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+QBoundingVolumeProvider::~QBoundingVolumeProvider()
+{
+
+}
+
+
+} // Qt3D
+
+QT_END_NAMESPACE
diff --git a/src/core/qboundingvolumeprovider.h b/src/core/qboundingvolumeprovider.h
new file mode 100644
index 000000000..3d8496d27
--- /dev/null
+++ b/src/core/qboundingvolumeprovider.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QBOUNDINGVOLUMEPROVIDER_H
+#define QT3D_QBOUNDINGVOLUMEPROVIDER_H
+
+#include <Qt3DCore/qt3dcore_global.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+class QBoundingVolume;
+
+class QT3DCORESHARED_EXPORT QBoundingVolumeProvider
+{
+public:
+ virtual ~QBoundingVolumeProvider();
+ virtual QVector<QBoundingVolume *> boundingVolumes() const = 0;
+};
+
+} // namespace Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_QBOUNDINGVOLUMEPROVIDER_H
diff --git a/src/core/services/nullservices_p.h b/src/core/services/nullservices_p.h
index 3529791a5..f11f9e29d 100644
--- a/src/core/services/nullservices_p.h
+++ b/src/core/services/nullservices_p.h
@@ -39,9 +39,10 @@
#include <Qt3DCore/qt3dcore_global.h>
#include <Qt3DCore/qray3d.h>
+#include <Qt3DCore/qcollisionqueryresult.h>
#include "qopenglinformationservice.h"
#include "qsysteminformationservice.h"
-#include "qabstractcollisionqueryservice.h"
+#include <Qt3DCore/qabstractcollisionqueryservice.h>
QT_BEGIN_NAMESPACE
diff --git a/src/core/services/services.pri b/src/core/services/services.pri
index 59c2ed140..6c0b252c7 100644
--- a/src/core/services/services.pri
+++ b/src/core/services/services.pri
@@ -21,7 +21,7 @@ HEADERS += \
$$PWD/qabstractcollisionqueryservice_p.h \
$$PWD/qcollisionqueryresult.h \
$$PWD/qcollisionqueryresult_p.h \
- $$PWD/qtickclockservice.h \
+ $$PWD/qtickclockservice_p.h \
$$PWD/qabstractframeadvanceservice.h \
$$PWD/qabstractframeadvanceservice_p.h
diff --git a/src/render/backend/qraycastingservice.cpp b/src/render/backend/qraycastingservice.cpp
new file mode 100644
index 000000000..56566f19a
--- /dev/null
+++ b/src/render/backend/qraycastingservice.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qraycastingservice.h"
+#include "qraycastingservice_p.h"
+
+#include <Qt3DCore/qray3d.h>
+#include <Qt3DRenderer/sphere.h>
+#include <Qt3DCore/qboundingvolumeprovider.h>
+
+#include <QMap>
+#include <QtConcurrent>
+
+#include "math.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+QCollisionQueryResult QRayCastingServicePrivate::collides(const QRay3D &ray, QBoundingVolumeProvider *provider,
+ QAbstractCollisionQueryService::QueryMode mode, const QQueryHandle &handle)
+{
+ Q_Q(QRayCastingService);
+
+ const QVector<QBoundingVolume *> spheres(provider->boundingVolumes());
+ QCollisionQueryResult result;
+ q->setResultHandle(result, handle);
+
+ if (mode == QAbstractCollisionQueryService::FirstHit) {
+ QVector3D intersection;
+ float collidingPointDistance = -1.0f;
+ QNodeId collidingSphere;
+
+ Q_FOREACH (QBoundingVolume *bs, spheres) {
+ if (bs->intersects(ray, &intersection)) {
+ const float distanceFromRay = ray.projectedDistance(intersection);
+
+ if (collidingPointDistance == -1.0f || (distanceFromRay >= 0.0f && distanceFromRay < collidingPointDistance)) {
+ collidingPointDistance = distanceFromRay;
+ collidingSphere = bs->id();
+ }
+ }
+ }
+
+ if (!collidingSphere.isNull()) {
+ q->addEntityHit(result, collidingSphere);
+ }
+
+ } else if (mode == QAbstractCollisionQueryService::AllHits) {
+ Q_FOREACH (QBoundingVolume *bs, spheres) {
+ if (bs->intersects(ray))
+ q->addEntityHit(result, bs->id());
+ }
+ }
+ return result;
+}
+
+QRayCastingServicePrivate::QRayCastingServicePrivate(const QString &description, QBoundingVolumeProvider *provider)
+ : QAbstractCollisionQueryServicePrivate(description)
+ , m_handlesCount(0)
+ , m_boundingProvider(provider)
+{
+}
+
+QRayCastingService::QRayCastingService(QBoundingVolumeProvider *provider)
+ : QAbstractCollisionQueryService(*new QRayCastingServicePrivate(QStringLiteral("Collision detection service using Ray Casting"),
+ provider))
+{
+}
+
+QQueryHandle QRayCastingService::query(const QRay3D &ray, QAbstractCollisionQueryService::QueryMode mode)
+{
+ Q_D(QRayCastingService);
+
+ QQueryHandle handle = d->m_handlesCount.fetchAndStoreOrdered(1);
+
+ // TODO: Implement run using jobs to avoid multiple threadpool
+ FutureQueryResult future = QtConcurrent::run(d, &QRayCastingServicePrivate::collides,
+ ray, d->m_boundingProvider, mode, handle);
+ d->m_results.insert(handle, future);
+
+ return handle;
+}
+
+QCollisionQueryResult QRayCastingService::fetchResult(const QQueryHandle &handle)
+{
+ Q_D(QRayCastingService);
+
+ return d->m_results.value(handle).result();
+}
+
+QVector<QCollisionQueryResult> QRayCastingService::fetchAllResults() const
+{
+ Q_D(const QRayCastingService);
+
+ const QList<FutureQueryResult> futureResults = d->m_results.values();
+ QVector<QCollisionQueryResult> results;
+ results.reserve(futureResults.size());
+
+ Q_FOREACH (const FutureQueryResult &future, futureResults)
+ results.append(future.result());
+
+ return results;
+}
+
+} // Qt3D
+
+QT_END_NAMESPACE
diff --git a/src/render/backend/qraycastingservice.h b/src/render/backend/qraycastingservice.h
new file mode 100644
index 000000000..4ae2b817e
--- /dev/null
+++ b/src/render/backend/qraycastingservice.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_RENDER_QRAYCASTINGSERVICE_H
+#define QT3D_RENDER_QRAYCASTINGSERVICE_H
+
+#include <Qt3DRenderer/qt3drenderer_global.h>
+
+#include <Qt3DCore/qabstractcollisionqueryservice.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+class QBoundingVolumeProvider;
+class QRayCastingServicePrivate;
+
+class QT3DRENDERERSHARED_EXPORT QRayCastingService : public QAbstractCollisionQueryService
+{
+public:
+ explicit QRayCastingService(QBoundingVolumeProvider *provider);
+
+ QQueryHandle query(const QRay3D &ray, QueryMode mode) Q_DECL_OVERRIDE;
+
+ QCollisionQueryResult fetchResult(const QQueryHandle &handle) Q_DECL_OVERRIDE;
+ QVector<QCollisionQueryResult> fetchAllResults() const Q_DECL_OVERRIDE;
+
+protected:
+ QRayCastingService(QRayCastingServicePrivate &dd);
+
+private:
+ Q_DISABLE_COPY(QRayCastingService)
+ Q_DECLARE_PRIVATE(QRayCastingService)
+};
+
+} // Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_RENDER_QRAYCASTINGSERVICE_H
diff --git a/src/render/backend/qraycastingservice_p.h b/src/render/backend/qraycastingservice_p.h
new file mode 100644
index 000000000..d9ed92323
--- /dev/null
+++ b/src/render/backend/qraycastingservice_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3D_QRAYCASTINGSERVICE_P_H
+#define QT3D_QRAYCASTINGSERVICE_P_H
+
+#include <Qt3DCore/qt3dcore_global.h>
+#include <Qt3DCore/qabstractcollisionqueryservice.h>
+#include <Qt3DCore/private/qabstractcollisionqueryservice_p.h>
+#include <Qt3DCore/qray3d.h>
+
+#include <QHash>
+#include <QtConcurrent>
+#include <QAtomicInt>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3D {
+
+class QBoundingVolumeProvider;
+class QBoundingVolume;
+typedef QFuture<QCollisionQueryResult> FutureQueryResult;
+
+class QRayCastingServicePrivate : public QAbstractCollisionQueryServicePrivate
+{
+public:
+ QRayCastingServicePrivate(const QString &description, QBoundingVolumeProvider *provider);
+
+ QCollisionQueryResult collides(const QRay3D &ray, QBoundingVolumeProvider *provider,
+ QAbstractCollisionQueryService::QueryMode mode, const QQueryHandle &handle);
+
+ Q_DECLARE_PUBLIC(QRayCastingService)
+
+ struct Query
+ {
+ QQueryHandle handle;
+ QRay3D ray;
+ QRayCastingService::QueryMode mode;
+ };
+
+ QHash<QQueryHandle, FutureQueryResult> m_results;
+ QAtomicInt m_handlesCount;
+
+ QBoundingVolumeProvider *m_boundingProvider;
+};
+
+} // Qt3D
+
+QT_END_NAMESPACE
+
+#endif // QT3D_QRAYCASTINGSERVICE_P_H
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 04b4e24c8..81aecd726 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -56,7 +56,9 @@ HEADERS += \
$$PWD/rendergeometry_p.h \
$$PWD/rendergeometryrenderer_p.h \
$$PWD/buffermanager_p.h \
- $$PWD/geometryrenderermanager_p.h
+ $$PWD/geometryrenderermanager_p.h \
+ $$PWD/qraycastingservice.h \
+ $$PWD/qraycastingservice_p.h
SOURCES += \
$$PWD/qrenderaspect.cpp \
@@ -97,10 +99,11 @@ SOURCES += \
$$PWD/rendershaderdata.cpp \
$$PWD/renderparametermapping.cpp \
$$PWD/rendertextureimage.cpp \
- $$PWD/vsyncframeadvanceservice.cpp \
$$PWD/renderbuffer.cpp \
$$PWD/renderattribute.cpp \
$$PWD/rendergeometry.cpp \
$$PWD/rendergeometryrenderer.cpp \
$$PWD/buffermanager.cpp \
- $$PWD/geometryrenderermanager.cpp
+ $$PWD/geometryrenderermanager.cpp \
+ $$PWD/qraycastingservice.cpp \
+ $$PWD/vsyncframeadvanceservice.cpp
diff --git a/src/render/frontend/sphere.cpp b/src/render/frontend/sphere.cpp
index 34c4be554..12077c87a 100644
--- a/src/render/frontend/sphere.cpp
+++ b/src/render/frontend/sphere.cpp
@@ -36,6 +36,8 @@
#include "sphere.h"
+#include <Qt3DCore/qray3d.h>
+
#include <QPair>
#include <math.h>
@@ -44,6 +46,46 @@ QT_BEGIN_NAMESPACE
namespace {
+// Algorithms taken from Real-time collision detection, p178-179
+
+// Intersects ray r = p + td, |d| = 1, with sphere s and, if intersecting,
+// returns true and intersection point q; false otherwise
+bool intersectRaySphere(const Qt3D::QRay3D &ray, const Qt3D::Sphere &s, QVector3D *q = Q_NULLPTR)
+{
+ const QVector3D p = ray.origin();
+ const QVector3D d = ray.direction();
+ const QVector3D m = p - s.center();
+ const float c = QVector3D::dotProduct(m, m) - s.radius() * s.radius();
+
+ // If there is definitely at least one real root, there must be an intersection
+ if (q == Q_NULLPTR && c <= 0.0f)
+ return true;
+
+ const float b = QVector3D::dotProduct(m, d);
+ // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0)
+ if (c > 0.0f && b > 0.0f)
+ return false;
+
+ const float discr = b*b - c;
+ // A negative discriminant corresponds to ray missing sphere
+ if (discr < 0.0f)
+ return false;
+
+ // If we don't need the intersection point, return early
+ if (q == Q_NULLPTR)
+ return true;
+
+ // Ray now found to intersect sphere, compute smallest t value of intersection
+ float t = -b - sqrt(discr);
+
+ // If t is negative, ray started inside sphere so clamp t to zero
+ if (t < 0.0f)
+ t = 0.0f;
+
+ *q = p + t * d;
+ return true;
+}
+
inline QPair<int, int> findExtremePoints(const QVector<QVector3D> &points)
{
// Find indices of extreme points along x, y, and z axes
@@ -169,6 +211,21 @@ Sphere Sphere::transformed(const QMatrix4x4 &mat)
return Sphere(c, sqrt(rSquared));
}
+QNodeId Sphere::id() const
+{
+ return m_id;
+}
+
+bool Sphere::intersects(const QRay3D &ray, QVector3D *q) const
+{
+ return intersectRaySphere(ray, *this, q);
+}
+
+QBoundingVolume::Type Sphere::type() const
+{
+ return QBoundingVolume::Sphere;
+}
+
}
QT_END_NAMESPACE
diff --git a/src/render/frontend/sphere.h b/src/render/frontend/sphere.h
index e02c01308..2c53d8fe6 100644
--- a/src/render/frontend/sphere.h
+++ b/src/render/frontend/sphere.h
@@ -38,6 +38,8 @@
#define SPHERE_H
#include <Qt3DRenderer/qt3drenderer_global.h>
+#include <Qt3DCore/qnodeid.h>
+#include <Qt3DCore/qboundingsphere.h>
#include <QMatrix4x4>
#include <QVector3D>
@@ -46,17 +48,19 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
-class Sphere
+class Q_AUTOTEST_EXPORT Sphere : public QBoundingSphere
{
public:
- inline Sphere()
- : m_center(),
- m_radius(0.0f)
+ inline Sphere(const QNodeId &i = QNodeId())
+ : m_center()
+ , m_radius(0.0f)
+ , m_id(i)
{}
- inline Sphere(const QVector3D &c, float r)
- : m_center(c),
- m_radius(r)
+ inline Sphere(const QVector3D &c, float r, const QNodeId &i = QNodeId())
+ : m_center(c)
+ , m_radius(r)
+ , m_id(i)
{}
void setCenter(const QVector3D &c);
@@ -85,11 +89,16 @@ public:
return *this;
}
+ QNodeId id() const Q_DECL_FINAL;
+ bool intersects(const QRay3D &ray, QVector3D *q) const Q_DECL_FINAL;
+ Type type() const Q_DECL_FINAL;
+
static Sphere fromPoints(const QVector<QVector3D> &points);
private:
QVector3D m_center;
float m_radius;
+ QNodeId m_id;
static const float ms_epsilon;
};
@@ -136,4 +145,6 @@ inline bool intersects(const Sphere &a, const Sphere &b)
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(Qt3D::Sphere)
+
#endif // SPHERE_H
diff --git a/src/render/render.pro b/src/render/render.pro
index 03f05e9ba..21ff1269d 100644
--- a/src/render/render.pro
+++ b/src/render/render.pro
@@ -1,6 +1,6 @@
TARGET = Qt3DRenderer
-QT += core-private gui-private 3dcore 3dcore-private openglextensions
+QT += core-private gui-private 3dcore 3dcore-private openglextensions concurrent
DEFINES += QT3DRENDERER_LIBRARY
diff --git a/tests/auto/render/raycasting/raycasting.pro b/tests/auto/render/raycasting/raycasting.pro
new file mode 100644
index 000000000..e389ef3d7
--- /dev/null
+++ b/tests/auto/render/raycasting/raycasting.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+
+TARGET = tst_raycasting
+
+QT += 3dcore 3dcore-private 3drenderer 3drenderer-private testlib
+
+CONFIG += testcase
+
+SOURCES += tst_raycasting.cpp
diff --git a/tests/auto/render/raycasting/tst_raycasting.cpp b/tests/auto/render/raycasting/tst_raycasting.cpp
new file mode 100644
index 000000000..6b0a9d80a
--- /dev/null
+++ b/tests/auto/render/raycasting/tst_raycasting.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <Qt3DRenderer/private/renderentity_p.h>
+#include <Qt3DRenderer/qraycastingservice.h>
+#include <Qt3DRenderer/sphere.h>
+#include <Qt3DCore/qboundingvolumeprovider.h>
+#include <Qt3DCore/qray3d.h>
+
+using namespace Qt3D;
+using namespace Qt3D::Render;
+
+class tst_RayCasting : public QObject
+{
+ Q_OBJECT
+public:
+ tst_RayCasting() {}
+ ~tst_RayCasting() {}
+
+private Q_SLOTS:
+ void shouldReturnValidHandle();
+ void shouldReturnResultForEachHandle();
+ void shouldReturnAllResults();
+ void shouldReturnHits();
+ void shouldReturnHits_data();
+ void shouldIntersect_data();
+ void shouldIntersect();
+ void shouldUseProvidedBoudingVolumes();
+
+ void cleanupTestCase();
+
+private:
+ Sphere *volumeAt(int index);
+ QVector<Sphere> boundingVolumes;
+};
+
+void tst_RayCasting::shouldIntersect_data()
+{
+ QTest::addColumn<QRay3D>("ray");
+ QTest::addColumn<Sphere>("sphere");
+ QTest::addColumn<int>("shouldIntersect");
+
+ QRay3D ray(QVector3D(1, 1, 1), QVector3D(0, 0, 1));
+
+ Sphere sphere1(QVector3D(1, 1, 1), 2);
+ Sphere sphere2(QVector3D(0, 0, 0), 3);
+ Sphere sphere3(QVector3D(0, 1, 3), 1);
+ Sphere sphere4(QVector3D(4, 4, 5), 1);
+ Sphere sphere5(QVector3D(2, 2, 11), 5);
+ Sphere sphere6(QVector3D(2, 2, 13), 1);
+ Sphere sphere7(QVector3D(2, 2, 15), 5);
+
+ QTest::newRow("Ray starts inside sphere") << ray << sphere1 << 1;
+ QTest::newRow("Ray starts inside sphere") << ray << sphere2 << 1;
+ QTest::newRow("Ray intersects sphere tangentially") << ray << sphere3 << 1;
+ QTest::newRow("No intersection") << ray << sphere4 << 0;
+ QTest::newRow("Ray intersect sphere") << ray << sphere5 << 1;
+ QTest::newRow("No intersection") << ray << sphere6 << 0;
+ QTest::newRow("Ray intersect sphere") << ray << sphere7 << 1;
+}
+
+void tst_RayCasting::shouldIntersect()
+{
+ QFETCH(QRay3D, ray);
+ QFETCH(Sphere, sphere);
+ QFETCH(int, shouldIntersect);
+
+ QVector3D intersectionPoint;
+
+ QCOMPARE(sphere.intersects(ray, &intersectionPoint), shouldIntersect);
+}
+
+class MyBoudingVolumesProvider : public QBoundingVolumeProvider
+{
+public:
+ MyBoudingVolumesProvider(QVector<QBoundingVolume *> volumes)
+ : m_volumes(volumes)
+ {}
+
+ QVector<QBoundingVolume *> boundingVolumes() const
+ {
+ return m_volumes;
+ }
+
+private:
+ QVector<QBoundingVolume *> m_volumes;
+};
+
+void tst_RayCasting::shouldReturnValidHandle()
+{
+ // GIVEN
+ QRay3D ray;
+ Sphere v1;
+ MyBoudingVolumesProvider provider = QVector<QBoundingVolume *>() << &v1;
+
+ QRayCastingService service(&provider);
+
+ // WHEN
+ QQueryHandle handle = service.query(ray, QAbstractCollisionQueryService::AllHits);
+
+ // THEN
+ QVERIFY(handle >= 0);
+
+ // Wait the query to finish
+ service.fetchResult(handle);
+}
+
+void tst_RayCasting::shouldReturnResultForEachHandle()
+{
+ // GIVEN
+ QRay3D ray;
+ QVector<QBoundingVolume *> volumes;
+ MyBoudingVolumesProvider provider(volumes);
+
+ QRayCastingService service(&provider);
+
+ QQueryHandle handle1 = service.query(ray, QAbstractCollisionQueryService::AllHits);
+ QQueryHandle handle2 = service.query(ray, QAbstractCollisionQueryService::FirstHit);
+
+ // WHEN
+ QCollisionQueryResult result2 = service.fetchResult(handle2);
+ QCollisionQueryResult result1 = service.fetchResult(handle1);
+
+ // THEN
+ QCOMPARE(result1.handle(), handle1);
+ QCOMPARE(result2.handle(), handle2);
+}
+
+void tst_RayCasting::shouldReturnAllResults()
+{
+ // GIVEN
+ QRay3D ray;
+ QVector<QBoundingVolume *> volumes;
+ MyBoudingVolumesProvider provider(volumes);
+
+ QRayCastingService service(&provider);
+
+ QVector<QQueryHandle> handles;
+ handles.append(service.query(ray, QAbstractCollisionQueryService::AllHits));
+ handles.append(service.query(ray, QAbstractCollisionQueryService::FirstHit));
+
+ // WHEN
+ QVector<QCollisionQueryResult> results = service.fetchAllResults();
+
+ // THEN
+ bool expectedHandlesFound = true;
+ Q_FOREACH (QQueryHandle expected, handles) {
+ bool found = false;
+ Q_FOREACH (QCollisionQueryResult result, results) {
+ if (result.handle() == expected)
+ found = true;
+ }
+
+ expectedHandlesFound &= found;
+ }
+
+ QVERIFY(expectedHandlesFound);
+}
+
+void tst_RayCasting::shouldReturnHits_data()
+{
+ QTest::addColumn<QRay3D>("ray");
+ QTest::addColumn<QVector<QBoundingVolume *> >("volumes");
+ QTest::addColumn<QVector<QNodeId> >("hits");
+ QTest::addColumn<QAbstractCollisionQueryService::QueryMode >("queryMode");
+
+ QRay3D ray(QVector3D(1, 1, 1), QVector3D(0, 0, 1));
+
+ this->boundingVolumes.clear();
+ this->boundingVolumes.append(QVector<Sphere>() << Sphere(QVector3D(1, 1, 1), 3, QNodeId::createId())
+ << Sphere(QVector3D(0, 0, 0), 3, QNodeId::createId())
+ << Sphere(QVector3D(0, 1, 3), 1, QNodeId::createId())
+ << Sphere(QVector3D(4, 4, 5), 1, QNodeId::createId())
+ << Sphere(QVector3D(2, 2, 11), 5, QNodeId::createId())
+ << Sphere(QVector3D(2, 2, 13), 1, QNodeId::createId())
+ << Sphere(QVector3D(2, 2, 15), 5, QNodeId::createId()));
+
+ QTest::newRow("All hits, One sphere intersect") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(0) << volumeAt(3))
+ << (QVector<QNodeId>() << volumeAt(0)->id())
+ << QAbstractCollisionQueryService::AllHits;
+
+ QTest::newRow("All hits, Three sphere intersect") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(0) << volumeAt(3) << volumeAt(6) << volumeAt(2))
+ << (QVector<QNodeId>() << volumeAt(0)->id() << volumeAt(6)->id() << volumeAt(2)->id())
+ << QAbstractCollisionQueryService::AllHits;
+
+ QTest::newRow("All hits, No sphere intersect") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(3) << volumeAt(5))
+ << (QVector<QNodeId>())
+ << QAbstractCollisionQueryService::AllHits;
+
+ QTest::newRow("Sphere 1 intersect, returns First Hit") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(0) << volumeAt(3) << volumeAt(1))
+ << (QVector<QNodeId>() << volumeAt(0)->id())
+ << QAbstractCollisionQueryService::FirstHit;
+
+ QTest::newRow("Sphere 3 and 5 intersects, returns First Hit") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(3) << volumeAt(6) << volumeAt(4))
+ << (QVector<QNodeId>() << volumeAt(4)->id())
+ << QAbstractCollisionQueryService::FirstHit;
+
+ QTest::newRow("Sphere 5 and 3 intersects, unordered list, returns First Hit") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(4) << volumeAt(3) << volumeAt(6))
+ << (QVector<QNodeId>() << volumeAt(4)->id())
+ << QAbstractCollisionQueryService::FirstHit;
+
+ QTest::newRow("No sphere intersect, returns First Hit") << ray
+ << (QVector<QBoundingVolume *> () << volumeAt(3) << volumeAt(5))
+ << (QVector<QNodeId>())
+ << QAbstractCollisionQueryService::FirstHit;
+}
+
+void tst_RayCasting::shouldReturnHits()
+{
+ // GIVEN
+ QFETCH(QRay3D, ray);
+ QFETCH(QVector<QBoundingVolume *>, volumes);
+ QFETCH(QVector<QNodeId>, hits);
+ QFETCH(QAbstractCollisionQueryService::QueryMode, queryMode);
+
+ MyBoudingVolumesProvider provider(volumes);
+ QRayCastingService service(&provider);
+
+ // WHEN
+ QQueryHandle handle = service.query(ray, queryMode);
+ QCollisionQueryResult result = service.fetchResult(handle);
+
+ // THEN
+ QCOMPARE(result.entitiesHit().size(), hits.size());
+ QCOMPARE(result.entitiesHit(), hits);
+}
+
+void tst_RayCasting::shouldUseProvidedBoudingVolumes()
+{
+ // GIVEN
+ QRay3D ray(QVector3D(1, 1, 1), QVector3D(0, 0, 1));
+
+ Sphere sphere1(QVector3D(1, 1, 1), 3);
+ Sphere sphere3(QVector3D(0, 1, 3), 1);
+ Sphere sphere4(QVector3D(4, 4, 5), 1);
+
+ MyBoudingVolumesProvider provider(QVector<QBoundingVolume *>() << &sphere1 << &sphere4 << &sphere3);
+ QVector<QNodeId> hits(QVector<QNodeId>() << sphere1.id() << sphere3.id());
+
+ QRayCastingService service(&provider);
+
+ // WHEN
+ QQueryHandle handle = service.query(ray, QAbstractCollisionQueryService::AllHits);
+ QCollisionQueryResult result = service.fetchResult(handle);
+
+ // THEN
+ QCOMPARE(result.entitiesHit().size(), hits.size());
+ QCOMPARE(result.entitiesHit(), hits);
+}
+
+void tst_RayCasting::cleanupTestCase()
+{
+ this->boundingVolumes.clear();
+}
+
+Sphere *tst_RayCasting::volumeAt(int index)
+{
+ return &*(boundingVolumes.begin() + index);
+}
+
+QTEST_APPLESS_MAIN(tst_RayCasting)
+
+#include "tst_raycasting.moc"
diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro
index f008bee8a..f9bf2b7d4 100644
--- a/tests/auto/render/render.pro
+++ b/tests/auto/render/render.pro
@@ -20,5 +20,6 @@ contains(QT_CONFIG, private_tests) {
renderbuffer \
renderattribute \
rendergeometry \
- rendergeometryrenderer
+ rendergeometryrenderer \
+ raycasting
}