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: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 "qlevelofdetail.h"
41#include "qlevelofdetail_p.h"
42#include "qcamera.h"
43
44QT_BEGIN_NAMESPACE
45
46namespace Qt3DRender {
47
48QLevelOfDetailPrivate::QLevelOfDetailPrivate()
49 : QComponentPrivate()
50 , m_camera(nullptr)
51 , m_currentIndex(0)
52 , m_thresholdType(QLevelOfDetail::DistanceToCameraThreshold)
53 , m_volumeOverride()
54{
55}
56
57void QLevelOfDetailPrivate::setCurrentIndex(int currentIndex)
58{
59 Q_Q(QLevelOfDetail);
60 if (m_currentIndex != currentIndex) {
61 m_currentIndex = currentIndex;
62 emit q->currentIndexChanged(currentIndex: m_currentIndex);
63 }
64}
65
66/*!
67 \class Qt3DRender::QLevelOfDetail
68 \inmodule Qt3DRender
69 \since 5.9
70 \brief The QLevelOfDetail class provides a way of controlling the complexity
71 of rendered entities based on their size on the screen.
72
73 QLevelOfDetail can be used to control the representation of an entity
74 based on distance from the observer or size on the screen.
75
76 In order to improve rendering performance, objects that are very small
77 can be rendered using far fewer details, in geometry or texture.
78
79 The component is controlled by specifying thresholds of values which are interpreted
80 as either distances from the camera or screen size.
81
82 As the point of view changes, the currentIndex property will change to
83 reflect matching value in the range array.
84
85 The currentIndex property can then be used, for example, to enable or
86 disable entities, change material, etc.
87
88 The LevelOfDetail component is not shareable between multiple \l [QML]{Entity}{entities}.
89
90 \code
91 #include <Qt3DCore/QEntity>
92 #include <Qt3DRender/QGeometryRenderer>
93 #include <Qt3DRender/QLevelOfDetail>
94
95 // Scene
96 Qt3DCore::QEntity *rootEntity = new Qt3DCore::Qt3DCore::QEntity;
97
98 Qt3DCore::QEntity *renderableEntity = new Qt3DCore::QEntity(rootEntity);
99 Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DCore::QGeometryRenderer(renderableEntity);
100 renderableEntity->addComponent(geometryRenderer);
101 Qt3DRender::QLevelOfDetail* lod = new Qt3Render::QLevelOfDetail(renderableEntity);
102 QVector<qreal> thresholds = {20, 35, 50, 65};
103 lod->setThresholds(thresholds);
104 lod->setCamera(mainCamera);
105 renderableEntity->addComponent(lod);
106
107 // connect to QLevelOfDetail::currentIndexChanged to toggle rendering
108 ...
109 \endcode
110*/
111
112/*!
113 \qmltype LevelOfDetail
114 \instantiates Qt3DRender::QLevelOfDetail
115 \inherits Component3D
116 \inqmlmodule Qt3D.Render
117 \since 5.9
118 \brief LevelOfDetail provides a way of controlling the complexity of
119 rendered entities based on their size on the screen.
120
121 LevelOfDetail can be used to control the representation of an entity
122 based on distance from the observer or size on the screen.
123
124 In order to improve rendering performance, objects that are very small
125 can be rendered using far fewer details, in geometry or texture.
126
127 The component is controlled by specifying thresholds of values which are interpreted
128 as either distances from the camera or screen size.
129
130 As the point of view changes, the currentIndex property will change to
131 reflect matching value in the range array.
132
133 The currentIndex property can then be used, for example, to enable or
134 disable entities, change source in an EntityLoader, or material.
135
136 The LevelOfDetail component is not shareable between multiple Entity's.
137
138 \code
139 import Qt3D.Core 2.0
140 import Qt3D.Render 2.0
141
142 Entity {
143 id: root
144
145 // Scene
146 Camera { id: mainCamera }
147
148 LevelOfDetail {
149 id: lod
150 camera: mainCamera
151 thresholds: [20, 35, 50, 65]
152 thresholdType: LevelOfDetail.DistanceToCameraThreshold
153 }
154
155 CylinderMesh {
156 id: mesh
157
158 property var sliceValues: [20, 10, 6, 4]
159 slices: sliceValues[lod.currentIndex]
160 }
161
162 Entity {
163 id: renderableEntity
164 components: [ mesh, lod ]
165 }
166 }
167 \endcode
168*/
169
170
171/*!
172 * \enum Qt3DRender::QLevelOfDetail::ThresholdType
173 *
174 * Specifies how the values in the thresholds are interpreted
175 *
176 * \value DistanceToCameraThreshold Distance from the entity to the selected camera
177 * \value ProjectedScreenPixelSizeThreshold Size of the entity when projected on the
178 * screen as seen from the selected camera, expressed in number of
179 * pixels on the side of the bounding square in screen space.
180 */
181
182/*!
183 * \qmlproperty enumeration LevelOfDetail::ThresholdType
184 *
185 * Specifies how the values in the thresholds are interpreted
186 *
187 * \list
188 * \li DistanceToCameraThreshold Distance from the entity to the selected camera
189 * \li ProjectedScreenPixelSizeThreshold Size of the entity when projected on the
190 * screen as seen from the selected camera, expressed in number of
191 * pixels on the side of the bounding square in screen space.
192 * \endlist
193 * \sa Qt3DRender::QLevelOfDetail::ThresholdType
194 */
195
196/*!
197 * \qmlproperty Camera LevelOfDetail::camera
198 *
199 * Holds the id of the camera that is used to compute the actual distance or the screen size.
200 */
201
202/*!
203 * \property QLevelOfDetail::camera
204 *
205 * Holds the id of the camera that is used to compute the actual distance or the screen size.
206 */
207
208/*!
209 * \qmlproperty int LevelOfDetail::currentIndex
210 *
211 * The index in the range array which matches the current distance to the camera or screen size.
212 */
213
214/*!
215 * \property QLevelOfDetail::currentIndex
216 *
217 * The index in the range array which matches the current distance to the camera or screen size.
218 */
219
220/*!
221 * \qmlproperty int LevelOfDetail::thresholdType
222 *
223 * Specifies how range values are interpreted.
224 */
225
226/*!
227 * \property QLevelOfDetail::thresholdType
228 *
229 * Specifies how range values are interpreted.
230 * \sa Qt3DRender::QLevelOfDetail::ThresholdType
231 */
232
233/*!
234 * \qmlproperty QVector<qreal> LevelOfDetail::thresholds
235 *
236 * Array of range values as float point numbers. The value for the most detailed representation
237 * should be specified first.
238 *
239 * If LevelOfDetail::thresholdType is set to LevelOfDetail.DistanceToCameraThreshold, values should
240 * be specified in ascending order, in camera space coordinates
241 *
242 * If LevelOfDetail::thresholdType is set to LevelOfDetail.ProjectedScreenPixelSizeThreshold, values
243 * should be specified in descending order, in screen space pixels.
244 */
245
246/*!
247 * \property QLevelOfDetail::thresholds
248 *
249 * Array of range values as float point numbers. The value for the most detailed representation
250 * should be specified first.
251 *
252 * If Qt3DRender::QLevelOfDetail::thresholdType is set to
253 * Qt3DRender::QLevelOfDetail::DistanceToCameraThreshold, values should be specified in
254 * ascending order, in camera space coordinates
255 *
256 * If Qt3DRender::QLevelOfDetail::thresholdType is set to
257 * Qt3DRender::QLevelOfDetail::ProjectedScreenPixelSizeThreshold, values should
258 * be specified in descending order, in screen space pixels.
259 *
260 * \sa Qt3DRender::QLevelOfDetail::ThresholdType
261 */
262
263/*!
264 * \qmlproperty int LevelOfDetail::volumeOverride
265 *
266 * Specifies what is used to evaluate the distance or screen size.
267 *
268 * The default is a sphere of radius 1 and centered at the local origin of the entity.
269 * This proxy volume is used to compute the distance to the camera or the size
270 * of the screen projection.
271 *
272 * If this value to null, the bounding volume of the entity is used. Care must be
273 * taken that this bounding volume never becomes invalid.
274 *
275 * \sa Qt3DRender::QLevelOfDetailBoundingSphere
276 */
277
278/*!
279 * \property QLevelOfDetail::volumeOverride
280 *
281 * The default is a sphere of radius 1 and centered at the local origin of the entity.
282 * This proxy volume is used to compute the distance to the camera or the size
283 * of the screen projection.
284 *
285 * If this value to nullptr, the bounding volume of the entity is used. Care must be
286 * taken that this bounding volume never becomes invalid.
287 *
288 * \sa Qt3DRender::QLevelOfDetailBoundingSphere
289 */
290
291
292/*! \fn Qt3DRender::QLevelOfDetail::QLevelOfDetail(Qt3DCore::QNode *parent)
293 Constructs a new QLevelOfDetail with the specified \a parent.
294 */
295QLevelOfDetail::QLevelOfDetail(QNode *parent)
296 : QComponent(*new QLevelOfDetailPrivate, parent)
297{
298}
299
300/*! \internal */
301QLevelOfDetail::~QLevelOfDetail()
302{
303}
304
305/*! \internal */
306QLevelOfDetail::QLevelOfDetail(QLevelOfDetailPrivate &dd, QNode *parent)
307 : QComponent(dd, parent)
308{
309}
310
311/*! \internal */
312Qt3DCore::QNodeCreatedChangeBasePtr QLevelOfDetail::createNodeCreationChange() const
313{
314 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QLevelOfDetailData>::create(arguments: this);
315 auto &data = creationChange->data;
316
317 Q_D(const QLevelOfDetail);
318 if (d->m_camera)
319 data.camera = d->m_camera->id();
320 data.currentIndex = d->m_currentIndex;
321 data.thresholdType = d->m_thresholdType;
322 data.thresholds = d->m_thresholds;
323 data.volumeOverride = d->m_volumeOverride;
324
325 return creationChange;
326}
327
328// TODO Unused remove in Qt6
329void QLevelOfDetail::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &)
330{
331}
332
333QCamera *QLevelOfDetail::camera() const
334{
335 Q_D(const QLevelOfDetail);
336 return d->m_camera;
337}
338
339/*!
340 * Sets the \a camera relative to which distance and size are computed.
341 */
342void QLevelOfDetail::setCamera(QCamera *camera)
343{
344 Q_D(QLevelOfDetail);
345 if (d->m_camera != camera) {
346 d->m_camera = camera;
347 emit cameraChanged(camera: d->m_camera);
348 }
349}
350
351int QLevelOfDetail::currentIndex() const
352{
353 Q_D(const QLevelOfDetail);
354 return d->m_currentIndex;
355}
356
357/*!
358 * Sets the \a currentIndex.
359 *
360 * \note This should not normally be set by the user.
361 *
362 * However, if the component is disabled, then changing the
363 * current index is a simple way of switching between multiple
364 * representations.
365 */
366void QLevelOfDetail::setCurrentIndex(int currentIndex)
367{
368 Q_D(QLevelOfDetail);
369 d->setCurrentIndex(currentIndex);
370}
371
372QLevelOfDetail::ThresholdType QLevelOfDetail::thresholdType() const
373{
374 Q_D(const QLevelOfDetail);
375 return d->m_thresholdType;
376}
377
378/*!
379 * Sets the way thresholds values are interpreted
380 * with parameter \a thresholdType
381 * \sa Qt3DRender::QLevelOfDetail::ThresholdType
382 */
383void QLevelOfDetail::setThresholdType(QLevelOfDetail::ThresholdType thresholdType)
384{
385 Q_D(QLevelOfDetail);
386 if (d->m_thresholdType != thresholdType) {
387 d->m_thresholdType = thresholdType;
388 emit thresholdTypeChanged(thresholdType: d->m_thresholdType);
389 }
390}
391
392QVector<qreal> QLevelOfDetail::thresholds() const
393{
394 Q_D(const QLevelOfDetail);
395 return d->m_thresholds;
396}
397
398QLevelOfDetailBoundingSphere QLevelOfDetail::createBoundingSphere(const QVector3D &center, float radius)
399{
400 return QLevelOfDetailBoundingSphere(center, radius);
401}
402
403/*!
404 * Sets the range values in \a thresholds.
405 * \sa Qt3DRender::QLevelOfDetail::thresholdType
406 */
407void QLevelOfDetail::setThresholds(const QVector<qreal> &thresholds)
408{
409 Q_D(QLevelOfDetail);
410 if (d->m_thresholds != thresholds) {
411 d->m_thresholds = thresholds;
412 emit thresholdsChanged(thresholds: d->m_thresholds);
413 }
414}
415
416QLevelOfDetailBoundingSphere QLevelOfDetail::volumeOverride() const
417{
418 Q_D(const QLevelOfDetail);
419 return d->m_volumeOverride;
420}
421
422void QLevelOfDetail::setVolumeOverride(const QLevelOfDetailBoundingSphere &volumeOverride)
423{
424 Q_D(QLevelOfDetail);
425 if (d->m_volumeOverride != volumeOverride) {
426 d->m_volumeOverride = volumeOverride;
427 emit volumeOverrideChanged(volumeOverride);
428 }
429}
430
431} // namespace Qt3DRender
432
433QT_END_NAMESPACE
434
435#include "moc_qlevelofdetail.cpp"
436

source code of qt3d/src/render/frontend/qlevelofdetail.cpp