1/****************************************************************************
2**
3** Copyright (C) 2014 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 "qattribute.h"
41#include "qattribute_p.h"
42#include <Qt3DRender/qbuffer.h>
43
44QT_BEGIN_NAMESPACE
45
46namespace Qt3DRender {
47
48QAttributePrivate::QAttributePrivate()
49 : QNodePrivate()
50 , m_buffer(nullptr)
51 , m_name()
52 , m_vertexBaseType(QAttribute::Float)
53 , m_vertexSize(1)
54 , m_count(0)
55 , m_byteStride(0)
56 , m_byteOffset(0)
57 , m_divisor(0)
58 , m_attributeType(QAttribute::VertexAttribute)
59{
60}
61
62/*!
63 * \qmltype Attribute
64 * \instantiates Qt3DRender::QAttribute
65 * \inqmlmodule Qt3D.Render
66 * \brief Defines an attribute and how data should be read from a Buffer.
67 *
68 * There are 3 types of attributes.
69 * \list
70 * \li VertexAttribute: used to define data to be read on a per vertex basis
71 * \li IndexAttribute: used to define vertex indices when indexed draw calls are
72 * to be used
73 *\li DrawIndirectAttribute: used to specify the DrawIndirect buffer to be used
74 * when indirect draw calls are to be used
75 * \endlist
76 *
77 * \note when an attribute is of type DrawIndirectAttribute, only count, stride
78 * and offset are relevant.
79 *
80 * When providing your own attributes, it may make sense to name your attribute
81 * using helpers such as QAttribute::defaultPositionAttributeName() as that
82 * will ensure your geometry will be compatible with picking and the various
83 * materials provided in the Qt3DExtras module.
84 */
85
86/*!
87 * \class Qt3DRender::QAttribute
88 * \inheaderfile Qt3DRender/QAttribute
89 * \inmodule Qt3DRender
90 *
91 * \inherits Qt3DCore::QNode
92 *
93 * \brief Defines an attribute and how data should be read from a QBuffer.
94 *
95 * There are 3 types of attributes.
96 * \list
97 * \li VertexAttribute: used to define data to be read on a per vertex basis
98 * \li IndexAttribute: used to define vertex indices when indexed draw calls are
99 * to be used
100 *\li DrawIndirectAttribute: used to specify the DrawIndirect buffer to be used
101 * when indirect draw calls are to be used
102 * \endlist
103 *
104 * \note when an attribute is of type DrawIndirectAttribute, only count, stride
105 * and offset are relevant.
106 *
107 * When providing your own attributes, it may make sense to name your attribute
108 * using helpers such as QAttribute::defaultPositionAttributeName() as that
109 * will ensure your geometry will be compatible with picking and the various
110 * materials provided in the Qt3DExtras module.
111 *
112 * \sa QBuffer
113 */
114
115/*!
116 * \typedef Qt3DRender::QBufferPtr
117 * \relates Qt3DRender::QAttribute
118 */
119
120/*!
121 * \enum QAttribute::AttributeType
122 *
123 * The type of the attribute.
124 *
125 * \value VertexAttribute
126 * \value IndexAttribute
127 * \value DrawIndirectAttribute
128 */
129
130/*!
131 * \enum QAttribute::VertexBaseType
132 *
133 * The type of the data.
134 *
135 * \value Byte
136 * \value UnsignedByte
137 * \value Short
138 * \value UnsignedShort
139 * \value Int
140 * \value UnsignedInt
141 * \value HalfFloat
142 * \value Float
143 * \value Double
144 */
145
146/*!
147 * Constructs a new QAttribute with \a parent.
148 */
149QAttribute::QAttribute(QNode *parent)
150 : QNode(*new QAttributePrivate(), parent)
151{
152}
153
154/*!
155 * Constructs a new QAttribute from \a buf of \a type, \a dataSize, \a count, \a offset,
156 * and \a stride with \a parent.
157 */
158QAttribute::QAttribute(QBuffer *buf, VertexBaseType type, uint dataSize, uint count, uint offset, uint stride, QNode *parent)
159 : QAttribute(parent)
160{
161 Q_D(QAttribute);
162 setBuffer(buf);
163 d->m_count = count;
164 d->m_byteOffset = offset;
165 d->m_vertexBaseType = type;
166 d->m_vertexSize = dataSize;
167 d->m_byteStride = stride;
168}
169
170
171/*!
172 * Constructs a new QAttribute named \a name from \a buf of \a type, \a
173 * dataSize, \a count, \a offset, and \a stride with \a parent.
174 */
175QAttribute::QAttribute(QBuffer *buf, const QString &name, VertexBaseType type, uint dataSize, uint count, uint offset, uint stride, QNode *parent)
176 : QAttribute(parent)
177{
178 Q_D(QAttribute);
179 setBuffer(buf);
180 d->m_name = name;
181 d->m_count = count;
182 d->m_byteOffset = offset;
183 d->m_vertexBaseType = type;
184 d->m_vertexSize = dataSize;
185 d->m_byteStride = stride;
186}
187
188/*! \internal */
189QAttribute::~QAttribute()
190{
191}
192
193/*!
194 * \property QAttribute::buffer
195 *
196 * Holds the buffer.
197 */
198QBuffer *QAttribute::buffer() const
199{
200 Q_D(const QAttribute);
201 return d->m_buffer;
202}
203
204/*!
205 * \property QAttribute::name
206 *
207 * Holds the name.
208 */
209QString QAttribute::name() const
210{
211 Q_D(const QAttribute);
212 return d->m_name;
213}
214
215/*!
216 * \property QAttribute::vertexSize
217 *
218 * Holds the data size, it can only be 1 to 4 units (scalars and vectors),
219 * 9 units (3x3 matrices) or 16 units (4x4 matrices).
220 */
221uint QAttribute::vertexSize() const
222{
223 Q_D(const QAttribute);
224 return d->m_vertexSize;
225}
226
227/*!
228 * \property QAttribute::vertexBaseType
229 *
230 * Holds the data type.
231 */
232QAttribute::VertexBaseType QAttribute::vertexBaseType() const
233{
234 Q_D(const QAttribute);
235 return d->m_vertexBaseType;
236}
237
238/*!
239 * \property QAttribute::count
240 *
241 * Holds the count.
242 */
243uint QAttribute::count() const
244{
245 Q_D(const QAttribute);
246 return d->m_count;
247}
248
249/*!
250 * \property QAttribute::byteStride
251 *
252 * Holds the byte stride.
253 */
254uint QAttribute::byteStride() const
255{
256 Q_D(const QAttribute);
257 return d->m_byteStride;
258}
259
260/*!
261 * \property QAttribute::byteOffset
262 *
263 * Holds the byte offset.
264 */
265uint QAttribute::byteOffset() const
266{
267 Q_D(const QAttribute);
268 return d->m_byteOffset;
269}
270
271/*!
272 * \property QAttribute::divisor
273 *
274 * Holds the divisor.
275 */
276uint QAttribute::divisor() const
277{
278 Q_D(const QAttribute);
279 return d->m_divisor;
280}
281
282/*!
283 * \property QAttribute::attributeType
284 *
285 * Holds the attribute type.
286 */
287QAttribute::AttributeType QAttribute::attributeType() const
288{
289 Q_D(const QAttribute);
290 return d->m_attributeType;
291}
292
293void QAttribute::setBuffer(QBuffer *buffer)
294{
295 Q_D(QAttribute);
296 if (d->m_buffer == buffer)
297 return;
298
299 if (d->m_buffer)
300 d->unregisterDestructionHelper(node: d->m_buffer);
301
302 // We need to add it as a child of the current node if it has been declared inline
303 // Or not previously added as a child of the current node so that
304 // 1) The backend gets notified about it's creation
305 // 2) When the current node is destroyed, it gets destroyed as well
306 if (buffer && !buffer->parent())
307 buffer->setParent(this);
308
309 d->m_buffer = buffer;
310
311 // Ensures proper bookkeeping
312 if (d->m_buffer)
313 d->registerDestructionHelper(node: d->m_buffer, func: &QAttribute::setBuffer, d->m_buffer);
314
315 emit bufferChanged(buffer);
316}
317
318void QAttribute::setName(const QString &name)
319{
320 Q_D(QAttribute);
321 if (d->m_name == name)
322 return;
323
324 d->m_name = name;
325 emit nameChanged(name);
326}
327
328void QAttribute::setVertexBaseType(VertexBaseType type)
329{
330 Q_D(QAttribute);
331
332 if (d->m_vertexBaseType == type)
333 return;
334
335 d->m_vertexBaseType = type;
336 emit vertexBaseTypeChanged(vertexBaseType: type);
337 emit dataTypeChanged(vertexBaseType: type);
338}
339
340void QAttribute::setVertexSize(uint size)
341{
342 Q_D(QAttribute);
343 if (d->m_vertexSize == size)
344 return;
345 Q_ASSERT((size >= 1 && size <= 4) || (size == 9) || (size == 16));
346 d->m_vertexSize = size;
347 emit vertexSizeChanged(vertexSize: size);
348 emit dataSizeChanged(vertexSize: size);
349}
350
351void QAttribute::setDataType(VertexBaseType type)
352{
353 setVertexBaseType(type);
354}
355
356void QAttribute::setDataSize(uint size)
357{
358 setVertexSize(size);
359}
360
361void QAttribute::setCount(uint count)
362{
363 Q_D(QAttribute);
364 if (d->m_count == count)
365 return;
366
367 d->m_count = count;
368 emit countChanged(count);
369}
370
371void QAttribute::setByteStride(uint byteStride)
372{
373 Q_D(QAttribute);
374 if (d->m_byteStride == byteStride)
375 return;
376
377 d->m_byteStride = byteStride;
378 emit byteStrideChanged(byteStride);
379}
380
381void QAttribute::setByteOffset(uint byteOffset)
382{
383 Q_D(QAttribute);
384 if (d->m_byteOffset == byteOffset)
385 return;
386
387 d->m_byteOffset = byteOffset;
388 emit byteOffsetChanged(byteOffset);
389}
390
391void QAttribute::setDivisor(uint divisor)
392{
393 Q_D(QAttribute);
394 if (d->m_divisor == divisor)
395 return;
396
397 d->m_divisor = divisor;
398 emit divisorChanged(divisor);
399}
400
401void QAttribute::setAttributeType(AttributeType attributeType)
402{
403 Q_D(QAttribute);
404 if (d->m_attributeType == attributeType)
405 return;
406
407 d->m_attributeType = attributeType;
408 emit attributeTypeChanged(attributeType);
409}
410/*!
411 * \brief QAttribute::defaultPositionAttributeName
412 * \return the name of the default position attribute
413 */
414QString QAttribute::defaultPositionAttributeName()
415{
416 return QStringLiteral("vertexPosition");
417}
418/*!
419 * \brief QAttribute::defaultNormalAttributeName
420 * \return the name of the default normal attribute
421 */
422QString QAttribute::defaultNormalAttributeName()
423{
424 return QStringLiteral("vertexNormal");
425}
426/*!
427 * \brief QAttribute::defaultColorAttributeName
428 * \return the name of the default color attribute
429 */
430QString QAttribute::defaultColorAttributeName()
431{
432 return QStringLiteral("vertexColor");
433}
434/*!
435 * \brief QAttribute::defaultTextureCoordinateAttributeName
436 * \return the name of the default texture coordinate attribute
437 */
438QString QAttribute::defaultTextureCoordinateAttributeName()
439{
440 return QStringLiteral("vertexTexCoord");
441}
442/*!
443 * \brief QAttribute::defaultTangentAttributeName
444 * \return the name of the default tangent attribute
445 */
446QString QAttribute::defaultTangentAttributeName()
447{
448 return QStringLiteral("vertexTangent");
449}
450
451/*!
452 * \brief QAttribute::defaultJointIndicesAttributeName
453 * \return the name of the default joint indices attribute
454 */
455QString QAttribute::defaultJointIndicesAttributeName()
456{
457 return QStringLiteral("vertexJointIndices");
458}
459
460/*!
461 * \brief QAttribute::defaultJointIndicesAttributeName
462 * \return the name of the default joint weights attribute
463 */
464QString QAttribute::defaultJointWeightsAttributeName()
465{
466 return QStringLiteral("vertexJointWeights");
467}
468
469/*!
470 * \brief QAttribute::defaultTextureCoordinate1AttributeName
471 * \return the name of the default attribute for the second layer of texture
472 * coordinates
473 */
474QString QAttribute::defaultTextureCoordinate1AttributeName()
475{
476 return QStringLiteral("vertexTexCoord1");
477}
478
479/*!
480 * \brief QAttribute::defaultTextureCoordinate2AttributeName
481 * \return the name of the default attribute for the third layer of texture
482 * coordinates
483 */
484QString QAttribute::defaultTextureCoordinate2AttributeName()
485{
486 return QStringLiteral("vertexTexCoord2");
487}
488
489Qt3DCore::QNodeCreatedChangeBasePtr QAttribute::createNodeCreationChange() const
490{
491 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAttributeData>::create(arguments: this);
492 auto &data = creationChange->data;
493 Q_D(const QAttribute);
494 data.bufferId = qIdForNode(node: d->m_buffer);
495 data.name = d->m_name;
496 data.vertexBaseType = d->m_vertexBaseType;
497 data.vertexSize = d->m_vertexSize;
498 data.count = d->m_count;
499 data.byteStride = d->m_byteStride;
500 data.byteOffset = d->m_byteOffset;
501 data.divisor = d->m_divisor;
502 data.attributeType = d->m_attributeType;
503 return creationChange;
504}
505
506
507/*!
508\fn Qt3DRender::QAttribute::dataSizeChanged(uint vertexSize)
509
510The signal is emitted with \a vertexSize when the dataSize changes.
511*/
512/*!
513\fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType)
514
515The signal is emitted with \a vertexBaseType when the dataType changed.
516*/
517
518
519} // Qt3DRender
520
521QT_END_NAMESPACE
522

source code of qt3d/src/render/geometry/qattribute.cpp