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