1/****************************************************************************
2**
3** Copyright (C) 2015 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:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "geometryrenderer_p.h"
41#include <Qt3DRender/private/geometryrenderermanager_p.h>
42#include <Qt3DRender/private/qboundingvolume_p.h>
43#include <Qt3DRender/private/qgeometryrenderer_p.h>
44#include <Qt3DRender/private/qmesh_p.h>
45#include <Qt3DCore/qpropertyupdatedchange.h>
46#include <Qt3DCore/private/qnode_p.h>
47#include <Qt3DCore/private/qtypedpropertyupdatechange_p.h>
48#include <Qt3DCore/private/qservicelocator_p.h>
49#include <QtCore/qcoreapplication.h>
50
51#include <memory>
52
53QT_BEGIN_NAMESPACE
54
55using namespace Qt3DCore;
56
57namespace Qt3DRender {
58namespace Render {
59
60GeometryRenderer::GeometryRenderer()
61 : BackendNode(ReadWrite)
62 , m_instanceCount(0)
63 , m_vertexCount(0)
64 , m_indexOffset(0)
65 , m_firstInstance(0)
66 , m_firstVertex(0)
67 , m_indexBufferByteOffset(0)
68 , m_restartIndexValue(-1)
69 , m_verticesPerPatch(0)
70 , m_primitiveRestartEnabled(false)
71 , m_primitiveType(QGeometryRenderer::Triangles)
72 , m_dirty(false)
73 , m_manager(nullptr)
74 , m_sortIndex(-1.f)
75{
76}
77
78GeometryRenderer::~GeometryRenderer()
79{
80}
81
82void GeometryRenderer::cleanup()
83{
84 BackendNode::setEnabled(false);
85 m_instanceCount = 0;
86 m_vertexCount = 0;
87 m_indexOffset = 0;
88 m_firstInstance = 0;
89 m_firstVertex = 0;
90 m_indexBufferByteOffset = 0;
91 m_restartIndexValue = -1;
92 m_verticesPerPatch = 0;
93 m_primitiveRestartEnabled = false;
94 m_primitiveType = QGeometryRenderer::Triangles;
95 m_geometryId = Qt3DCore::QNodeId();
96 m_dirty = false;
97 m_geometryFactory.reset();
98 qDeleteAll(c: m_triangleVolumes);
99 m_triangleVolumes.clear();
100 m_sortIndex = -1.f;
101}
102
103void GeometryRenderer::setManager(GeometryRendererManager *manager)
104{
105 m_manager = manager;
106}
107
108void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
109{
110 BackendNode::syncFromFrontEnd(frontEnd, firstTime);
111 const QGeometryRenderer *node = qobject_cast<const QGeometryRenderer *>(object: frontEnd);
112 if (!node)
113 return;
114
115 m_dirty |= m_instanceCount != node->instanceCount();
116 m_instanceCount = node->instanceCount();
117 m_dirty |= m_vertexCount != node->vertexCount();
118 m_vertexCount = node->vertexCount();
119 m_dirty |= m_indexOffset != node->indexOffset();
120 m_indexOffset = node->indexOffset();
121 m_dirty |= m_firstInstance != node->firstInstance();
122 m_firstInstance = node->firstInstance();
123 m_dirty |= m_firstVertex != node->firstVertex();
124 m_firstVertex = node->firstVertex();
125 m_dirty |= m_indexBufferByteOffset != node->indexBufferByteOffset();
126 m_indexBufferByteOffset = node->indexBufferByteOffset();
127 m_dirty |= m_restartIndexValue != node->restartIndexValue();
128 m_restartIndexValue = node->restartIndexValue();
129 m_dirty |= m_verticesPerPatch != node->verticesPerPatch();
130 m_verticesPerPatch = node->verticesPerPatch();
131 m_dirty |= m_primitiveRestartEnabled != node->primitiveRestartEnabled();
132 m_primitiveRestartEnabled = node->primitiveRestartEnabled();
133 m_dirty |= m_primitiveType != node->primitiveType();
134 m_primitiveType = node->primitiveType();
135 m_dirty |= (node->geometry() && m_geometryId != node->geometry()->id()) || (!node->geometry() && !m_geometryId.isNull());
136 m_geometryId = node->geometry() ? node->geometry()->id() : Qt3DCore::QNodeId();
137 QGeometryFactoryPtr newFunctor = node->geometryFactory();
138 const bool functorDirty = ((m_geometryFactory && !newFunctor)
139 || (!m_geometryFactory && newFunctor)
140 || (m_geometryFactory && newFunctor && !(*newFunctor == *m_geometryFactory)));
141 if (functorDirty) {
142 m_dirty = true;
143 m_geometryFactory = newFunctor;
144 if (m_geometryFactory && m_manager != nullptr) {
145 m_manager->addDirtyGeometryRenderer(bufferId: peerId());
146
147 const bool isQMeshFunctor = m_geometryFactory->id() == Qt3DRender::functorTypeId<MeshLoaderFunctor>();
148 if (isQMeshFunctor) {
149 const QMesh *meshNode = static_cast<const QMesh *>(node);
150 QMeshPrivate *dmeshNode = QMeshPrivate::get(q: const_cast<QMesh *>(meshNode));
151 dmeshNode->setStatus(QMesh::Loading);
152 }
153 }
154 }
155
156 const auto dnode = static_cast<const QGeometryRendererPrivate*>(QGeometryRendererPrivate::get(q: node));
157 m_sortIndex = dnode->m_sortIndex;
158
159 markDirty(changes: AbstractRenderer::GeometryDirty);
160}
161
162GeometryFunctorResult GeometryRenderer::executeFunctor()
163{
164 Q_ASSERT(m_geometryFactory);
165
166 // What kind of functor are we dealing with?
167 const bool isQMeshFunctor = m_geometryFactory->id() == Qt3DRender::functorTypeId<MeshLoaderFunctor>();
168
169 if (isQMeshFunctor) {
170 QSharedPointer<MeshLoaderFunctor> meshLoader = qSharedPointerCast<MeshLoaderFunctor>(src: m_geometryFactory);
171
172 // Set the aspect engine to allow remote downloads
173 if (meshLoader->nodeManagers() == nullptr)
174 meshLoader->setNodeManagers(m_renderer->nodeManagers());
175
176 if (meshLoader->downloaderService() == nullptr) {
177 Qt3DCore::QServiceLocator *services = m_renderer->services();
178 meshLoader->setDownloaderService(services->service<Qt3DCore::QDownloadHelperService>(serviceType: Qt3DCore::QServiceLocator::DownloadHelperService));
179 };
180 }
181
182 // Load geometry
183 QGeometry *geometry = (*m_geometryFactory)();
184 QMesh::Status meshLoaderStatus = QMesh::None;
185
186 // If the geometry is null, then we were either unable to load it (Error)
187 // or the mesh is located at a remote url and needs to be downloaded first (Loading)
188 if (geometry != nullptr) {
189 // Move the QGeometry object to the main thread and notify the
190 // corresponding QGeometryRenderer
191 const auto appThread = QCoreApplication::instance()->thread();
192 geometry->moveToThread(thread: appThread);
193 }
194
195 // Send Status
196 if (isQMeshFunctor) {
197 QSharedPointer<MeshLoaderFunctor> meshLoader = qSharedPointerCast<MeshLoaderFunctor>(src: m_geometryFactory);
198 meshLoaderStatus = meshLoader->status();
199 }
200
201 return { .geometry: geometry, .status: meshLoaderStatus };
202}
203
204void GeometryRenderer::unsetDirty()
205{
206 m_dirty = false;
207}
208
209
210void GeometryRenderer::setTriangleVolumes(const QVector<RayCasting::QBoundingVolume *> &volumes)
211{
212 qDeleteAll(c: m_triangleVolumes);
213 m_triangleVolumes = volumes;
214}
215
216QVector<RayCasting::QBoundingVolume *> GeometryRenderer::triangleData() const
217{
218 return m_triangleVolumes;
219}
220
221GeometryRendererFunctor::GeometryRendererFunctor(AbstractRenderer *renderer, GeometryRendererManager *manager)
222 : m_manager(manager)
223 , m_renderer(renderer)
224{
225}
226
227Qt3DCore::QBackendNode *GeometryRendererFunctor::create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const
228{
229 GeometryRenderer *geometryRenderer = m_manager->getOrCreateResource(id: change->subjectId());
230 geometryRenderer->setManager(m_manager);
231 geometryRenderer->setRenderer(m_renderer);
232 return geometryRenderer;
233}
234
235Qt3DCore::QBackendNode *GeometryRendererFunctor::get(Qt3DCore::QNodeId id) const
236{
237 return m_manager->lookupResource(id);
238}
239
240void GeometryRendererFunctor::destroy(Qt3DCore::QNodeId id) const
241{
242 m_manager->releaseResource(id);
243}
244
245} // namespace Render
246} // namespace Qt3DRender
247
248QT_END_NAMESPACE
249

source code of qt3d/src/render/geometry/geometryrenderer.cpp