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 "qcuboidgeometry.h"
41#include "qcuboidgeometry_p.h"
42
43#include <Qt3DRender/qattribute.h>
44#include <Qt3DRender/qbuffer.h>
45#include <Qt3DRender/qbufferdatagenerator.h>
46#include <Qt3DRender/private/renderlogging_p.h>
47
48#include <limits>
49
50
51QT_BEGIN_NAMESPACE
52
53using namespace Qt3DRender;
54
55namespace Qt3DExtras {
56
57namespace {
58
59enum PlaneNormal {
60 PositiveX,
61 NegativeX,
62 PositiveY,
63 NegativeY,
64 PositiveZ,
65 NegativeZ
66};
67
68void createPlaneVertexData(float w, float h, const QSize &resolution,
69 PlaneNormal normal, float planeDistance,
70 float *vertices)
71{
72 const float a0 = -w / 2.0f;
73 const float b0 = -h / 2.0f;
74 const float da = w / (resolution.width() - 1);
75 const float db = h / (resolution.height() - 1);
76 const float du = 1.0f / (resolution.width() - 1);
77 const float dv = 1.0f / (resolution.height() - 1);
78
79 switch (normal) {
80 case NegativeX:
81 // Iterate over z
82 for (int j = resolution.height() - 1; j >= 0; --j) {
83 const float b = b0 + static_cast<float>(j) * db;
84 const float v = static_cast<float>(j) * dv;
85
86 // Iterate over y
87 for (int i = 0; i < resolution.width(); ++i) {
88 const float a = a0 + static_cast<float>(i) * da;
89 const float u = static_cast<float>(i) * du;
90
91 // position
92 *vertices++ = planeDistance;
93 *vertices++ = a;
94 *vertices++ = b;
95
96 // texture coordinates
97 *vertices++ = v;
98 *vertices++ = u;
99
100 // normal
101 *vertices++ = -1.0f;
102 *vertices++ = 0.0f;
103 *vertices++ = 0.0f;
104
105 // tangent
106 *vertices++ = 0.0f;
107 *vertices++ = 0.0f;
108 *vertices++ = 1.0f;
109 *vertices++ = 1.0f;
110 }
111 }
112 break;
113
114 case PositiveX: {
115 // Iterate over z
116 for (int j = 0; j < resolution.height(); ++j) {
117 const float b = b0 + static_cast<float>(j) * db;
118 const float v = static_cast<float>(j) * dv;
119
120 // Iterate over y
121 for (int i = 0; i < resolution.width(); ++i) {
122 const float a = a0 + static_cast<float>(i) * da;
123 const float u = static_cast<float>(i) * du;
124
125 // position
126 *vertices++ = planeDistance;
127 *vertices++ = a;
128 *vertices++ = b;
129
130 // texture coordinates
131 *vertices++ = 1.0f - v;
132 *vertices++ = u;
133
134 // normal
135 *vertices++ = 1.0f;
136 *vertices++ = 0.0f;
137 *vertices++ = 0.0f;
138
139 // tangent
140 *vertices++ = 0.0f;
141 *vertices++ = 0.0f;
142 *vertices++ = -1.0f;
143 *vertices++ = 1.0f;
144 }
145 }
146 break;
147 }
148
149 case NegativeY:
150 // Iterate over z
151 for (int j = 0; j < resolution.height(); ++j) {
152 const float b = b0 + static_cast<float>(j) * db;
153 const float v = static_cast<float>(j) * dv;
154
155 // Iterate over x
156 // This iterates in the opposite sense to the other directions
157 // so that the winding order is correct
158 for (int i = 0; i < resolution.width(); ++i) {
159 const float a = a0 + static_cast<float>(i) * da;
160 const float u = static_cast<float>(i) * du;
161
162 // position
163 *vertices++ = a;
164 *vertices++ = planeDistance;
165 *vertices++ = b;
166
167 // texture coordinates
168 *vertices++ = u;
169 *vertices++ = v;
170
171 // normal
172 *vertices++ = 0.0f;
173 *vertices++ = -1.0f;
174 *vertices++ = 0.0f;
175
176 // tangent
177 *vertices++ = 1.0f;
178 *vertices++ = 0.0f;
179 *vertices++ = 0.0f;
180 *vertices++ = 1.0f;
181 }
182 }
183 break;
184
185 case PositiveY: {
186 // Iterate over z
187 for (int j = resolution.height() - 1; j >= 0; --j) {
188 const float b = b0 + static_cast<float>(j) * db;
189 const float v = static_cast<float>(j) * dv;
190
191 // Iterate over x
192 // This iterates in the opposite sense to the other directions
193 // so that the winding order is correct
194 for (int i = 0; i < resolution.width(); ++i) {
195 const float a = a0 + static_cast<float>(i) * da;
196 const float u = static_cast<float>(i) * du;
197
198 // position
199 *vertices++ = a;
200 *vertices++ = planeDistance;
201 *vertices++ = b;
202
203 // texture coordinates
204 *vertices++ = u;
205 *vertices++ = 1.0f - v;
206
207 // normal
208 *vertices++ = 0.0f;
209 *vertices++ = 1.0f;
210 *vertices++ = 0.0f;
211
212 // tangent
213 *vertices++ = 1.0f;
214 *vertices++ = 0.0f;
215 *vertices++ = 0.0f;
216 *vertices++ = 1.0f;
217 }
218 }
219 break;
220 }
221
222 case NegativeZ:
223 // Iterate over y
224 for (int j = 0; j < resolution.height(); ++j) {
225 const float b = b0 + static_cast<float>(j) * db;
226 const float v = static_cast<float>(j) * dv;
227
228 // Iterate over x
229 for (int i = resolution.width() - 1; i >= 0; --i) {
230 const float a = a0 + static_cast<float>(i) * da;
231 const float u = static_cast<float>(i) * du;
232
233 // position
234 *vertices++ = a;
235 *vertices++ = b;
236 *vertices++ = planeDistance;
237
238 // texture coordinates
239 *vertices++ = 1.0f - u;
240 *vertices++ = v;
241
242 // normal
243 *vertices++ = 0.0f;
244 *vertices++ = 0.0f;
245 *vertices++ = -1.0f;
246
247 // tangent
248 *vertices++ = -1.0f;
249 *vertices++ = 0.0f;
250 *vertices++ = 0.0f;
251 *vertices++ = 1.0f;
252 }
253 }
254 break;
255
256 case PositiveZ: {
257 // Iterate over y
258 for (int j = 0; j < resolution.height(); ++j) {
259 const float b = b0 + static_cast<float>(j) * db;
260 const float v = static_cast<float>(j) * dv;
261
262 // Iterate over x
263 for (int i = 0; i < resolution.width(); ++i) {
264 const float a = a0 + static_cast<float>(i) * da;
265 const float u = static_cast<float>(i) * du;
266
267 // position
268 *vertices++ = a;
269 *vertices++ = b;
270 *vertices++ = planeDistance;
271
272 // texture coordinates
273 *vertices++ = u;
274 *vertices++ = v;
275
276 // normal
277 *vertices++ = 0.0f;
278 *vertices++ = 0.0f;
279 *vertices++ = 1.0f;
280
281 // tangent
282 *vertices++ = 1.0f;
283 *vertices++ = 0.0f;
284 *vertices++ = 0.0f;
285 *vertices++ = 1.0f;
286 }
287 }
288 break;
289 }
290 } // switch (normal)
291}
292
293void createPlaneIndexData(const QSize &resolution, quint16 *indices, quint16 &baseVertex)
294{
295 // Populate indices taking care to get correct CCW winding on all faces
296 // Iterate over v direction (rows)
297 for (int j = 0; j < resolution.height() - 1; ++j) {
298 const int rowStartIndex = j * resolution.width() + baseVertex;
299 const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex;
300
301 // Iterate over u direction (columns)
302 for (int i = 0; i < resolution.width() - 1; ++i) {
303 // Split quad into two triangles
304 *indices++ = rowStartIndex + i;
305 *indices++ = rowStartIndex + i + 1;
306 *indices++ = nextRowStartIndex + i;
307
308 *indices++ = nextRowStartIndex + i;
309 *indices++ = rowStartIndex + i + 1;
310 *indices++ = nextRowStartIndex + i + 1;
311 }
312 }
313 baseVertex += resolution.width() * resolution.height();
314}
315
316QByteArray createCuboidVertexData(float xExtent,
317 float yExtent,
318 float zExtent,
319 const QSize &yzResolution,
320 const QSize &xzResolution,
321 const QSize &xyResolution)
322{
323 Q_ASSERT(xExtent > 0.0f && yExtent > 0.0f && zExtent > 0.0);
324 Q_ASSERT(yzResolution.width() >= 2 && yzResolution.height() >=2);
325 Q_ASSERT(xzResolution.width() >= 2 && xzResolution.height() >=2);
326 Q_ASSERT(xyResolution.width() >= 2 && xyResolution.height() >=2);
327
328 const int yzVerts = yzResolution.width() * yzResolution.height();
329 const int xzVerts = xzResolution.width() * xzResolution.height();
330 const int xyVerts = xyResolution.width() * xyResolution.height();
331 const int nVerts = 2 * (yzVerts + xzVerts + xyVerts);
332
333 const quint32 elementSize = 3 + 3 + 2 + 4;
334 const quint32 stride = elementSize * sizeof(float);
335 QByteArray vertexBytes;
336 vertexBytes.resize(size: stride * nVerts);
337 float* vertices = reinterpret_cast<float*>(vertexBytes.data());
338
339 createPlaneVertexData(w: yExtent, h: zExtent, resolution: yzResolution, normal: PositiveX, planeDistance: xExtent * 0.5f, vertices);
340 vertices += yzVerts * elementSize;
341 createPlaneVertexData(w: yExtent, h: zExtent, resolution: yzResolution, normal: NegativeX, planeDistance: -xExtent * 0.5f, vertices);
342 vertices += yzVerts * elementSize;
343 createPlaneVertexData(w: xExtent, h: zExtent, resolution: xzResolution, normal: PositiveY, planeDistance: yExtent * 0.5f, vertices);
344 vertices += xzVerts * elementSize;
345 createPlaneVertexData(w: xExtent, h: zExtent, resolution: xzResolution, normal: NegativeY, planeDistance: -yExtent * 0.5f, vertices);
346 vertices += xzVerts * elementSize;
347 createPlaneVertexData(w: xExtent, h: yExtent, resolution: xyResolution, normal: PositiveZ, planeDistance: zExtent * 0.5f, vertices);
348 vertices += xyVerts * elementSize;
349 createPlaneVertexData(w: xExtent, h: yExtent, resolution: xyResolution, normal: NegativeZ, planeDistance: -zExtent * 0.5f, vertices);
350
351 return vertexBytes;
352}
353
354QByteArray createCuboidIndexData(const QSize &yzResolution,
355 const QSize &xzResolution,
356 const QSize &xyResolution)
357{
358 Q_ASSERT(yzResolution.width() >= 2 && yzResolution.height() >= 2);
359 Q_ASSERT(xzResolution.width() >= 2 && xzResolution.height() >= 2);
360 Q_ASSERT(xyResolution.width() >= 2 && xyResolution.height() >= 2);
361
362 const int yzIndices = 2 * 3 * (yzResolution.width() - 1) * (yzResolution.height() - 1);
363 const int xzIndices = 2 * 3 * (xzResolution.width() - 1) * (xzResolution.height() - 1);
364 const int xyIndices = 2 * 3 * (xyResolution.width() - 1) * (xyResolution.height() - 1);
365 const int indexCount = 2 * (yzIndices + xzIndices + xyIndices);
366
367 QByteArray indexData;
368 indexData.resize(size: indexCount * sizeof(quint16));
369 quint16 *indices = reinterpret_cast<quint16 *>(indexData.data());
370 quint16 baseIndex = 0;
371
372 createPlaneIndexData(resolution: yzResolution, indices, baseVertex&: baseIndex);
373 indices += yzIndices;
374 createPlaneIndexData(resolution: yzResolution, indices, baseVertex&: baseIndex);
375 indices += yzIndices;
376 createPlaneIndexData(resolution: xzResolution, indices, baseVertex&: baseIndex);
377 indices += xzIndices;
378 createPlaneIndexData(resolution: xzResolution, indices, baseVertex&: baseIndex);
379 indices += xzIndices;
380 createPlaneIndexData(resolution: xyResolution, indices, baseVertex&: baseIndex);
381 indices += xyIndices;
382 createPlaneIndexData(resolution: xyResolution, indices, baseVertex&: baseIndex);
383
384 return indexData;
385}
386
387} // anonymous
388
389class CuboidVertexBufferFunctor : public QBufferDataGenerator
390{
391public:
392 explicit CuboidVertexBufferFunctor(float xExtent,
393 float yExtent,
394 float zExtent,
395 const QSize &yzResolution,
396 const QSize &xzResolution,
397 const QSize &xyResolution)
398 : m_xExtent(xExtent)
399 , m_yExtent(yExtent)
400 , m_zExtent(zExtent)
401 , m_yzFaceResolution(yzResolution)
402 , m_xzFaceResolution(xzResolution)
403 , m_xyFaceResolution(xyResolution)
404 {}
405
406 ~CuboidVertexBufferFunctor() {}
407
408 QByteArray operator()() final
409 {
410 return createCuboidVertexData(xExtent: m_xExtent, yExtent: m_yExtent, zExtent: m_zExtent,
411 yzResolution: m_yzFaceResolution, xzResolution: m_xzFaceResolution, xyResolution: m_xyFaceResolution);
412 }
413
414 bool operator ==(const QBufferDataGenerator &other) const final
415 {
416 const CuboidVertexBufferFunctor *otherFunctor = functor_cast<CuboidVertexBufferFunctor>(other: &other);
417 if (otherFunctor != nullptr)
418 return (otherFunctor->m_xExtent == m_xExtent &&
419 otherFunctor->m_yExtent == m_yExtent &&
420 otherFunctor->m_zExtent == m_zExtent &&
421 otherFunctor->m_yzFaceResolution == m_yzFaceResolution &&
422 otherFunctor->m_xzFaceResolution == m_xzFaceResolution &&
423 otherFunctor->m_xyFaceResolution == m_xyFaceResolution);
424 return false;
425 }
426
427 QT3D_FUNCTOR(CuboidVertexBufferFunctor)
428
429private:
430 float m_xExtent;
431 float m_yExtent;
432 float m_zExtent;
433 QSize m_yzFaceResolution;
434 QSize m_xzFaceResolution;
435 QSize m_xyFaceResolution;
436};
437
438class CuboidIndexBufferFunctor : public QBufferDataGenerator
439{
440public:
441 explicit CuboidIndexBufferFunctor(const QSize &yzResolution,
442 const QSize &xzResolution,
443 const QSize &xyResolution)
444 : m_yzFaceResolution(yzResolution)
445 , m_xzFaceResolution(xzResolution)
446 , m_xyFaceResolution(xyResolution)
447 {}
448
449 ~CuboidIndexBufferFunctor() {}
450
451 QByteArray operator()() final
452 {
453 return createCuboidIndexData(yzResolution: m_yzFaceResolution, xzResolution: m_xzFaceResolution, xyResolution: m_xyFaceResolution);
454 }
455
456 bool operator ==(const QBufferDataGenerator &other) const final
457 {
458 const CuboidIndexBufferFunctor *otherFunctor = functor_cast<CuboidIndexBufferFunctor>(other: &other);
459 if (otherFunctor != nullptr)
460 return (otherFunctor->m_yzFaceResolution == m_yzFaceResolution &&
461 otherFunctor->m_xzFaceResolution == m_xzFaceResolution &&
462 otherFunctor->m_xyFaceResolution == m_xyFaceResolution);
463 return false;
464 }
465
466 QT3D_FUNCTOR(CuboidIndexBufferFunctor)
467
468private:
469 QSize m_yzFaceResolution;
470 QSize m_xzFaceResolution;
471 QSize m_xyFaceResolution;
472};
473
474QCuboidGeometryPrivate::QCuboidGeometryPrivate()
475 : QGeometryPrivate()
476 , m_xExtent(1.0f)
477 , m_yExtent(1.0f)
478 , m_zExtent(1.0f)
479 , m_yzFaceResolution(2, 2)
480 , m_xzFaceResolution(2, 2)
481 , m_xyFaceResolution(2, 2)
482 , m_positionAttribute(nullptr)
483 , m_normalAttribute(nullptr)
484 , m_texCoordAttribute(nullptr)
485 , m_tangentAttribute(nullptr)
486 , m_indexAttribute(nullptr)
487 , m_vertexBuffer(nullptr)
488 , m_indexBuffer(nullptr)
489{
490}
491
492void QCuboidGeometryPrivate::init()
493{
494 Q_Q(QCuboidGeometry);
495 m_positionAttribute = new Qt3DRender::QAttribute(q);
496 m_normalAttribute = new Qt3DRender::QAttribute(q);
497 m_texCoordAttribute = new Qt3DRender::QAttribute(q);
498 m_tangentAttribute = new Qt3DRender::QAttribute(q);
499 m_indexAttribute = new Qt3DRender::QAttribute(q);
500 m_vertexBuffer = new Qt3DRender::QBuffer(q);
501 m_indexBuffer = new Qt3DRender::QBuffer(q);
502
503 // vec3 pos vec2 tex vec3 normal vec4 tangent
504 const quint32 stride = (3 + 2 + 3 + 4) * sizeof(float);
505 const int yzIndices = 2 * 3 * (m_yzFaceResolution.width() - 1) * (m_yzFaceResolution.height() - 1);
506 const int xzIndices = 2 * 3 * (m_xzFaceResolution.width() - 1) * (m_xzFaceResolution.height() - 1);
507 const int xyIndices = 2 * 3 * (m_xyFaceResolution.width() - 1) * (m_xyFaceResolution.height() - 1);
508 const int yzVerts = m_yzFaceResolution.width() * m_yzFaceResolution.height();
509 const int xzVerts = m_xzFaceResolution.width() * m_xzFaceResolution.height();
510 const int xyVerts = m_xyFaceResolution.width() * m_xyFaceResolution.height();
511
512 const int nVerts = 2 * (yzVerts + xzVerts + xyVerts);
513 const int indexCount = 2 * (yzIndices + xzIndices + xyIndices);
514
515 m_positionAttribute->setName(QAttribute::defaultPositionAttributeName());
516 m_positionAttribute->setVertexBaseType(QAttribute::Float);
517 m_positionAttribute->setVertexSize(3);
518 m_positionAttribute->setAttributeType(QAttribute::VertexAttribute);
519 m_positionAttribute->setBuffer(m_vertexBuffer);
520 m_positionAttribute->setByteStride(stride);
521 m_positionAttribute->setCount(nVerts);
522
523 m_texCoordAttribute->setName(QAttribute::defaultTextureCoordinateAttributeName());
524 m_texCoordAttribute->setVertexBaseType(QAttribute::Float);
525 m_texCoordAttribute->setVertexSize(2);
526 m_texCoordAttribute->setAttributeType(QAttribute::VertexAttribute);
527 m_texCoordAttribute->setBuffer(m_vertexBuffer);
528 m_texCoordAttribute->setByteStride(stride);
529 m_texCoordAttribute->setByteOffset(3 * sizeof(float));
530 m_texCoordAttribute->setCount(nVerts);
531
532 m_normalAttribute->setName(QAttribute::defaultNormalAttributeName());
533 m_normalAttribute->setVertexBaseType(QAttribute::Float);
534 m_normalAttribute->setVertexSize(3);
535 m_normalAttribute->setAttributeType(QAttribute::VertexAttribute);
536 m_normalAttribute->setBuffer(m_vertexBuffer);
537 m_normalAttribute->setByteStride(stride);
538 m_normalAttribute->setByteOffset(5 * sizeof(float));
539 m_normalAttribute->setCount(nVerts);
540
541 m_tangentAttribute->setName(QAttribute::defaultTangentAttributeName());
542 m_tangentAttribute->setVertexBaseType(QAttribute::Float);
543 m_tangentAttribute->setVertexSize(4);
544 m_tangentAttribute->setAttributeType(QAttribute::VertexAttribute);
545 m_tangentAttribute->setBuffer(m_vertexBuffer);
546 m_tangentAttribute->setByteStride(stride);
547 m_tangentAttribute->setByteOffset(8 * sizeof(float));
548 m_tangentAttribute->setCount(nVerts);
549
550 m_indexAttribute->setAttributeType(QAttribute::IndexAttribute);
551 m_indexAttribute->setVertexBaseType(QAttribute::UnsignedShort);
552 m_indexAttribute->setBuffer(m_indexBuffer);
553
554 m_indexAttribute->setCount(indexCount);
555
556 m_vertexBuffer->setDataGenerator(QSharedPointer<CuboidVertexBufferFunctor>::create(arguments&: m_xExtent, arguments&: m_yExtent, arguments&: m_zExtent,
557 arguments&: m_yzFaceResolution, arguments&: m_xzFaceResolution, arguments&: m_xyFaceResolution));
558 m_indexBuffer->setDataGenerator(QSharedPointer<CuboidIndexBufferFunctor>::create(arguments&: m_yzFaceResolution, arguments&: m_xzFaceResolution, arguments&: m_xyFaceResolution));
559
560 q->addAttribute(attribute: m_positionAttribute);
561 q->addAttribute(attribute: m_texCoordAttribute);
562 q->addAttribute(attribute: m_normalAttribute);
563 q->addAttribute(attribute: m_tangentAttribute);
564 q->addAttribute(attribute: m_indexAttribute);
565}
566
567/*!
568 * \qmltype CuboidGeometry
569 * \instantiates Qt3DExtras::QCuboidGeometry
570 * \inqmlmodule Qt3D.Extras
571 * \brief CuboidGeometry allows creation of a cuboid in 3D space.
572 *
573 * The CuboidGeometry type is most commonly used internally by the CuboidMesh type
574 * but can also be used in custom GeometryRenderer types.
575 */
576
577/*!
578 * \qmlproperty real CuboidGeometry::xExtent
579 *
580 * Holds the x extent of the geometry.
581 */
582
583/*!
584 * \qmlproperty real CuboidGeometry::yExtent
585 *
586 * Holds the y extent of the geometry.
587 */
588
589/*!
590 * \qmlproperty real CuboidGeometry::zExtent
591 *
592 * Holds the z extent of the geometry.
593 */
594
595/*!
596 * \qmlproperty size CuboidGeometry::yzMeshResolution
597 *
598 * Holds the y-z resolution.
599 * The width and height values of this property specify the number of vertices generated for
600 * the y-z faces of the mesh.
601 */
602
603/*!
604 * \qmlproperty size CuboidGeometry::xzMeshResolution
605 *
606 * Holds the x-z resolution.
607 * The width and height values of this property specify the number of vertices generated for
608 * the x-z faces of the mesh.
609 */
610
611/*!
612 * \qmlproperty size CuboidGeometry::xyMeshResolution
613 *
614 * Holds the x-y resolution.
615 * The width and height values of this property specify the number of vertices generated for
616 * the x-y faces of the mesh.
617 */
618
619/*!
620 * \qmlproperty Attribute CuboidGeometry::positionAttribute
621 *
622 * Holds the geometry position attribute.
623 */
624
625/*!
626 * \qmlproperty Attribute CuboidGeometry::normalAttribute
627 *
628 * Holds the geometry normal attribute.
629 */
630
631/*!
632 * \qmlproperty Attribute CuboidGeometry::texCoordAttribute
633 *
634 * Holds the geometry texture coordinate attribute.
635 */
636
637/*!
638 * \qmlproperty Attribute CuboidGeometry::tangentAttribute
639 *
640 * Holds the geometry tangent attribute.
641 */
642
643/*!
644 * \qmlproperty Attribute CuboidGeometry::indexAttribute
645 *
646 * Holds the geometry index attribute.
647 */
648
649/*!
650 * \class Qt3DExtras::QCuboidGeometry
651 \ingroup qt3d-extras-geometries
652 * \inheaderfile Qt3DExtras/QCuboidGeometry
653 * \inmodule Qt3DExtras
654 * \brief The QCuboidGeometry class allows creation of a cuboid in 3D space.
655 * \since 5.7
656 * \ingroup geometries
657 * \inherits Qt3DRender::QGeometry
658 *
659 * The QCuboidGeometry class is most commonly used internally by the QCuboidMesh
660 * but can also be used in custom Qt3DRender::QGeometryRenderer subclasses.
661 */
662
663/*!
664 * Constructs a new QCuboidGeometry with \a parent.
665 */
666QCuboidGeometry::QCuboidGeometry(QNode *parent)
667 : QGeometry(*new QCuboidGeometryPrivate(), parent)
668{
669 Q_D(QCuboidGeometry);
670 d->init();
671}
672
673/*!
674 * \internal
675 */
676QCuboidGeometry::QCuboidGeometry(QCuboidGeometryPrivate &dd, QNode *parent)
677 : QGeometry(dd, parent)
678{
679 Q_D(QCuboidGeometry);
680 d->init();
681}
682
683/*!
684 * \internal
685 */
686QCuboidGeometry::~QCuboidGeometry()
687{
688}
689
690/*!
691 * Updates indices based on mesh resolutions.
692 */
693void QCuboidGeometry::updateIndices()
694{
695 Q_D(QCuboidGeometry);
696 const int yzIndices = 2 * 3 * (d->m_yzFaceResolution.width() - 1) * (d->m_yzFaceResolution.height() - 1);
697 const int xzIndices = 2 * 3 * (d->m_xzFaceResolution.width() - 1) * (d->m_xzFaceResolution.height() - 1);
698 const int xyIndices = 2 * 3 * (d->m_xyFaceResolution.width() - 1) * (d->m_xyFaceResolution.height() - 1);
699 const int indexCount = 2 * (yzIndices + xzIndices + xyIndices);
700
701 d->m_indexAttribute->setCount(indexCount);
702 d->m_indexBuffer->setDataGenerator(QSharedPointer<CuboidIndexBufferFunctor>::create(arguments&: d->m_yzFaceResolution, arguments&: d->m_xzFaceResolution, arguments&: d->m_xyFaceResolution));
703
704}
705
706/*!
707 * Updates vertices based on mesh resolutions.
708 */
709void QCuboidGeometry::updateVertices()
710{
711 Q_D(QCuboidGeometry);
712 const int yzVerts = d->m_yzFaceResolution.width() * d->m_yzFaceResolution.height();
713 const int xzVerts = d->m_xzFaceResolution.width() * d->m_xzFaceResolution.height();
714 const int xyVerts = d->m_xyFaceResolution.width() * d->m_xyFaceResolution.height();
715 const int nVerts = 2 * (yzVerts + xzVerts + xyVerts);
716
717 d->m_positionAttribute->setCount(nVerts);
718 d->m_normalAttribute->setCount(nVerts);
719 d->m_texCoordAttribute->setCount(nVerts);
720 d->m_tangentAttribute->setCount(nVerts);
721
722 d->m_vertexBuffer->setDataGenerator(QSharedPointer<CuboidVertexBufferFunctor>::create(arguments&: d->m_xExtent, arguments&: d->m_yExtent, arguments&: d->m_zExtent,
723 arguments&: d->m_yzFaceResolution, arguments&: d->m_xzFaceResolution, arguments&: d->m_xyFaceResolution));
724}
725
726void QCuboidGeometry::setXExtent(float xExtent)
727{
728 Q_D(QCuboidGeometry);
729 if (d->m_xExtent != xExtent) {
730 d->m_xExtent = xExtent;
731 updateVertices();
732 emit xExtentChanged(xExtent);
733 }
734}
735
736void QCuboidGeometry::setYExtent(float yExtent)
737{
738 Q_D(QCuboidGeometry);
739 if (d->m_yExtent != yExtent) {
740 d->m_yExtent = yExtent;
741 updateVertices();
742 emit yExtentChanged(yExtent);
743 }
744}
745
746void QCuboidGeometry::setZExtent(float zExtent)
747{
748 Q_D(QCuboidGeometry);
749 if (d->m_zExtent != zExtent) {
750 d->m_zExtent = zExtent;
751 updateVertices();
752 emit zExtentChanged(zExtent);
753 }
754}
755
756void QCuboidGeometry::setYZMeshResolution(const QSize &resolution)
757{
758 Q_D(QCuboidGeometry);
759 if (d->m_yzFaceResolution != resolution) {
760 d->m_yzFaceResolution = resolution;
761 updateVertices();
762 updateIndices();
763 emit yzMeshResolutionChanged(yzMeshResolution: resolution);
764 }
765}
766
767void QCuboidGeometry::setXZMeshResolution(const QSize &resolution)
768{
769 Q_D(QCuboidGeometry);
770 if (d->m_xzFaceResolution != resolution) {
771 d->m_xzFaceResolution = resolution;
772 updateVertices();
773 updateIndices();
774 emit xzMeshResolutionChanged(xzMeshResolution: resolution);
775 }
776}
777
778void QCuboidGeometry::setXYMeshResolution(const QSize &resolution)
779{
780 Q_D(QCuboidGeometry);
781 if (d->m_xyFaceResolution != resolution) {
782 d->m_xyFaceResolution = resolution;
783 updateVertices();
784 updateIndices();
785 emit xyMeshResolutionChanged(xyMeshResolution: resolution);
786 }
787}
788
789/*!
790 * \property QCuboidGeometry::xExtent
791 *
792 * Holds the x extent of the geometry.
793 */
794float QCuboidGeometry::xExtent() const
795{
796 Q_D(const QCuboidGeometry);
797 return d->m_xExtent;
798}
799
800/*!
801 * \property QCuboidGeometry::yExtent
802 *
803 * Holds the y extent of the geometry.
804 */
805float QCuboidGeometry::yExtent() const
806{
807 Q_D(const QCuboidGeometry);
808 return d->m_yExtent;
809}
810
811/*!
812 * \property QCuboidGeometry::zExtent
813 *
814 * Holds the z extent of the geometry.
815 */
816float QCuboidGeometry::zExtent() const
817{
818 Q_D(const QCuboidGeometry);
819 return d->m_zExtent;
820}
821
822/*!
823 * \property QCuboidGeometry::yzMeshResolution
824 *
825 * Holds the y-z resolution.
826 * The width and height values of this property specify the number of vertices generated for
827 * the y-z faces of the mesh.
828 */
829QSize QCuboidGeometry::yzMeshResolution() const
830{
831 Q_D(const QCuboidGeometry);
832 return d->m_yzFaceResolution;
833}
834
835/*!
836 * \property QCuboidGeometry::xzMeshResolution
837 *
838 * Holds the x-z resolution.
839 * The width and height values of this property specify the number of vertices generated for
840 * the x-z faces of the mesh.
841 */
842QSize QCuboidGeometry::xyMeshResolution() const
843{
844 Q_D(const QCuboidGeometry);
845 return d->m_xyFaceResolution;
846}
847
848/*!
849 * \property QCuboidGeometry::xyMeshResolution
850 *
851 * Holds the x-y resolution.
852 * The width and height values of this property specify the number of vertices generated for
853 * the x-y faces of the mesh.
854 */
855QSize QCuboidGeometry::xzMeshResolution() const
856{
857 Q_D(const QCuboidGeometry);
858 return d->m_xzFaceResolution;
859}
860
861/*!
862 * \property QCuboidGeometry::positionAttribute
863 *
864 * Holds the geometry position attribute.
865 */
866QAttribute *QCuboidGeometry::positionAttribute() const
867{
868 Q_D(const QCuboidGeometry);
869 return d->m_positionAttribute;
870}
871
872/*!
873 * \property QCuboidGeometry::normalAttribute
874 *
875 * Holds the geometry normal attribute.
876 */
877QAttribute *QCuboidGeometry::normalAttribute() const
878{
879 Q_D(const QCuboidGeometry);
880 return d->m_normalAttribute;
881}
882
883/*!
884 * \property QCuboidGeometry::texCoordAttribute
885 *
886 * Holds the geometry texture coordinate attribute.
887 */
888QAttribute *QCuboidGeometry::texCoordAttribute() const
889{
890 Q_D(const QCuboidGeometry);
891 return d->m_texCoordAttribute;
892}
893
894/*!
895 * \property QCuboidGeometry::tangentAttribute
896 *
897 * Holds the geometry tangent attribute.
898 */
899QAttribute *QCuboidGeometry::tangentAttribute() const
900{
901 Q_D(const QCuboidGeometry);
902 return d->m_tangentAttribute;
903}
904
905/*!
906 * \property QCuboidGeometry::indexAttribute
907 *
908 * Holds the geometry index attribute.
909 */
910QAttribute *QCuboidGeometry::indexAttribute() const
911{
912 Q_D(const QCuboidGeometry);
913 return d->m_indexAttribute;
914}
915
916} // Qt3DExtras
917
918QT_END_NAMESPACE
919

source code of qt3d/src/extras/geometries/qcuboidgeometry.cpp