1/****************************************************************************
2**
3** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "filterproximitydistancejob_p.h"
30#include <Qt3DRender/private/managers_p.h>
31#include <Qt3DRender/private/nodemanagers_p.h>
32#include <Qt3DRender/private/entity_p.h>
33#include <Qt3DRender/private/proximityfilter_p.h>
34#include <Qt3DRender/private/job_common_p.h>
35#include <Qt3DRender/private/sphere_p.h>
36
37QT_BEGIN_NAMESPACE
38
39namespace Qt3DRender {
40
41namespace Render {
42
43namespace {
44int instanceCounter = 0;
45} // anonymous
46
47
48FilterProximityDistanceJob::FilterProximityDistanceJob()
49 : m_manager(nullptr)
50 , m_targetEntity(nullptr)
51 , m_distanceThresholdSquared(0.)
52{
53 SET_JOB_RUN_STAT_TYPE(this, JobTypes::ProximityFiltering, instanceCounter++)
54}
55
56FilterProximityDistanceJob::~FilterProximityDistanceJob()
57{
58 --instanceCounter;
59}
60
61void FilterProximityDistanceJob::run()
62{
63 Q_ASSERT(m_manager != nullptr);
64 m_filteredEntities.clear();
65
66 // Fill m_filteredEntities
67 // If no filtering needs to be done, this will be the output value
68 // otherwise it will be used as the base list of entities to filter
69
70 if (hasProximityFilter()) {
71 selectAllEntities();
72 QVector<Entity *> entitiesToFilter = std::move(m_filteredEntities);
73 FrameGraphManager *frameGraphManager = m_manager->frameGraphManager();
74 EntityManager *entityManager = m_manager->renderNodesManager();
75
76 for (const Qt3DCore::QNodeId proximityFilterId : qAsConst(t&: m_proximityFilterIds)) {
77 ProximityFilter *proximityFilter = static_cast<ProximityFilter *>(frameGraphManager->lookupNode(id: proximityFilterId));
78 m_targetEntity = entityManager->lookupResource(id: proximityFilter->entityId());
79 m_distanceThresholdSquared = proximityFilter->distanceThreshold();
80 m_distanceThresholdSquared *= m_distanceThresholdSquared;
81
82 // We can't filter, select nothings
83 if (m_targetEntity == nullptr || m_distanceThresholdSquared <= 0.0f) {
84 m_filteredEntities.clear();
85 return;
86 }
87 // Otherwise we filter
88 filterEntities(entitiesToFilter);
89
90 // And we make the filtered subset be the list of entities to filter
91 // for the next loop
92 entitiesToFilter = std::move(m_filteredEntities);
93 }
94 m_filteredEntities = std::move(entitiesToFilter);
95 }
96
97 // sort needed for set_intersection in RenderViewBuilder
98 std::sort(first: m_filteredEntities.begin(), last: m_filteredEntities.end());
99}
100
101void FilterProximityDistanceJob::selectAllEntities()
102{
103 EntityManager *entityManager = m_manager->renderNodesManager();
104 const std::vector<HEntity> &handles = entityManager->activeHandles();
105
106 m_filteredEntities.reserve(asize: handles.size());
107 for (const HEntity &handle : handles) {
108 Entity *e = entityManager->data(handle);
109 m_filteredEntities.push_back(t: e);
110 }
111}
112
113void FilterProximityDistanceJob::filterEntities(const QVector<Entity *> &entitiesToFilter)
114{
115 const Sphere *target = m_targetEntity->worldBoundingVolumeWithChildren();
116
117 for (Entity *entity : entitiesToFilter) {
118 // Note: The target entity is always selected as distance will be 0
119
120 // Retrieve center of bounding volume for entity
121 const Sphere *s = entity->worldBoundingVolumeWithChildren();
122
123 // If distance between entity and target is less than threshold, we keep the entity
124 if ((s->center() - target->center()).lengthSquared() <= m_distanceThresholdSquared)
125 m_filteredEntities.push_back(t: entity);
126 }
127}
128
129} // Render
130
131} // Qt3DRender
132
133QT_END_NAMESPACE
134

source code of qt3d/src/render/jobs/filterproximitydistancejob.cpp