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