1/****************************************************************************
2**
3** Copyright (C) 2016 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/*!
41 * \class Qt3DExtras::QConeGeometry
42 \ingroup qt3d-extras-geometries
43 * \inheaderfile Qt3DExtras/QConeGeometry
44 * \inmodule Qt3DExtras
45 * \brief The QConeGeometry class allows creation of a cone in 3D space.
46 * \since 5.7
47 * \ingroup geometries
48 * \inherits Qt3DRender::QGeometry
49 *
50 * The QConeGeometry class is most commonly used internally by the QConeMesh
51 * but can also be used in custom Qt3DRender::QGeometryRenderer subclasses. The class
52 * allows for creation of both a cone and a truncated cone.
53 */
54
55#ifndef _USE_MATH_DEFINES
56# define _USE_MATH_DEFINES // For MSVC
57#endif
58
59#include "qconegeometry.h"
60#include "qconegeometry_p.h"
61
62#include <Qt3DRender/qbuffer.h>
63#include <Qt3DRender/qbufferdatagenerator.h>
64#include <Qt3DRender/qattribute.h>
65#include <QtGui/QVector3D>
66
67#include <cmath>
68
69QT_BEGIN_NAMESPACE
70
71using namespace Qt3DRender;
72
73namespace Qt3DExtras {
74
75namespace {
76
77int faceCount(int slices, int rings, int capCount)
78{
79 return (slices * 2) * (rings - 1) + slices * capCount;
80}
81
82int vertexCount(int slices, int rings, int capCount)
83{
84 return (slices + 1) * rings + capCount * (slices + 2);
85}
86
87void createSidesVertices(float *&verticesPtr,
88 int rings,
89 int slices,
90 double topRadius,
91 double bottomRadius,
92 double length)
93{
94 const float dY = length / static_cast<float>(rings - 1);
95 const float dTheta = (M_PI * 2) / static_cast<float>(slices);
96
97 for (int ring = 0; ring < rings; ++ring) {
98 const float y = -length / 2.0f + static_cast<float>(ring) * dY;
99
100 const float t = (y + length / 2) / length;
101 const float radius = (bottomRadius * (1 - t)) + (t * topRadius);
102
103 for (int slice = 0; slice <= slices; ++slice) {
104 const float theta = static_cast<float>(slice) * dTheta;
105 const float ta = std::tan(x: (M_PI/2) - std::atan(x: length / (bottomRadius - topRadius)));
106 const float ct = std::cos(x: theta);
107 const float st = std::sin(x: theta);
108
109 *verticesPtr++ = radius * ct;
110 *verticesPtr++ = y;
111 *verticesPtr++ = radius * st;
112
113 *verticesPtr++ = (y + length / 2.0) / length;
114 *verticesPtr++ = theta / (M_PI * 2);
115
116 QVector3D n(ct, ta, st);
117 n.normalize();
118 *verticesPtr++ = n.x();
119 *verticesPtr++ = n.y();
120 *verticesPtr++ = n.z();
121 }
122 }
123}
124
125void createSidesIndices(quint16 *&indicesPtr, int rings, int slices)
126{
127 for (int ring = 0; ring < rings-1; ++ring) {
128 const int ringIndexStart = ring * (slices + 1);
129 const int nextRingIndexStart = (ring + 1) * (slices + 1);
130
131 for (int slice = 0; slice <= slices; ++slice) {
132 if (slice == slices)
133 continue;
134
135 const int nextSlice = slice + 1;
136
137 *indicesPtr++ = (ringIndexStart + slice);
138 *indicesPtr++ = (nextRingIndexStart + slice);
139 *indicesPtr++ = (ringIndexStart + nextSlice);
140 *indicesPtr++ = (ringIndexStart + nextSlice);
141 *indicesPtr++ = (nextRingIndexStart + slice);
142 *indicesPtr++ = (nextRingIndexStart + nextSlice);
143 }
144 }
145}
146
147void createDiscVertices(float *&verticesPtr,
148 int slices,
149 double topRadius,
150 double bottomRadius,
151 double length,
152 double yPosition)
153{
154 const float dTheta = (M_PI * 2) / static_cast<float>(slices);
155 const double yNormal = (yPosition < 0.0f) ? -1.0f : 1.0f;
156
157 *verticesPtr++ = 0.0f;
158 *verticesPtr++ = yPosition;
159 *verticesPtr++ = 0.0f;
160
161 *verticesPtr++ = 1.0f;
162 *verticesPtr++ = 0.0f;
163
164 *verticesPtr++ = 0.0f;
165 *verticesPtr++ = yNormal;
166 *verticesPtr++ = 0.0f;
167
168
169 for (int slice = 0; slice <= slices; ++slice)
170 {
171 const float theta = static_cast<float>(slice) * dTheta;
172 const float ct = std::cos(x: theta);
173 const float st = std::sin(x: theta);
174
175 const float t = (yPosition + length / 2) / length;
176 const float radius = (bottomRadius * (1 - t)) + (t * topRadius);
177
178 *verticesPtr++ = radius * ct;
179 *verticesPtr++ = yPosition;
180 *verticesPtr++ = radius * st;
181
182 *verticesPtr++ = 1.0f;
183 *verticesPtr++ = theta / (M_PI * 2);
184
185 *verticesPtr++ = 0.0f;
186 *verticesPtr++ = yNormal;
187 *verticesPtr++ = 0.0f;
188 }
189}
190
191void createDiscIndices(quint16 *&indicesPtr,
192 int discCenterIndex,
193 int slices,
194 bool isTopCap)
195{
196 if ( !isTopCap ) {
197 for ( int i = slices - 1 ; i >= 0 ; --i )
198 {
199 if ( i != 0 ) {
200 *indicesPtr++ = discCenterIndex;
201 *indicesPtr++ = discCenterIndex + i + 1;
202 *indicesPtr++ = discCenterIndex + i;
203 } else {
204 *indicesPtr++ = discCenterIndex;
205 *indicesPtr++ = discCenterIndex + i + 1;
206 *indicesPtr++ = discCenterIndex + slices;
207 }
208 }
209 } else {
210 for ( int i = 0 ; i < slices; ++i )
211 {
212 if ( i != slices - 1 ) {
213 *indicesPtr++ = discCenterIndex;
214 *indicesPtr++ = discCenterIndex + i + 1;
215 *indicesPtr++ = discCenterIndex + i + 2;
216 } else {
217 *indicesPtr++ = discCenterIndex;
218 *indicesPtr++ = discCenterIndex + i + 1;
219 *indicesPtr++ = discCenterIndex + 1;
220 }
221 }
222 }
223}
224
225} // anonymous
226
227
228class ConeVertexDataFunctor : public QBufferDataGenerator
229{
230public:
231 ConeVertexDataFunctor(bool hasTopEndcap, bool hasBottomEndcap, int rings, int slices,
232 float topRadius, float bottomRadius, float length)
233 : m_hasTopEndcap(hasTopEndcap)
234 , m_hasBottomEndcap(hasBottomEndcap)
235 , m_rings(rings)
236 , m_slices(slices)
237 , m_topRadius(topRadius)
238 , m_bottomRadius(bottomRadius)
239 , m_length(length)
240 {}
241
242 QByteArray operator ()() override
243 {
244 const int verticesCount =
245 vertexCount(slices: m_slices, rings: m_rings, capCount: (m_hasTopEndcap + m_hasBottomEndcap));
246
247 // vec3 pos, vec2 texCoord, vec3 normal
248 const quint32 vertexSize = (3 + 2 + 3) * sizeof(float);
249
250 QByteArray verticesData;
251 verticesData.resize(size: vertexSize * verticesCount);
252 float *verticesPtr = reinterpret_cast<float*>(verticesData.data());
253
254 createSidesVertices(verticesPtr, rings: m_rings, slices: m_slices, topRadius: m_topRadius, bottomRadius: m_bottomRadius, length: m_length);
255 if ( m_hasTopEndcap )
256 createDiscVertices(verticesPtr, slices: m_slices, topRadius: m_topRadius, bottomRadius: m_bottomRadius, length: m_length, yPosition: m_length * 0.5f);
257 if ( m_hasBottomEndcap )
258 createDiscVertices(verticesPtr, slices: m_slices, topRadius: m_topRadius, bottomRadius: m_bottomRadius, length: m_length, yPosition: -m_length * 0.5f);
259
260 return verticesData;
261 }
262
263 bool operator ==(const QBufferDataGenerator &other) const override
264 {
265 const ConeVertexDataFunctor *otherFunctor = functor_cast<ConeVertexDataFunctor>(other: &other);
266 if (otherFunctor != nullptr)
267 return (otherFunctor->m_hasTopEndcap == m_hasTopEndcap &&
268 otherFunctor->m_hasBottomEndcap == m_hasBottomEndcap &&
269 otherFunctor->m_rings == m_rings &&
270 otherFunctor->m_slices == m_slices &&
271 otherFunctor->m_topRadius == m_topRadius &&
272 otherFunctor->m_bottomRadius == m_bottomRadius &&
273 otherFunctor->m_length == m_length);
274 return false;
275 }
276
277 QT3D_FUNCTOR(ConeVertexDataFunctor)
278
279private:
280 bool m_hasTopEndcap;
281 bool m_hasBottomEndcap;
282 int m_rings;
283 int m_slices;
284 float m_topRadius;
285 float m_bottomRadius;
286 float m_length;
287};
288
289class ConeIndexDataFunctor : public QBufferDataGenerator
290{
291public:
292 ConeIndexDataFunctor(bool hasTopEndcap, bool hasBottomEndcap, int rings, int slices,
293 float length)
294 : m_hasTopEndcap(hasTopEndcap)
295 , m_hasBottomEndcap(hasBottomEndcap)
296 , m_rings(rings)
297 , m_slices(slices)
298 , m_length(length)
299 {
300 }
301
302 QByteArray operator ()() override
303 {
304 const int facesCount = faceCount(slices: m_slices, rings: m_rings, capCount: (m_hasTopEndcap + m_hasBottomEndcap));
305
306 const int indicesCount = facesCount * 3;
307 const int indexSize = sizeof(quint16);
308 Q_ASSERT(indicesCount < 65536);
309
310 QByteArray indicesBytes;
311 indicesBytes.resize(size: indicesCount * indexSize);
312 quint16 *indicesPtr = reinterpret_cast<quint16*>(indicesBytes.data());
313
314 createSidesIndices(indicesPtr, rings: m_rings, slices: m_slices);
315 if ( m_hasTopEndcap )
316 createDiscIndices(indicesPtr, discCenterIndex: m_rings * (m_slices + 1) + m_slices + 2, slices: m_slices, isTopCap: true);
317 if ( m_hasBottomEndcap )
318 createDiscIndices(indicesPtr, discCenterIndex: m_rings * (m_slices + 1), slices: m_slices, isTopCap: false);
319
320 return indicesBytes;
321 }
322
323 bool operator ==(const QBufferDataGenerator &other) const override
324 {
325 const ConeIndexDataFunctor *otherFunctor = functor_cast<ConeIndexDataFunctor>(other: &other);
326 if (otherFunctor != nullptr)
327 return (otherFunctor->m_hasTopEndcap == m_hasTopEndcap &&
328 otherFunctor->m_hasBottomEndcap == m_hasBottomEndcap &&
329 otherFunctor->m_rings == m_rings &&
330 otherFunctor->m_slices == m_slices &&
331 otherFunctor->m_length == m_length);
332 return false;
333 }
334
335 QT3D_FUNCTOR(ConeIndexDataFunctor)
336
337private:
338 bool m_hasTopEndcap;
339 bool m_hasBottomEndcap;
340 int m_rings;
341 int m_slices;
342 float m_length;
343};
344
345
346QConeGeometryPrivate::QConeGeometryPrivate()
347 : QGeometryPrivate()
348 , m_hasTopEndcap(true)
349 , m_hasBottomEndcap(true)
350 , m_rings(16)
351 , m_slices(16)
352 , m_topRadius(0.0f)
353 , m_bottomRadius(1.0f)
354 , m_length(1.0f)
355 , m_positionAttribute(nullptr)
356 , m_normalAttribute(nullptr)
357 , m_texCoordAttribute(nullptr)
358 , m_indexAttribute(nullptr)
359 , m_positionBuffer(nullptr)
360 , m_vertexBuffer(nullptr)
361 , m_indexBuffer(nullptr)
362{
363}
364
365void QConeGeometryPrivate::init()
366{
367 Q_Q(QConeGeometry);
368 m_positionAttribute = new QAttribute(q);
369 m_normalAttribute = new QAttribute(q);
370 m_texCoordAttribute = new QAttribute(q);
371 m_indexAttribute = new QAttribute(q);
372 m_vertexBuffer = new Qt3DRender::QBuffer(q);
373 m_indexBuffer = new Qt3DRender::QBuffer(q);
374
375 // vec3 pos, vec2 tex, vec3 normal
376 const quint32 elementSize = 3 + 2 + 3;
377 const quint32 stride = elementSize * sizeof(float);
378 const int faces = faceCount(slices: m_slices, rings: m_rings, capCount: (m_hasTopEndcap + m_hasBottomEndcap));
379 const int nVerts = vertexCount(slices: m_slices, rings: m_rings, capCount: (m_hasTopEndcap + m_hasBottomEndcap));
380
381 m_positionAttribute->setName(QAttribute::defaultPositionAttributeName());
382 m_positionAttribute->setVertexBaseType(QAttribute::Float);
383 m_positionAttribute->setVertexSize(3);
384 m_positionAttribute->setAttributeType(QAttribute::VertexAttribute);
385 m_positionAttribute->setBuffer(m_vertexBuffer);
386 m_positionAttribute->setByteStride(stride);
387 m_positionAttribute->setCount(nVerts);
388
389 m_texCoordAttribute->setName(QAttribute::defaultTextureCoordinateAttributeName());
390 m_texCoordAttribute->setVertexBaseType(QAttribute::Float);
391 m_texCoordAttribute->setVertexSize(2);
392 m_texCoordAttribute->setAttributeType(QAttribute::VertexAttribute);
393 m_texCoordAttribute->setBuffer(m_vertexBuffer);
394 m_texCoordAttribute->setByteStride(stride);
395 m_texCoordAttribute->setByteOffset(3 * sizeof(float));
396 m_texCoordAttribute->setCount(nVerts);
397
398 m_normalAttribute->setName(QAttribute::defaultNormalAttributeName());
399 m_normalAttribute->setVertexBaseType(QAttribute::Float);
400 m_normalAttribute->setVertexSize(3);
401 m_normalAttribute->setAttributeType(QAttribute::VertexAttribute);
402 m_normalAttribute->setBuffer(m_vertexBuffer);
403 m_normalAttribute->setByteStride(stride);
404 m_normalAttribute->setByteOffset(5 * sizeof(float));
405 m_normalAttribute->setCount(nVerts);
406
407 m_indexAttribute->setAttributeType(QAttribute::IndexAttribute);
408 m_indexAttribute->setVertexBaseType(QAttribute::UnsignedShort);
409 m_indexAttribute->setBuffer(m_indexBuffer);
410
411 m_indexAttribute->setCount(faces * 3);
412
413 m_vertexBuffer->setDataGenerator(QSharedPointer<ConeVertexDataFunctor>::create(arguments&: m_hasTopEndcap, arguments&: m_hasBottomEndcap, arguments&: m_rings, arguments&: m_slices,
414 arguments&: m_topRadius, arguments&: m_bottomRadius, arguments&: m_length));
415 m_indexBuffer->setDataGenerator(QSharedPointer<ConeIndexDataFunctor>::create(arguments&: m_hasTopEndcap, arguments&: m_hasBottomEndcap, arguments&: m_rings, arguments&: m_slices,
416 arguments&: m_length));
417
418 q->addAttribute(attribute: m_positionAttribute);
419 q->addAttribute(attribute: m_texCoordAttribute);
420 q->addAttribute(attribute: m_normalAttribute);
421 q->addAttribute(attribute: m_indexAttribute);
422}
423
424/*!
425 * \qmltype ConeGeometry
426 * \instantiates Qt3DExtras::QConeGeometry
427 * \inqmlmodule Qt3D.Extras
428 * \brief ConeGeometry allows creation of a cone in 3D space.
429 *
430 * The ConeGeometry type is most commonly used internally by the ConeMesh type
431 * but can also be used in custom GeometryRenderer types.
432 * The ConeGeometry type allows for creation of both a cone and a truncated cone.
433 */
434
435/*!
436 * \qmlproperty bool ConeGeometry::hasTopEndcap
437 *
438 * Determines if the cone top is capped or open.
439 */
440
441/*!
442 * \qmlproperty bool ConeGeometry::hasBottomEndcap
443 *
444 * Determines if the cone bottom is capped or open.
445 */
446
447/*!
448 * \qmlproperty int ConeGeometry::rings
449 *
450 * Holds the number of rings in the geometry.
451 */
452
453/*!
454 * \qmlproperty int ConeGeometry::slices
455 *
456 * Holds the number of slices in the geometry.
457 */
458
459/*!
460 * \qmlproperty real ConeGeometry::topRadius
461 *
462 * Holds the top radius of the cone.
463 */
464
465/*!
466 * \qmlproperty real ConeGeometry::bottomRadius
467 *
468 * Holds the bottom radius of the cone.
469 */
470
471/*!
472 * \qmlproperty real ConeGeometry::length
473 *
474 * Holds the length of the cone.
475 */
476
477/*!
478 * \qmlproperty Attribute ConeGeometry::positionAttribute
479 *
480 * Holds the geometry position attribute.
481 */
482
483/*!
484 * \qmlproperty Attribute ConeGeometry::normalAttribute
485 *
486 * Holds the geometry normal attribute.
487 */
488
489/*!
490 * \qmlproperty Attribute ConeGeometry::texCoordAttribute
491 *
492 * Holds the geometry texture coordinate attribute.
493 */
494
495/*!
496 * \qmlproperty Attribute ConeGeometry::indexAttribute
497 *
498 * Holds the geometry index attribute.
499 */
500
501QConeGeometry::QConeGeometry(QNode *parent)
502 : QGeometry(*new QConeGeometryPrivate, parent)
503{
504 Q_D(QConeGeometry);
505 d->init();
506}
507
508QConeGeometry::QConeGeometry(QConeGeometryPrivate &dd, QNode *parent)
509 :QGeometry(dd, parent)
510{
511 Q_D(QConeGeometry);
512 d->init();
513}
514
515
516/*! \internal */
517QConeGeometry::~QConeGeometry()
518{
519}
520
521/*!
522 * Updates vertices based on geometry properties.
523 */
524void QConeGeometry::updateVertices()
525{
526 Q_D(QConeGeometry);
527 const int nVerts = vertexCount(slices: d->m_slices, rings: d->m_rings,
528 capCount: (d->m_hasTopEndcap + d->m_hasBottomEndcap));
529
530 d->m_positionAttribute->setCount(nVerts);
531 d->m_texCoordAttribute->setCount(nVerts);
532 d->m_normalAttribute->setCount(nVerts);
533 d->m_vertexBuffer->setDataGenerator(QSharedPointer<ConeVertexDataFunctor>::create(arguments&: d->m_hasTopEndcap, arguments&: d->m_hasBottomEndcap, arguments&: d->m_rings, arguments&: d->m_slices,
534 arguments&: d->m_topRadius, arguments&: d->m_bottomRadius, arguments&: d->m_length));
535}
536
537/*!
538 * Updates indices based on geometry properties.
539 */
540void QConeGeometry::updateIndices()
541{
542 Q_D(QConeGeometry);
543 const int faces = faceCount(slices: d->m_slices, rings: d->m_rings,
544 capCount: (d->m_hasTopEndcap + d->m_hasBottomEndcap));
545
546 d->m_indexAttribute->setCount(faces * 3);
547 d->m_indexBuffer->setDataGenerator(QSharedPointer<ConeIndexDataFunctor>::create(arguments&: d->m_hasTopEndcap, arguments&: d->m_hasBottomEndcap, arguments&: d->m_rings, arguments&: d->m_slices,
548 arguments&: d->m_length));
549}
550
551/*!
552 * \property QConeGeometry::hasTopEndcap
553 *
554 * Determines if the cone top is capped or open.
555 */
556/*!
557 * \property QConeGeometry::hasBottomEndcap
558 *
559 * Determines if the cone bottom is capped or open.
560 */
561
562/*!
563 * \property QConeGeometry::rings
564 *
565 * Holds the number of rings in the geometry.
566 */
567
568/*!
569 * \property QConeGeometry::slices
570 *
571 * Holds the number of slices in the geometry.
572 */
573
574/*!
575 * \property QConeGeometry::topRadius
576 *
577 * Holds the top radius of the cone.
578 */
579
580/*!
581 * \property QConeGeometry::bottomRadius
582 *
583 * Holds the bottom radius of the cone.
584 */
585
586/*!
587 * \property QConeGeometry::length
588 *
589 * Holds the length of the cone.
590 */
591
592/*!
593 * \property QConeGeometry::positionAttribute
594 *
595 * Holds the geometry position attribute.
596 */
597
598/*!
599 * \property QConeGeometry::normalAttribute
600 *
601 * Holds the geometry normal attribute.
602 */
603
604/*!
605 * \property QConeGeometry::texCoordAttribute
606 *
607 * Holds the geometry texture coordinate attribute.
608 */
609
610/*!
611 * \property QConeGeometry::indexAttribute
612 *
613 * Holds the geometry index attribute.
614 */
615
616void QConeGeometry::setHasTopEndcap(bool hasTopEndcap)
617{
618 Q_D(QConeGeometry);
619 if (hasTopEndcap != d->m_hasTopEndcap) {
620 d->m_hasTopEndcap = hasTopEndcap;
621 updateVertices();
622 emit hasTopEndcapChanged(hasTopEndcap);
623 }
624}
625
626void QConeGeometry::setHasBottomEndcap(bool hasBottomEndcap)
627{
628 Q_D(QConeGeometry);
629 if (hasBottomEndcap != d->m_hasBottomEndcap) {
630 d->m_hasBottomEndcap = hasBottomEndcap;
631 updateVertices();
632 emit hasBottomEndcapChanged(hasBottomEndcap);
633 }
634}
635
636void QConeGeometry::setRings(int rings)
637{
638 Q_D(QConeGeometry);
639 if (rings != d->m_rings) {
640 d->m_rings = rings;
641 updateVertices();
642 updateIndices();
643 emit ringsChanged(rings);
644 }
645}
646
647void QConeGeometry::setSlices(int slices)
648{
649 Q_D(QConeGeometry);
650 if (slices != d->m_slices) {
651 d->m_slices = slices;
652 updateVertices();
653 updateIndices();
654 emit slicesChanged(slices);
655 }
656}
657
658void QConeGeometry::setTopRadius(float topRadius)
659{
660 Q_D(QConeGeometry);
661 if (topRadius != d->m_topRadius) {
662 d->m_topRadius = topRadius;
663 updateVertices();
664 emit topRadiusChanged(topRadius);
665 }
666}
667
668void QConeGeometry::setBottomRadius(float bottomRadius)
669{
670 Q_D(QConeGeometry);
671 if (bottomRadius != d->m_bottomRadius) {
672 d->m_bottomRadius = bottomRadius;
673 updateVertices();
674 emit bottomRadiusChanged(bottomRadius);
675 }
676}
677
678void QConeGeometry::setLength(float length)
679{
680 Q_D(QConeGeometry);
681 if (length != d->m_length) {
682 d->m_length = length;
683 updateVertices();
684 updateIndices();
685 emit lengthChanged(length);
686 }
687}
688
689bool QConeGeometry::hasTopEndcap() const
690{
691 Q_D(const QConeGeometry);
692 return d->m_hasTopEndcap;
693}
694
695bool QConeGeometry::hasBottomEndcap() const
696{
697 Q_D(const QConeGeometry);
698 return d->m_hasBottomEndcap;
699}
700
701float QConeGeometry::topRadius() const
702{
703 Q_D(const QConeGeometry);
704 return d->m_topRadius;
705}
706
707float QConeGeometry::bottomRadius() const
708{
709 Q_D(const QConeGeometry);
710 return d->m_bottomRadius;
711}
712
713int QConeGeometry::rings() const
714{
715 Q_D(const QConeGeometry);
716 return d->m_rings;
717}
718
719int QConeGeometry::slices() const
720{
721 Q_D(const QConeGeometry);
722 return d->m_slices;
723}
724
725float QConeGeometry::length() const
726{
727 Q_D(const QConeGeometry);
728 return d->m_length;
729}
730
731QAttribute *QConeGeometry::positionAttribute() const
732{
733 Q_D(const QConeGeometry);
734 return d->m_positionAttribute;
735}
736
737QAttribute *QConeGeometry::normalAttribute() const
738{
739 Q_D(const QConeGeometry);
740 return d->m_normalAttribute;
741}
742
743QAttribute *QConeGeometry::texCoordAttribute() const
744{
745 Q_D(const QConeGeometry);
746 return d->m_texCoordAttribute;
747}
748
749QAttribute *QConeGeometry::indexAttribute() const
750{
751 Q_D(const QConeGeometry);
752 return d->m_indexAttribute;
753}
754
755} // namespace Qt3DExtras
756
757QT_END_NAMESPACE
758

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