1 | // Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "filterproximitydistancejob_p.h" |
5 | #include <Qt3DRender/private/managers_p.h> |
6 | #include <Qt3DRender/private/nodemanagers_p.h> |
7 | #include <Qt3DRender/private/entity_p.h> |
8 | #include <Qt3DRender/private/proximityfilter_p.h> |
9 | #include <Qt3DRender/private/job_common_p.h> |
10 | #include <Qt3DRender/private/sphere_p.h> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | namespace Qt3DRender { |
15 | |
16 | namespace Render { |
17 | |
18 | namespace { |
19 | int instanceCounter = 0; |
20 | } // anonymous |
21 | |
22 | |
23 | FilterProximityDistanceJob::FilterProximityDistanceJob() |
24 | : m_manager(nullptr) |
25 | , m_targetEntity(nullptr) |
26 | , m_distanceThresholdSquared(0.) |
27 | { |
28 | SET_JOB_RUN_STAT_TYPE(this, JobTypes::ProximityFiltering, instanceCounter++) |
29 | } |
30 | |
31 | FilterProximityDistanceJob::~FilterProximityDistanceJob() |
32 | { |
33 | --instanceCounter; |
34 | } |
35 | |
36 | bool FilterProximityDistanceJob::isRequired() |
37 | { |
38 | return hasProximityFilter(); |
39 | } |
40 | |
41 | void FilterProximityDistanceJob::run() |
42 | { |
43 | Q_ASSERT(m_manager != nullptr); |
44 | m_filteredEntities.clear(); |
45 | |
46 | // Fill m_filteredEntities |
47 | // If no filtering needs to be done, this will be the output value |
48 | // otherwise it will be used as the base list of entities to filter |
49 | |
50 | if (hasProximityFilter()) { |
51 | selectAllEntities(); |
52 | std::vector<Entity *> entitiesToFilter = std::move(m_filteredEntities); |
53 | FrameGraphManager *frameGraphManager = m_manager->frameGraphManager(); |
54 | EntityManager *entityManager = m_manager->renderNodesManager(); |
55 | |
56 | for (const Qt3DCore::QNodeId &proximityFilterId : std::as_const(t&: m_proximityFilterIds)) { |
57 | ProximityFilter *proximityFilter = static_cast<ProximityFilter *>(frameGraphManager->lookupNode(id: proximityFilterId)); |
58 | m_targetEntity = entityManager->lookupResource(id: proximityFilter->entityId()); |
59 | m_distanceThresholdSquared = proximityFilter->distanceThreshold(); |
60 | m_distanceThresholdSquared *= m_distanceThresholdSquared; |
61 | |
62 | // We can't filter, select nothings |
63 | if (m_targetEntity == nullptr || m_distanceThresholdSquared <= 0.0f) { |
64 | m_filteredEntities.clear(); |
65 | return; |
66 | } |
67 | // Otherwise we filter |
68 | filterEntities(entitiesToFilter); |
69 | |
70 | // And we make the filtered subset be the list of entities to filter |
71 | // for the next loop |
72 | entitiesToFilter = std::move(m_filteredEntities); |
73 | } |
74 | m_filteredEntities = std::move(entitiesToFilter); |
75 | } |
76 | |
77 | // sort needed for set_intersection in RenderViewBuilder |
78 | std::sort(first: m_filteredEntities.begin(), last: m_filteredEntities.end()); |
79 | } |
80 | |
81 | void FilterProximityDistanceJob::selectAllEntities() |
82 | { |
83 | EntityManager *entityManager = m_manager->renderNodesManager(); |
84 | const std::vector<HEntity> &handles = entityManager->activeHandles(); |
85 | |
86 | m_filteredEntities.reserve(n: handles.size()); |
87 | for (const HEntity &handle : handles) { |
88 | Entity *e = entityManager->data(handle); |
89 | m_filteredEntities.push_back(x: e); |
90 | } |
91 | } |
92 | |
93 | void FilterProximityDistanceJob::filterEntities(const std::vector<Entity *> &entitiesToFilter) |
94 | { |
95 | const Sphere *target = m_targetEntity->worldBoundingVolumeWithChildren(); |
96 | |
97 | for (Entity *entity : entitiesToFilter) { |
98 | // Note: The target entity is always selected as distance will be 0 |
99 | |
100 | // Retrieve center of bounding volume for entity |
101 | const Sphere *s = entity->worldBoundingVolumeWithChildren(); |
102 | |
103 | // If distance between entity and target is less than threshold, we keep the entity |
104 | if ((s->center() - target->center()).lengthSquared() <= m_distanceThresholdSquared) |
105 | m_filteredEntities.push_back(x: entity); |
106 | } |
107 | } |
108 | |
109 | } // Render |
110 | |
111 | } // Qt3DRender |
112 | |
113 | QT_END_NAMESPACE |
114 |