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
44 QT_BEGIN_NAMESPACE
45
46 namespace Qt3DRender {
47
QAttributePrivate()48 QAttributePrivate::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 */
QAttribute(QNode * parent)149 QAttribute::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 */
QAttribute(QBuffer * buf,VertexBaseType type,uint dataSize,uint count,uint offset,uint stride,QNode * parent)158 QAttribute::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 */
QAttribute(QBuffer * buf,const QString & name,VertexBaseType type,uint dataSize,uint count,uint offset,uint stride,QNode * parent)175 QAttribute::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 */
~QAttribute()189 QAttribute::~QAttribute()
190 {
191 }
192
193 /*!
194 * \property QAttribute::buffer
195 *
196 * Holds the buffer.
197 */
buffer() const198 QBuffer *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 */
name() const209 QString 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 */
vertexSize() const221 uint 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 */
vertexBaseType() const232 QAttribute::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 */
count() const243 uint 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 */
byteStride() const254 uint 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 */
byteOffset() const265 uint 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 */
divisor() const276 uint 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 */
attributeType() const287 QAttribute::AttributeType QAttribute::attributeType() const
288 {
289 Q_D(const QAttribute);
290 return d->m_attributeType;
291 }
292
setBuffer(QBuffer * buffer)293 void 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(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(d->m_buffer, &QAttribute::setBuffer, d->m_buffer);
314
315 emit bufferChanged(buffer);
316 }
317
setName(const QString & name)318 void 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
setVertexBaseType(VertexBaseType type)328 void 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(type);
337 emit dataTypeChanged(type);
338 }
339
setVertexSize(uint size)340 void 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(size);
348 emit dataSizeChanged(size);
349 }
350
setDataType(VertexBaseType type)351 void QAttribute::setDataType(VertexBaseType type)
352 {
353 setVertexBaseType(type);
354 }
355
setDataSize(uint size)356 void QAttribute::setDataSize(uint size)
357 {
358 setVertexSize(size);
359 }
360
setCount(uint count)361 void 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
setByteStride(uint byteStride)371 void 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
setByteOffset(uint byteOffset)381 void 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
setDivisor(uint divisor)391 void 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
setAttributeType(AttributeType attributeType)401 void 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 */
defaultPositionAttributeName()414 QString QAttribute::defaultPositionAttributeName()
415 {
416 return QStringLiteral("vertexPosition");
417 }
418 /*!
419 * \brief QAttribute::defaultNormalAttributeName
420 * \return the name of the default normal attribute
421 */
defaultNormalAttributeName()422 QString QAttribute::defaultNormalAttributeName()
423 {
424 return QStringLiteral("vertexNormal");
425 }
426 /*!
427 * \brief QAttribute::defaultColorAttributeName
428 * \return the name of the default color attribute
429 */
defaultColorAttributeName()430 QString QAttribute::defaultColorAttributeName()
431 {
432 return QStringLiteral("vertexColor");
433 }
434 /*!
435 * \brief QAttribute::defaultTextureCoordinateAttributeName
436 * \return the name of the default texture coordinate attribute
437 */
defaultTextureCoordinateAttributeName()438 QString QAttribute::defaultTextureCoordinateAttributeName()
439 {
440 return QStringLiteral("vertexTexCoord");
441 }
442 /*!
443 * \brief QAttribute::defaultTangentAttributeName
444 * \return the name of the default tangent attribute
445 */
defaultTangentAttributeName()446 QString 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 */
defaultJointIndicesAttributeName()455 QString 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 */
defaultJointWeightsAttributeName()464 QString 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 */
defaultTextureCoordinate1AttributeName()474 QString 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 */
defaultTextureCoordinate2AttributeName()484 QString QAttribute::defaultTextureCoordinate2AttributeName()
485 {
486 return QStringLiteral("vertexTexCoord2");
487 }
488
createNodeCreationChange() const489 Qt3DCore::QNodeCreatedChangeBasePtr QAttribute::createNodeCreationChange() const
490 {
491 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QAttributeData>::create(this);
492 auto &data = creationChange->data;
493 Q_D(const QAttribute);
494 data.bufferId = qIdForNode(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
510 The signal is emitted with \a vertexSize when the dataSize changes.
511 */
512 /*!
513 \fn Qt3DRender::QAttribute::dataTypeChanged(Qt3DRender::QAttribute::VertexBaseType vertexBaseType)
514
515 The signal is emitted with \a vertexBaseType when the dataType changed.
516 */
517
518
519 } // Qt3DRender
520
521 QT_END_NAMESPACE
522