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
51 QT_BEGIN_NAMESPACE
52
53 using namespace Qt3DRender;
54
55 namespace Qt3DExtras {
56
57 namespace {
58
59 enum PlaneNormal {
60 PositiveX,
61 NegativeX,
62 PositiveY,
63 NegativeY,
64 PositiveZ,
65 NegativeZ
66 };
67
createPlaneVertexData(float w,float h,const QSize & resolution,PlaneNormal normal,float planeDistance,float * vertices)68 void 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
createPlaneIndexData(const QSize & resolution,quint16 * indices,quint16 & baseVertex)293 void 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
createCuboidVertexData(float xExtent,float yExtent,float zExtent,const QSize & yzResolution,const QSize & xzResolution,const QSize & xyResolution)316 QByteArray 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(stride * nVerts);
337 float* vertices = reinterpret_cast<float*>(vertexBytes.data());
338
339 createPlaneVertexData(yExtent, zExtent, yzResolution, PositiveX, xExtent * 0.5f, vertices);
340 vertices += yzVerts * elementSize;
341 createPlaneVertexData(yExtent, zExtent, yzResolution, NegativeX, -xExtent * 0.5f, vertices);
342 vertices += yzVerts * elementSize;
343 createPlaneVertexData(xExtent, zExtent, xzResolution, PositiveY, yExtent * 0.5f, vertices);
344 vertices += xzVerts * elementSize;
345 createPlaneVertexData(xExtent, zExtent, xzResolution, NegativeY, -yExtent * 0.5f, vertices);
346 vertices += xzVerts * elementSize;
347 createPlaneVertexData(xExtent, yExtent, xyResolution, PositiveZ, zExtent * 0.5f, vertices);
348 vertices += xyVerts * elementSize;
349 createPlaneVertexData(xExtent, yExtent, xyResolution, NegativeZ, -zExtent * 0.5f, vertices);
350
351 return vertexBytes;
352 }
353
createCuboidIndexData(const QSize & yzResolution,const QSize & xzResolution,const QSize & xyResolution)354 QByteArray 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(indexCount * sizeof(quint16));
369 quint16 *indices = reinterpret_cast<quint16 *>(indexData.data());
370 quint16 baseIndex = 0;
371
372 createPlaneIndexData(yzResolution, indices, baseIndex);
373 indices += yzIndices;
374 createPlaneIndexData(yzResolution, indices, baseIndex);
375 indices += yzIndices;
376 createPlaneIndexData(xzResolution, indices, baseIndex);
377 indices += xzIndices;
378 createPlaneIndexData(xzResolution, indices, baseIndex);
379 indices += xzIndices;
380 createPlaneIndexData(xyResolution, indices, baseIndex);
381 indices += xyIndices;
382 createPlaneIndexData(xyResolution, indices, baseIndex);
383
384 return indexData;
385 }
386
387 } // anonymous
388
389 class CuboidVertexBufferFunctor : public QBufferDataGenerator
390 {
391 public:
CuboidVertexBufferFunctor(float xExtent,float yExtent,float zExtent,const QSize & yzResolution,const QSize & xzResolution,const QSize & xyResolution)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
~CuboidVertexBufferFunctor()406 ~CuboidVertexBufferFunctor() {}
407
operator ()()408 QByteArray operator()() final
409 {
410 return createCuboidVertexData(m_xExtent, m_yExtent, m_zExtent,
411 m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution);
412 }
413
operator ==(const QBufferDataGenerator & other) const414 bool operator ==(const QBufferDataGenerator &other) const final
415 {
416 const CuboidVertexBufferFunctor *otherFunctor = functor_cast<CuboidVertexBufferFunctor>(&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
429 private:
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
438 class CuboidIndexBufferFunctor : public QBufferDataGenerator
439 {
440 public:
CuboidIndexBufferFunctor(const QSize & yzResolution,const QSize & xzResolution,const QSize & xyResolution)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
~CuboidIndexBufferFunctor()449 ~CuboidIndexBufferFunctor() {}
450
operator ()()451 QByteArray operator()() final
452 {
453 return createCuboidIndexData(m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution);
454 }
455
operator ==(const QBufferDataGenerator & other) const456 bool operator ==(const QBufferDataGenerator &other) const final
457 {
458 const CuboidIndexBufferFunctor *otherFunctor = functor_cast<CuboidIndexBufferFunctor>(&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
468 private:
469 QSize m_yzFaceResolution;
470 QSize m_xzFaceResolution;
471 QSize m_xyFaceResolution;
472 };
473
QCuboidGeometryPrivate()474 QCuboidGeometryPrivate::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
init()492 void 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(m_xExtent, m_yExtent, m_zExtent,
557 m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution));
558 m_indexBuffer->setDataGenerator(QSharedPointer<CuboidIndexBufferFunctor>::create(m_yzFaceResolution, m_xzFaceResolution, m_xyFaceResolution));
559
560 q->addAttribute(m_positionAttribute);
561 q->addAttribute(m_texCoordAttribute);
562 q->addAttribute(m_normalAttribute);
563 q->addAttribute(m_tangentAttribute);
564 q->addAttribute(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 */
QCuboidGeometry(QNode * parent)666 QCuboidGeometry::QCuboidGeometry(QNode *parent)
667 : QGeometry(*new QCuboidGeometryPrivate(), parent)
668 {
669 Q_D(QCuboidGeometry);
670 d->init();
671 }
672
673 /*!
674 * \internal
675 */
QCuboidGeometry(QCuboidGeometryPrivate & dd,QNode * parent)676 QCuboidGeometry::QCuboidGeometry(QCuboidGeometryPrivate &dd, QNode *parent)
677 : QGeometry(dd, parent)
678 {
679 Q_D(QCuboidGeometry);
680 d->init();
681 }
682
683 /*!
684 * \internal
685 */
~QCuboidGeometry()686 QCuboidGeometry::~QCuboidGeometry()
687 {
688 }
689
690 /*!
691 * Updates indices based on mesh resolutions.
692 */
updateIndices()693 void 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(d->m_yzFaceResolution, d->m_xzFaceResolution, d->m_xyFaceResolution));
703
704 }
705
706 /*!
707 * Updates vertices based on mesh resolutions.
708 */
updateVertices()709 void 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(d->m_xExtent, d->m_yExtent, d->m_zExtent,
723 d->m_yzFaceResolution, d->m_xzFaceResolution, d->m_xyFaceResolution));
724 }
725
setXExtent(float xExtent)726 void 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
setYExtent(float yExtent)736 void 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
setZExtent(float zExtent)746 void 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
setYZMeshResolution(const QSize & resolution)756 void 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(resolution);
764 }
765 }
766
setXZMeshResolution(const QSize & resolution)767 void 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(resolution);
775 }
776 }
777
setXYMeshResolution(const QSize & resolution)778 void 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(resolution);
786 }
787 }
788
789 /*!
790 * \property QCuboidGeometry::xExtent
791 *
792 * Holds the x extent of the geometry.
793 */
xExtent() const794 float 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 */
yExtent() const805 float 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 */
zExtent() const816 float 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 */
yzMeshResolution() const829 QSize 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 */
xyMeshResolution() const842 QSize 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 */
xzMeshResolution() const855 QSize 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 */
positionAttribute() const866 QAttribute *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 */
normalAttribute() const877 QAttribute *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 */
texCoordAttribute() const888 QAttribute *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 */
tangentAttribute() const899 QAttribute *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 */
indexAttribute() const910 QAttribute *QCuboidGeometry::indexAttribute() const
911 {
912 Q_D(const QCuboidGeometry);
913 return d->m_indexAttribute;
914 }
915
916 } // Qt3DExtras
917
918 QT_END_NAMESPACE
919