| 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 |  | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 */ | 
| 189 | QAttribute::~QAttribute() | 
| 190 | { | 
| 191 | } | 
| 192 |  | 
| 193 | /*! | 
| 194 |  * \property QAttribute::buffer | 
| 195 |  * | 
| 196 |  * Holds the buffer. | 
| 197 |  */ | 
| 198 | 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 |  */ | 
| 209 | 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 |  */ | 
| 221 | 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 |  */ | 
| 232 | 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 |  */ | 
| 243 | 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 |  */ | 
| 254 | 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 |  */ | 
| 265 | 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 |  */ | 
| 276 | 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 |  */ | 
| 287 | QAttribute::AttributeType QAttribute::attributeType() const | 
| 288 | { | 
| 289 |     Q_D(const QAttribute); | 
| 290 |     return d->m_attributeType; | 
| 291 | } | 
| 292 |  | 
| 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(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 |  | 
| 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 |  | 
| 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(vertexBaseType: type); | 
| 337 |     emit dataTypeChanged(vertexBaseType: type); | 
| 338 | } | 
| 339 |  | 
| 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(vertexSize: size); | 
| 348 |     emit dataSizeChanged(vertexSize: size); | 
| 349 | } | 
| 350 |  | 
| 351 | void QAttribute::setDataType(VertexBaseType type) | 
| 352 | { | 
| 353 |     setVertexBaseType(type); | 
| 354 | } | 
| 355 |  | 
| 356 | void QAttribute::setDataSize(uint size) | 
| 357 | { | 
| 358 |     setVertexSize(size); | 
| 359 | } | 
| 360 |  | 
| 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 |  | 
| 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 |  | 
| 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 |  | 
| 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 |  | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 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 |  */ | 
| 484 | QString QAttribute::defaultTextureCoordinate2AttributeName() | 
| 485 | { | 
| 486 |     return QStringLiteral("vertexTexCoord2" ); | 
| 487 | } | 
| 488 |  | 
| 489 | Qt3DCore::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 |  | 
| 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 |  |