1// Copyright (C) 2020 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 "qgeometryview.h"
5#include "qgeometryview_p.h"
6#include "qgeometry_p.h"
7#include "buffervisitor_p.h"
8
9#include <Qt3DCore/QAttribute>
10#include <Qt3DCore/QBuffer>
11#include <Qt3DCore/private/vector3d_p.h>
12
13QT_BEGIN_NAMESPACE
14
15namespace Qt3DCore {
16
17namespace {
18
19class FindExtremePoints : public Buffer3fVisitor
20{
21public:
22 FindExtremePoints()
23 : Buffer3fVisitor()
24 , xMin(0.0f), xMax(0.0f), yMin(0.0f), yMax(0.0f), zMin(0.0f), zMax(0.0f)
25 { }
26
27 float xMin, xMax, yMin, yMax, zMin, zMax;
28 Vector3D xMinPt, xMaxPt, yMinPt, yMaxPt, zMinPt, zMaxPt;
29
30 void visit(uint ndx, float x, float y, float z) override
31 {
32 if (ndx) {
33 if (x < xMin) {
34 xMin = x;
35 xMinPt = Vector3D(x, y, z);
36 }
37 if (x > xMax) {
38 xMax = x;
39 xMaxPt = Vector3D(x, y, z);
40 }
41 if (y < yMin) {
42 yMin = y;
43 yMinPt = Vector3D(x, y, z);
44 }
45 if (y > yMax) {
46 yMax = y;
47 yMaxPt = Vector3D(x, y, z);
48 }
49 if (z < zMin) {
50 zMin = z;
51 zMinPt = Vector3D(x, y, z);
52 }
53 if (z > zMax) {
54 zMax = z;
55 zMaxPt = Vector3D(x, y, z);
56 }
57 } else {
58 xMin = xMax = x;
59 yMin = yMax = y;
60 zMin = zMax = z;
61 xMinPt = xMaxPt = yMinPt = yMaxPt = zMinPt = zMaxPt = Vector3D(x, y, z);
62 }
63 }
64};
65
66class FindMaxDistantPoint : public Buffer3fVisitor
67{
68public:
69 FindMaxDistantPoint()
70 : Buffer3fVisitor()
71 { }
72
73 float maxLengthSquared = 0.0f;
74 bool setReferencePoint = false;
75 bool hasNoPoints = true;
76 Vector3D maxDistPt;
77 Vector3D referencePt;
78
79 void visit(uint ndx, float x, float y, float z) override
80 {
81 Q_UNUSED(ndx);
82 const Vector3D p = Vector3D(x, y, z);
83
84 if (hasNoPoints && setReferencePoint) {
85 maxLengthSquared = 0.0f;
86 referencePt = p;
87 }
88 const float lengthSquared = (p - referencePt).lengthSquared();
89 if ( lengthSquared >= maxLengthSquared ) {
90 maxDistPt = p;
91 maxLengthSquared = lengthSquared;
92 }
93 hasNoPoints = false;
94 }
95};
96
97}
98
99bool BoundingVolumeCalculator::apply(QAttribute *positionAttribute,
100 QAttribute *indexAttribute,
101 int drawVertexCount,
102 bool primitiveRestartEnabled,
103 int primitiveRestartIndex)
104{
105 m_radius = -1.f;
106
107 FindExtremePoints findExtremePoints;
108 if (!findExtremePoints.apply(attribute: positionAttribute, indexAttribute, drawVertexCount,
109 primitiveRestartEnabled, primitiveRestartIndex)) {
110 return false;
111 }
112
113 m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
114 m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
115
116 FindMaxDistantPoint maxDistantPointY;
117 maxDistantPointY.setReferencePoint = true;
118 if (!maxDistantPointY.apply(attribute: positionAttribute, indexAttribute, drawVertexCount,
119 primitiveRestartEnabled, primitiveRestartIndex)) {
120 return false;
121 }
122 if (maxDistantPointY.hasNoPoints)
123 return false;
124
125 //const Vector3D x = maxDistantPointY.referencePt;
126 const Vector3D y = maxDistantPointY.maxDistPt;
127
128 FindMaxDistantPoint maxDistantPointZ;
129 maxDistantPointZ.setReferencePoint = false;
130 maxDistantPointZ.referencePt = y;
131 if (!maxDistantPointZ.apply(attribute: positionAttribute, indexAttribute, drawVertexCount,
132 primitiveRestartEnabled, primitiveRestartIndex))
133 return false;
134 const Vector3D z = maxDistantPointZ.maxDistPt;
135 const Vector3D center = (y + z) * .5f;
136
137 FindMaxDistantPoint maxDistantPointCenter;
138 maxDistantPointCenter.setReferencePoint = false;
139 maxDistantPointCenter.referencePt = center;
140 if (!maxDistantPointCenter.apply(attribute: positionAttribute, indexAttribute, drawVertexCount,
141 primitiveRestartEnabled, primitiveRestartIndex))
142 return false;
143
144 const float radius = (center - maxDistantPointCenter.maxDistPt).length();
145
146 if (center == Vector3D{} && radius < 0.f)
147 return false;
148
149 m_radius = radius;
150 m_center = QVector3D{ center.x(), center.y(), center.z() };
151
152 return true;
153}
154
155
156QGeometryViewPrivate::QGeometryViewPrivate()
157 : QNodePrivate()
158 , m_instanceCount(1)
159 , m_vertexCount(0)
160 , m_indexOffset(0)
161 , m_firstInstance(0)
162 , m_firstVertex(0)
163 , m_indexBufferByteOffset(0)
164 , m_restartIndexValue(-1)
165 , m_verticesPerPatch(0)
166 , m_primitiveRestart(false)
167 , m_geometry(nullptr)
168 , m_primitiveType(QGeometryView::Triangles)
169 , m_dirty(false)
170{
171}
172
173QGeometryViewPrivate::~QGeometryViewPrivate()
174{
175}
176
177QGeometryViewPrivate *QGeometryViewPrivate::get(QGeometryView *q)
178{
179 return q->d_func();
180}
181
182void QGeometryViewPrivate::update()
183{
184 if (!m_blockNotifications)
185 m_dirty = true;
186 QNodePrivate::update();
187}
188
189/*!
190 \qmltype GeometryView
191 \instantiates Qt3DCore::QGeometryView
192 \inqmlmodule Qt3D.Core
193 \inherits Node
194 \since 6.0
195 \brief Encapsulates geometry details.
196
197 A GeometryView holds all the information necessary to handle
198 a Geometry. A Geometry holds the coordinates of the geometry data -
199 GeometryView specifies how to interpret that data.
200 */
201
202/*!
203 \class Qt3DCore::QGeometryView
204 \inmodule Qt3DCore
205 \since 6.0
206 \brief Encapsulates geometry details.
207
208 A GeometryView holds all the information necessary to handle
209 a Geometry. A Geometry holds the coordinates of the geometry data -
210 GeometryView specifies how to interpret that data.
211 */
212
213
214/*!
215 \enum QGeometryView::PrimitiveType
216
217 The type of the primitive.
218
219 \value Points List of points
220 \value Lines List of lines
221 \value LineLoop Connected group of lines connected at ends forming a loop
222 \value LineStrip Connected group of lines
223 \value Triangles List of triangles
224 \value TriangleStrip List of connected triangles
225 \value TriangleFan List of connected triagles where all triangles share the first vertex
226 \value LinesAdjacency Allows geometry shader to access adjacent lines in a line list
227 \value TrianglesAdjacency Allows geometry shader to access adjacent triangles in a triangle list
228 \value LineStripAdjacency Allows geometry shader to access adjacent lines in a line strip
229 \value TriangleStripAdjacency Allows geometry shader to access adjacent triangles in a triangle strip
230 \value Patches Only primitive type accepted by tesselation shader where a patch consists of arbitrary number of vertices
231 */
232
233/*!
234 \qmlproperty int GeometryView::instanceCount
235
236 Holds the instance count.
237 */
238
239/*!
240 \qmlproperty int GeometryView::vertexCount
241
242 Holds the vertex count.
243 */
244
245/*!
246 \qmlproperty int GeometryView::indexOffset
247
248 Holds the base vertex.
249 */
250
251/*!
252 \qmlproperty int GeometryView::firstInstance
253
254 Holds the base instance.
255 */
256
257/*!
258 \qmlproperty int GeometryView::firstVertex
259
260 Holds the first vertex.
261 */
262
263/*!
264 \qmlproperty int GeometryView::indexBufferByteOffset
265
266 Holds the byte offset into the index buffer.
267 */
268
269/*!
270 \qmlproperty int GeometryView::restartIndex
271
272 Holds the restart index.
273 */
274
275/*!
276 \qmlproperty int GeometryView::verticesPerPatch
277
278 Holds vertices per patch.
279 */
280
281/*!
282 \qmlproperty bool GeometryView::primitiveRestart
283
284 Holds the primitive restart flag.
285 */
286
287/*!
288 \qmlproperty Geometry GeometryView::geometry
289
290 Holds the geometry.
291 */
292
293/*!
294 \qmlproperty enumeration GeometryView::primitiveType
295
296 Holds the primitive type.
297
298 \list
299 \li QGeometryView.Points
300 \li QGeometryView.Lines
301 \li QGeometryView.LineLoop
302 \li QGeometryView.LineStrip
303 \li QGeometryView.Triangles
304 \li QGeometryView.TriangleStrip
305 \li QGeometryView.TriangleFan
306 \li QGeometryView.LinesAdjacency
307 \li QGeometryView.TrianglesAdjacency
308 \li QGeometryView.LineStripAdjacency
309 \li QGeometryView.TriangleStripAdjacency
310 \li QGeometryView.Patches
311 \endlist
312 \sa Qt3DCore::QGeometryView::PrimitiveType
313 */
314
315
316/*!
317 Constructs a new QGeometryView with \a parent.
318 */
319QGeometryView::QGeometryView(QNode *parent)
320 : QNode(*new QGeometryViewPrivate(), parent)
321{
322}
323
324/*!
325 \internal
326 */
327QGeometryView::~QGeometryView()
328{
329}
330
331/*!
332 \internal
333 */
334QGeometryView::QGeometryView(QGeometryViewPrivate &dd, QNode *parent)
335 : QNode(dd, parent)
336{
337}
338
339/*!
340 \property QGeometryView::instanceCount
341
342 Holds the instance count.
343 */
344int QGeometryView::instanceCount() const
345{
346 Q_D(const QGeometryView);
347 return d->m_instanceCount;
348}
349
350/*!
351 \property QGeometryView::vertexCount
352
353 Holds the primitive count.
354 */
355int QGeometryView::vertexCount() const
356{
357 Q_D(const QGeometryView);
358 return d->m_vertexCount;
359}
360
361/*!
362 \property QGeometryView::indexOffset
363
364 Holds the base vertex.
365 */
366int QGeometryView::indexOffset() const
367{
368 Q_D(const QGeometryView);
369 return d->m_indexOffset;
370}
371
372/*!
373 \property QGeometryView::firstInstance
374
375 Holds the base instance.
376 */
377int QGeometryView::firstInstance() const
378{
379 Q_D(const QGeometryView);
380 return d->m_firstInstance;
381}
382
383/*!
384 \property QGeometryView::firstVertex
385
386 Holds the base vertex.
387 */
388int QGeometryView::firstVertex() const
389{
390 Q_D(const QGeometryView);
391 return d->m_firstVertex;
392}
393
394/*!
395 \property QGeometryView::indexBufferByteOffset
396
397 Holds the byte offset into the index buffer.
398 */
399int QGeometryView::indexBufferByteOffset() const
400{
401 Q_D(const QGeometryView);
402 return d->m_indexBufferByteOffset;
403}
404
405/*!
406 \property QGeometryView::restartIndexValue
407
408 Holds the restart index.
409 */
410int QGeometryView::restartIndexValue() const
411{
412 Q_D(const QGeometryView);
413 return d->m_restartIndexValue;
414}
415
416/*!
417 \property QGeometryView::verticesPerPatch
418
419 Holds vertices per patch.
420 */
421int QGeometryView::verticesPerPatch() const
422{
423 Q_D(const QGeometryView);
424 return d->m_verticesPerPatch;
425}
426
427/*!
428 \property QGeometryView::primitiveRestartEnabled
429
430 Holds the primitive restart flag.
431 */
432bool QGeometryView::primitiveRestartEnabled() const
433{
434 Q_D(const QGeometryView);
435 return d->m_primitiveRestart;
436}
437
438/*!
439 \property QGeometryView::geometry
440
441 Holds the geometry.
442 */
443QGeometry *QGeometryView::geometry() const
444{
445 Q_D(const QGeometryView);
446 return d->m_geometry;
447}
448
449/*!
450 \property QGeometryView::primitiveType
451
452 Holds the primitive type.
453 */
454QGeometryView::PrimitiveType QGeometryView::primitiveType() const
455{
456 Q_D(const QGeometryView);
457 return d->m_primitiveType;
458}
459
460void QGeometryView::setInstanceCount(int instanceCount)
461{
462 Q_D(QGeometryView);
463 if (d->m_instanceCount == instanceCount)
464 return;
465
466 d->m_instanceCount = instanceCount;
467 emit instanceCountChanged(instanceCount);
468}
469
470void QGeometryView::setVertexCount(int vertexCount)
471{
472 Q_D(QGeometryView);
473 if (d->m_vertexCount == vertexCount)
474 return;
475
476 d->m_vertexCount = vertexCount;
477 emit vertexCountChanged(vertexCount);
478}
479
480void QGeometryView::setIndexOffset(int indexOffset)
481{
482 Q_D(QGeometryView);
483 if (d->m_indexOffset == indexOffset)
484 return;
485
486 d->m_indexOffset = indexOffset;
487 emit indexOffsetChanged(indexOffset);
488}
489
490void QGeometryView::setFirstInstance(int firstInstance)
491{
492 Q_D(QGeometryView);
493 if (d->m_firstInstance == firstInstance)
494 return;
495
496 d->m_firstInstance = firstInstance;
497 emit firstInstanceChanged(firstInstance);
498}
499
500void QGeometryView::setFirstVertex(int firstVertex)
501{
502 Q_D(QGeometryView);
503 if (d->m_firstVertex == firstVertex)
504 return;
505
506 d->m_firstVertex = firstVertex;
507 emit firstVertexChanged(firstVertex);
508}
509
510void QGeometryView::setIndexBufferByteOffset(int offset)
511{
512 Q_D(QGeometryView);
513 if (d->m_indexBufferByteOffset == offset)
514 return;
515
516 d->m_indexBufferByteOffset = offset;
517 emit indexBufferByteOffsetChanged(offset);
518}
519
520void QGeometryView::setRestartIndexValue(int index)
521{
522 Q_D(QGeometryView);
523 if (index == d->m_restartIndexValue)
524 return;
525
526 d->m_restartIndexValue = index;
527 emit restartIndexValueChanged(restartIndexValue: index);
528}
529
530void QGeometryView::setVerticesPerPatch(int verticesPerPatch)
531{
532 Q_D(QGeometryView);
533 if (d->m_verticesPerPatch != verticesPerPatch) {
534 d->m_verticesPerPatch = verticesPerPatch;
535 emit verticesPerPatchChanged(verticesPerPatch);
536 }
537}
538
539void QGeometryView::setPrimitiveRestartEnabled(bool enabled)
540{
541 Q_D(QGeometryView);
542 if (enabled == d->m_primitiveRestart)
543 return;
544
545 d->m_primitiveRestart = enabled;
546 emit primitiveRestartEnabledChanged(primitiveRestartEnabled: enabled);
547}
548
549void QGeometryView::setGeometry(QGeometry *geometry)
550{
551 Q_D(QGeometryView);
552 if (d->m_geometry == geometry)
553 return;
554
555 if (d->m_geometry)
556 d->unregisterDestructionHelper(node: d->m_geometry);
557
558 if (geometry && !geometry->parent())
559 geometry->setParent(this);
560
561 d->m_geometry = geometry;
562
563 // Ensures proper bookkeeping
564 if (d->m_geometry)
565 d->registerDestructionHelper(node: d->m_geometry, func: &QGeometryView::setGeometry, d->m_geometry);
566
567 emit geometryChanged(geometry);
568}
569
570void QGeometryView::setPrimitiveType(QGeometryView::PrimitiveType primitiveType)
571{
572 Q_D(QGeometryView);
573 if (d->m_primitiveType == primitiveType)
574 return;
575
576 d->m_primitiveType = primitiveType;
577 emit primitiveTypeChanged(primitiveType);
578}
579
580} // namespace Qt3DCore
581
582QT_END_NAMESPACE
583
584#include "moc_qgeometryview.cpp"
585

source code of qt3d/src/core/geometry/qgeometryview.cpp