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

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