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 | |
8 | QT_BEGIN_NAMESPACE |
9 | |
10 | namespace Qt3DCore { |
11 | |
12 | QAttributePrivate::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 | |
27 | void QAttributePrivate::update() |
28 | { |
29 | if (!m_blockNotifications) |
30 | m_dirty = true; |
31 | QNodePrivate::update(); |
32 | } |
33 | |
34 | QAttributePrivate *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 | */ |
126 | QAttribute::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 | */ |
135 | QAttribute::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 | */ |
152 | QAttribute::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 */ |
166 | QAttribute::~QAttribute() |
167 | { |
168 | } |
169 | |
170 | /*! |
171 | * \property QAttribute::buffer |
172 | * |
173 | * Holds the buffer. |
174 | */ |
175 | QBuffer *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 | */ |
186 | QString 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 | */ |
198 | uint 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 | */ |
209 | QAttribute::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 | */ |
220 | uint 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 | */ |
231 | uint 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 | */ |
242 | uint 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 | */ |
253 | uint 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 | */ |
264 | QAttribute::AttributeType QAttribute::attributeType() const |
265 | { |
266 | Q_D(const QAttribute); |
267 | return d->m_attributeType; |
268 | } |
269 | |
270 | void 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 | |
295 | void 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 | |
305 | void 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 | |
317 | void 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 | |
328 | void 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 | |
338 | void 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 | |
348 | void 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 | |
358 | void 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 | |
368 | void 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 | */ |
381 | QString QAttribute::defaultPositionAttributeName() |
382 | { |
383 | return QStringLiteral("vertexPosition" ); |
384 | } |
385 | /*! |
386 | * \brief QAttribute::defaultNormalAttributeName |
387 | * \return the name of the default normal attribute |
388 | */ |
389 | QString QAttribute::defaultNormalAttributeName() |
390 | { |
391 | return QStringLiteral("vertexNormal" ); |
392 | } |
393 | /*! |
394 | * \brief QAttribute::defaultColorAttributeName |
395 | * \return the name of the default color attribute |
396 | */ |
397 | QString QAttribute::defaultColorAttributeName() |
398 | { |
399 | return QStringLiteral("vertexColor" ); |
400 | } |
401 | /*! |
402 | * \brief QAttribute::defaultTextureCoordinateAttributeName |
403 | * \return the name of the default texture coordinate attribute |
404 | */ |
405 | QString QAttribute::defaultTextureCoordinateAttributeName() |
406 | { |
407 | return QStringLiteral("vertexTexCoord" ); |
408 | } |
409 | /*! |
410 | * \brief QAttribute::defaultTangentAttributeName |
411 | * \return the name of the default tangent attribute |
412 | */ |
413 | QString 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 | */ |
422 | QString 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 | */ |
431 | QString 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 | */ |
441 | QString 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 | */ |
451 | QString QAttribute::defaultTextureCoordinate2AttributeName() |
452 | { |
453 | return QStringLiteral("vertexTexCoord2" ); |
454 | } |
455 | |
456 | /*! |
457 | \fn Qt3DCore::QAttribute::dataSizeChanged(uint vertexSize) |
458 | |
459 | The signal is emitted with \a vertexSize when the dataSize changes. |
460 | */ |
461 | /*! |
462 | \fn Qt3DCore::QAttribute::dataTypeChanged(Qt3DCore::QAttribute::VertexBaseType vertexBaseType) |
463 | |
464 | The signal is emitted with \a vertexBaseType when the dataType changed. |
465 | */ |
466 | |
467 | } // Qt3DCore |
468 | |
469 | QT_END_NAMESPACE |
470 | |
471 | #include "moc_qattribute.cpp" |
472 | |