1// Copyright (C) 2016 Paul Lemire
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 "frustumcullingjob_p.h"
5#include <Qt3DRender/private/job_common_p.h>
6#include <Qt3DRender/private/managers_p.h>
7#include <Qt3DRender/private/entity_p.h>
8#include <Qt3DRender/private/sphere_p.h>
9#include <Qt3DRender/private/managers_p.h>
10#include <Qt3DRender/private/nodemanagers_p.h>
11
12QT_BEGIN_NAMESPACE
13
14namespace Qt3DRender {
15
16namespace Render {
17
18namespace {
19int instanceCounter = 0;
20} // anonymous
21
22FrustumCullingJob::FrustumCullingJob()
23 : Qt3DCore::QAspectJob()
24 , m_root(nullptr)
25 , m_manager(nullptr)
26 , m_active(false)
27{
28 SET_JOB_RUN_STAT_TYPE(this, JobTypes::FrustumCulling, instanceCounter++)
29}
30
31FrustumCullingJob::~FrustumCullingJob()
32{
33 --instanceCounter;
34}
35
36void FrustumCullingJob::run()
37{
38 // Early return if not activated
39 if (!m_active)
40 return;
41
42 m_visibleEntities.clear();
43
44 const Plane planes[6] = {
45 Plane(m_viewProjection.row(index: 3) + m_viewProjection.row(index: 0)), // Left
46 Plane(m_viewProjection.row(index: 3) - m_viewProjection.row(index: 0)), // Right
47 Plane(m_viewProjection.row(index: 3) + m_viewProjection.row(index: 1)), // Top
48 Plane(m_viewProjection.row(index: 3) - m_viewProjection.row(index: 1)), // Bottom
49 Plane(m_viewProjection.row(index: 3) + m_viewProjection.row(index: 2)), // Front
50 Plane(m_viewProjection.row(index: 3) - m_viewProjection.row(index: 2)), // Back
51 };
52
53 cullScene(e: m_root, planes);
54
55 // sort needed for set_intersection in RenderViewBuilder
56 std::sort(first: m_visibleEntities.begin(), last: m_visibleEntities.end());
57}
58
59void FrustumCullingJob::cullScene(Entity *e, const Plane *planes)
60{
61 e->traverse(operation: [planes, this](Entity *e) {
62 const Sphere *s = e->worldBoundingVolumeWithChildren();
63
64 // Unrolled loop
65 if (Vector3D::dotProduct(a: s->center(), b: planes[0].normal) + planes[0].d < -s->radius())
66 return;
67 if (Vector3D::dotProduct(a: s->center(), b: planes[1].normal) + planes[1].d < -s->radius())
68 return;
69 if (Vector3D::dotProduct(a: s->center(), b: planes[2].normal) + planes[2].d < -s->radius())
70 return;
71 if (Vector3D::dotProduct(a: s->center(), b: planes[3].normal) + planes[3].d < -s->radius())
72 return;
73 if (Vector3D::dotProduct(a: s->center(), b: planes[4].normal) + planes[4].d < -s->radius())
74 return;
75 if (Vector3D::dotProduct(a: s->center(), b: planes[5].normal) + planes[5].d < -s->radius())
76 return;
77
78 m_visibleEntities.push_back(x: e);
79 });
80}
81
82bool FrustumCullingJob::isRequired()
83{
84 return m_active;
85}
86
87} // Render
88
89} // Qt3DRender
90
91QT_END_NAMESPACE
92

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