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