Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquick3dparticlemodelblendparticle.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
7
8#include <QtCore/qdir.h>
9#include <QtQml/qqmlfile.h>
10
11#include <QtQuick3D/private/qquick3dobject_p.h>
12#include <QtQuick3D/private/qquick3dgeometry_p.h>
13
14#include <QtQuick3DUtils/private/qssgutils_p.h>
15#include <QtQuick3DRuntimeRender/private/qssgrenderparticles_p.h>
16#include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h>
17#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
18#include <QtQuick3DUtils/private/qssgmesh_p.h>
19
21
64
66{
67 delete m_model;
68 delete m_modelGeometry;
69}
70
95{
96 return m_delegate;
97}
98
100{
101 if (delegate == m_delegate)
102 return;
103 m_delegate = delegate;
104
105 reset();
106 regenerate();
108}
109
118{
119 return m_endNode;
120}
121
143
154{
155 return m_endTime;
156}
157
169{
170 return m_activationNode;
171}
172
194
196{
197 if (m_endNode == node)
198 return;
199 if (m_endNode)
201
202 m_endNode = node;
203
204 if (m_endNode) {
205 QObject::connect(m_endNode, &QQuick3DNode::positionChanged, this, &QQuick3DParticleModelBlendParticle::handleEndNodeChanged);
206 QObject::connect(m_endNode, &QQuick3DNode::rotationChanged, this, &QQuick3DParticleModelBlendParticle::handleEndNodeChanged);
207 QObject::connect(m_endNode, &QQuick3DNode::scaleChanged, this, &QQuick3DParticleModelBlendParticle::handleEndNodeChanged);
208 }
209 handleEndNodeChanged();
211}
212
214{
215 if (m_modelBlendMode == mode)
216 return;
217 m_modelBlendMode = mode;
218 reset();
220}
221
223{
224 if (endTime == m_endTime)
225 return;
226 m_endTime = endTime;
228}
229
231{
232 if (m_activationNode == activationNode)
233 return;
234
235 m_activationNode = activationNode;
237}
238
240{
241 if (m_emitMode == emitMode)
242 return;
243
244 m_emitMode = emitMode;
246}
247
248void QQuick3DParticleModelBlendParticle::regenerate()
249{
250 delete m_model;
251 m_model = nullptr;
252
253 if (!isComponentComplete())
254 return;
255
256 if (!m_delegate)
257 return;
258
259 if (QQuick3DParticleSystem::isGloballyDisabled())
260 return;
261
262 auto *obj = m_delegate->create(m_delegate->creationContext());
263
264 m_model = qobject_cast<QQuick3DModel *>(obj);
265 if (m_model) {
266 updateParticles();
267 auto *psystem = QQuick3DParticle::system();
268 m_model->setParent(psystem);
269 m_model->setParentItem(psystem);
270 } else {
271 delete obj;
272 }
273 handleEndNodeChanged();
274}
275
277{
279 if (source.startsWith(QLatin1Char('#'))) {
281 src.prepend(QLatin1String(":/"));
282 }
284 if (src.startsWith(QLatin1String("qrc:/")))
285 src = src.mid(3);
286
287 QFile file(src);
289 return {};
291}
292
293static QVector3D getPosition(const quint8 *srcVertices, quint32 idx, quint32 vertexStride, quint32 posOffset)
294{
295 const quint8 *vertex = srcVertices + idx * vertexStride;
296 return *reinterpret_cast<const QVector3D *>(vertex + posOffset);
297}
298
299static float calcTriangleRadius(const QVector3D &center, const QVector3D &p0, const QVector3D &p1, const QVector3D &p2)
300{
301 return qMax(center.distanceToPoint(p1), qMax(center.distanceToPoint(p2), center.distanceToPoint(p0)));
302}
303
304static void copyToUnindexedVertices(QByteArray &unindexedVertexData,
305 QVector<QVector3D> &centerData,
306 float &maxTriangleRadius,
307 const QByteArray &vertexBufferData,
308 quint32 vertexStride,
309 quint32 posOffset,
310 const QByteArray &indexBufferData,
311 bool u16Indices,
312 quint32 primitiveCount)
313{
314 const quint8 *srcVertices = reinterpret_cast<const quint8 *>(vertexBufferData.data());
315 quint8 *dst = reinterpret_cast<quint8 *>(unindexedVertexData.data());
316 const quint16 *indexData16 = reinterpret_cast<const quint16 *>(indexBufferData.begin());
317 const quint32 *indexData32 = reinterpret_cast<const quint32 *>(indexBufferData.begin());
318 const float c_div3 = 1.0f / 3.0f;
319 for (quint32 i = 0; i < primitiveCount; i++) {
320 quint32 i0, i1, i2;
321 if (u16Indices) {
322 i0 = indexData16[3 * i];
323 i1 = indexData16[3 * i + 1];
324 i2 = indexData16[3 * i + 2];
325 } else {
326 i0 = indexData32[3 * i];
327 i1 = indexData32[3 * i + 1];
328 i2 = indexData32[3 * i + 2];
329 }
330 QVector3D p0 = getPosition(srcVertices, i0, vertexStride, posOffset);
331 QVector3D p1 = getPosition(srcVertices, i1, vertexStride, posOffset);
332 QVector3D p2 = getPosition(srcVertices, i2, vertexStride, posOffset);
333 QVector3D center = (p0 + p1 + p2) * c_div3;
334 centerData[i] = center;
335 maxTriangleRadius = qMax(maxTriangleRadius, calcTriangleRadius(center, p0, p1, p2));
336 memcpy(dst, srcVertices + i0 * vertexStride, vertexStride);
337 dst += vertexStride;
338 memcpy(dst, srcVertices + i1 * vertexStride, vertexStride);
339 dst += vertexStride;
340 memcpy(dst, srcVertices + i2 * vertexStride, vertexStride);
341 dst += vertexStride;
342 }
343}
344
345static void getVertexCenterData(QVector<QVector3D> &centerData,
346 float &maxTriangleRadius,
347 const QByteArray &vertexBufferData,
348 quint32 vertexStride,
349 quint32 posOffset,
350 quint32 primitiveCount)
351{
352 const quint8 *srcVertices = reinterpret_cast<const quint8 *>(vertexBufferData.data());
353 const float c_div3 = 1.0f / 3.0f;
354 for (quint32 i = 0; i < primitiveCount; i++) {
355 QVector3D p0 = getPosition(srcVertices, 3 * i, vertexStride, posOffset);
356 QVector3D p1 = getPosition(srcVertices, 3 * i + 1, vertexStride, posOffset);
357 QVector3D p2 = getPosition(srcVertices, 3 * i + 2, vertexStride, posOffset);
358 QVector3D center = (p0 + p1 + p2) * c_div3;
359 centerData[i] = center;
360 maxTriangleRadius = qMax(maxTriangleRadius, calcTriangleRadius(center, p0, p1, p2));
361 }
362}
363
364void QQuick3DParticleModelBlendParticle::updateParticles()
365{
366 m_maxTriangleRadius = 0.f;
367
368 // The primitives needs to be triangle list without indexing, because each triangle
369 // needs to be it's own primitive and we need vertex index to get the particle index,
370 // which we don't get with indexed primitives
371 if (m_model->geometry()) {
372 QQuick3DGeometry *geometry = m_model->geometry();
374 qWarning () << "ModelBlendParticle3D: Invalid geometry primitive type, must be Triangles. ";
375 return;
376 }
377 auto vertexBuffer = geometry->vertexData();
378 auto indexBuffer = geometry->indexData();
379
380 if (!vertexBuffer.size()) {
381 qWarning () << "ModelBlendParticle3D: Invalid geometry, vertexData is empty. ";
382 return;
383 }
384
385 const auto attributeBySemantic = [&](const QQuick3DGeometry *geometry, QQuick3DGeometry::Attribute::Semantic semantic) {
386 for (int i = 0; i < geometry->attributeCount(); i++) {
387 const auto attr = geometry->attribute(i);
388 if (attr.semantic == semantic)
389 return attr;
390 }
391 Q_ASSERT(0);
393 };
394
395 if (indexBuffer.size()) {
396 m_modelGeometry = new QQuick3DGeometry;
397
398 m_modelGeometry->setBounds(geometry->boundsMin(), geometry->boundsMax());
400 m_modelGeometry->setStride(geometry->stride());
401
402 for (int i = 0; i < geometry->attributeCount(); i++) {
403 auto attr = geometry->attribute(i);
405 m_modelGeometry->addAttribute(attr);
406 }
407
408 // deindex data
409 QByteArray unindexedVertexData;
410 quint32 primitiveCount = indexBuffer.size();
412 bool u16IndexType = indexAttribute.componentType == QQuick3DGeometry::Attribute::U16Type;
413 if (u16IndexType)
414 primitiveCount /= 6;
415 else
416 primitiveCount /= 12;
417
418 unindexedVertexData.resize(geometry->stride() * primitiveCount * 3);
419 m_centerData.resize(primitiveCount);
420 m_particleCount = primitiveCount;
421 copyToUnindexedVertices(unindexedVertexData,
422 m_centerData,
423 m_maxTriangleRadius,
424 vertexBuffer,
425 geometry->stride(),
427 indexBuffer,
428 u16IndexType,
429 primitiveCount);
430
431 m_modelGeometry->setVertexData(unindexedVertexData);
432 m_model->setGeometry(m_modelGeometry);
433 } else {
434 // can use provided geometry directly
435 quint32 primitiveCount = vertexBuffer.size() / geometry->stride() / 3;
436 m_centerData.resize(primitiveCount);
437 m_particleCount = primitiveCount;
438 getVertexCenterData(m_centerData,
439 m_maxTriangleRadius,
440 vertexBuffer,
441 geometry->stride(),
443 primitiveCount);
444 }
445 } else {
446 const QQmlContext *context = qmlContext(this);
447 QString src = m_model->source().toString();
448 if (context && !src.startsWith(QLatin1Char('#')))
449 src = QQmlFile::urlToLocalFileOrQrc(context->resolvedUrl(m_model->source()));
451 if (!mesh.isValid()) {
452 qWarning () << "ModelBlendParticle3D: Unable to load mesh: " << src;
453 return;
454 }
455 if (mesh.drawMode() != QSSGMesh::Mesh::DrawMode::Triangles) {
456 qWarning () << "ModelBlendParticle3D: Invalid mesh primitive type, must be Triangles. ";
457 return;
458 }
459
460 m_modelGeometry = new QQuick3DGeometry;
461
462 const auto vertexBuffer = mesh.vertexBuffer();
463 const auto indexBuffer = mesh.indexBuffer();
464
465 const auto entryOffset = [&](const QSSGMesh::Mesh::VertexBuffer &vb, const QByteArray &name) -> int {
466 for (const auto &e : vb.entries) {
467 if (e.name == name) {
468 Q_ASSERT(e.componentType == QSSGMesh::Mesh::ComponentType::Float32);
469 return e.offset;
470 }
471 }
472 Q_ASSERT(0);
473 return -1;
474 };
475 const auto toAttribute = [&](const QSSGMesh::Mesh::VertexBufferEntry &e) -> QQuick3DGeometry::Attribute {
478 a.offset = e.offset;
480 return a;
481 };
482
483 const auto indexedPrimitiveCount = [&](const QSSGMesh::Mesh::IndexBuffer &indexBuffer) -> quint32 {
484 if (indexBuffer.componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16)
485 return quint32(indexBuffer.data.size() / sizeof(quint16) / 3);
486 return quint32(indexBuffer.data.size() / sizeof(quint32) / 3);
487 };
488
489 if (indexBuffer.data.size()) {
490 // deindex data
491 QByteArray unindexedVertexData;
492 quint32 primitiveCount = indexedPrimitiveCount(indexBuffer);
493 bool u16IndexType = indexBuffer.componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16;
494 unindexedVertexData.resize(vertexBuffer.stride * primitiveCount * 3);
495 m_centerData.resize(primitiveCount);
496 m_particleCount = primitiveCount;
497
498 copyToUnindexedVertices(unindexedVertexData,
499 m_centerData,
500 m_maxTriangleRadius,
501 vertexBuffer.data,
502 vertexBuffer.stride,
503 entryOffset(vertexBuffer, QByteArray(QSSGMesh::MeshInternal::getPositionAttrName())),
504 indexBuffer.data,
505 u16IndexType,
506 primitiveCount);
507 m_modelGeometry->setBounds(mesh.subsets().first().bounds.min, mesh.subsets().first().bounds.max);
508 m_modelGeometry->setStride(vertexBuffer.stride);
509 m_modelGeometry->setVertexData(unindexedVertexData);
511 } else {
512 // can use vertexbuffer directly
513 quint32 primitiveCount = vertexBuffer.data.size() / vertexBuffer.stride / 3;
514 m_centerData.resize(primitiveCount);
515 m_particleCount = primitiveCount;
516 getVertexCenterData(m_centerData,
517 m_maxTriangleRadius,
518 vertexBuffer.data,
519 vertexBuffer.stride,
520 entryOffset(vertexBuffer, QByteArray(QSSGMesh::MeshInternal::getPositionAttrName())),
521 primitiveCount);
522 m_modelGeometry->setBounds(mesh.subsets().first().bounds.min, mesh.subsets().first().bounds.max);
523 m_modelGeometry->setStride(vertexBuffer.stride);
524 m_modelGeometry->setVertexData(vertexBuffer.data);
526 }
527 for (auto &e : vertexBuffer.entries)
528 m_modelGeometry->addAttribute(toAttribute(e));
529 for (auto &s : mesh.subsets())
530 m_modelGeometry->addSubset(s.offset, s.count, s.bounds.min, s.bounds.max, s.name);
531
532 m_model->setSource({});
533 m_model->setGeometry(m_modelGeometry);
534 }
535
537 if (m_model->parentNode())
540 // Take max component scale for a conservative bounds estimation
541 const float scaleMax = qMax(scale.x(), qMax(scale.y(), scale.z()));
542 m_maxTriangleRadius *= scaleMax;
543
544 m_triangleParticleData.resize(m_particleCount);
545 m_particleData.resize(m_particleCount);
547 for (int i = 0; i < m_particleCount; i++) {
548 m_triangleParticleData[i].center = m_centerData[i];
549 m_centerData[i] = transform.map(m_centerData[i]);
550 if (m_modelBlendMode == Construct) {
551 m_triangleParticleData[i].size = 0.0f;
552 } else {
553 m_triangleParticleData[i].size = 1.0f;
554 m_triangleParticleData[i].position = m_centerData[i];
555 }
556 }
557 QQuick3DParticle::doSetMaxAmount(m_particleCount);
558}
559
561{
562 if (!m_model)
563 return node;
564 auto *spatialNode = QQuick3DObjectPrivate::get(m_model)->spatialNode;
565 if (!spatialNode) {
566 spatialNode = QQuick3DObjectPrivate::updateSpatialNode(m_model, nullptr);
567 QQuick3DObjectPrivate::get(m_model)->spatialNode = spatialNode;
568 Q_QUICK3D_PROFILE_ASSIGN_ID_SG(this, spatialNode);
569 }
570#if QT_CONFIG(qml_debug)
571 auto *geometrySpatialNode = QQuick3DObjectPrivate::get(m_modelGeometry)->spatialNode;
572 if (geometrySpatialNode)
573 Q_QUICK3D_PROFILE_ASSIGN_ID_SG(this, geometrySpatialNode);
574#endif
575
576 QSSGRenderModel *model = static_cast<QSSGRenderModel *>(spatialNode);
577
578 if (!model->particleBuffer) {
579 QSSGParticleBuffer *buffer = model->particleBuffer = new QSSGParticleBuffer;
580 buffer->resize(m_particleCount, sizeof(QSSGTriangleParticle));
581 }
583 QMatrix4x4 particleMatrix = psystem->sceneTransform().inverted() * m_model->sceneTransform();
584 model->particleMatrix = particleMatrix.inverted();
586 updateParticleBuffer(model->particleBuffer, psystem->sceneTransform());
587
588 return node;
589}
590
592{
593 if (!system() && qobject_cast<QQuick3DParticleSystem *>(parentItem()))
594 setSystem(qobject_cast<QQuick3DParticleSystem *>(parentItem()));
595
596 // don't call particles componentComplete, we don't wan't to emit maxAmountChanged yet
598 regenerate();
599}
600
602{
603 qWarning() << "ModelBlendParticle3D.maxAmount: Unable to set maximum amount, because it is set from the model.";
604 return;
605}
606
608{
609 if (!m_perEmitterData.contains(emitter)) {
610 m_perEmitterData.insert(emitter, PerEmitterData());
611 auto &perEmitter = m_perEmitterData[emitter];
612 perEmitter.emitter = emitter;
613 perEmitter.emitterIndex = m_nextEmitterIndex++;
614 }
615 auto &perEmitter = m_perEmitterData[emitter];
617 if (m_triangleParticleData[index].emitterIndex != perEmitter.emitterIndex) {
618 if (m_triangleParticleData[index].emitterIndex >= 0)
619 perEmitterData(m_triangleParticleData[index].emitterIndex).particleCount--;
620 perEmitter.particleCount++;
621 }
622 m_triangleParticleData[index].emitterIndex = perEmitter.emitterIndex;
623 return index;
624}
625
626
628 const QVector3D &position,
629 const QVector3D &rotation,
630 const QVector4D &color,
631 float size, float age)
632{
633 auto &dst = m_triangleParticleData[particleIndex];
634 dst = {position, rotation, dst.center, color, age, size, dst.emitterIndex};
635 m_dataChanged = true;
636}
637
638QQuick3DParticleModelBlendParticle::PerEmitterData &QQuick3DParticleModelBlendParticle::perEmitterData(int emitterIndex)
639{
640 for (auto &perEmitter : m_perEmitterData) {
641 if (perEmitter.emitterIndex == emitterIndex)
642 return perEmitter;
643 }
644 return n_noPerEmitterData;
645}
646
647void QQuick3DParticleModelBlendParticle::updateParticleBuffer(QSSGParticleBuffer *buffer, const QMatrix4x4 &sceneTransform)
648{
649 const auto &particles = m_triangleParticleData;
650
651 if (!buffer || !m_dataChanged)
652 return;
653
654 const int particleCount = m_particleCount;
655
656 char *dest = buffer->pointer();
657 const TriangleParticleData *src = particles.data();
658 const int pps = buffer->particlesPerSlice();
659 const int ss = buffer->sliceStride();
660 const int slices = buffer->sliceCount();
661 const float c_degToRad = float(M_PI / 180.0f);
662 int i = 0;
663 QSSGBounds3 bounds;
664 for (int s = 0; s < slices; s++) {
665 QSSGTriangleParticle *dp = reinterpret_cast<QSSGTriangleParticle *>(dest);
666 for (int p = 0; p < pps && i < particleCount; ) {
667 if (src->size > 0.0f)
668 bounds.include(src->position);
669 dp->position = src->position;
670 dp->rotation = src->rotation * c_degToRad;
671 dp->color = src->color;
672 dp->age = src->age;
673 dp->center = src->center;
674 dp->size = src->size;
675 dp++;
676 p++;
677 i++;
678 src++;
679 }
680 dest += ss;
681 }
682
683 bounds.fatten(m_maxTriangleRadius);
685 buffer->setBounds(bounds);
686 m_dataChanged = false;
687}
688
689void QQuick3DParticleModelBlendParticle::itemChange(QQuick3DObject::ItemChange change,
690 const QQuick3DObject::ItemChangeData &value)
691{
693 if (change == ItemParentHasChanged && value.sceneManager)
694 regenerate();
695}
696
698{
700 if (m_particleCount) {
701 for (int i = 0; i < m_particleCount; i++) {
702 if (m_modelBlendMode == Construct) {
703 m_triangleParticleData[i].size = 0.0f;
704 } else {
705 m_triangleParticleData[i].size = 1.0f;
706 m_triangleParticleData[i].position = m_triangleParticleData[i].center;
707 }
708 }
709 }
710}
711
713{
714 return m_centerData[particleIndex];
715}
716
721
722static QMatrix3x3 qt_fromEulerRotation(const QVector3D &eulerRotation)
723{
724 float x = qDegreesToRadians(eulerRotation.x());
725 float y = qDegreesToRadians(eulerRotation.y());
726 float z = qDegreesToRadians(eulerRotation.z());
727 float a = cos(x);
728 float b = sin(x);
729 float c = cos(y);
730 float d = sin(y);
731 float e = cos(z);
732 float f = sin(z);
734 float bd = b * d;
735 float ad = a * d;
736 ret(0,0) = c * e;
737 ret(0,1) = -c * f;
738 ret(0,2) = d;
739 ret(1,0) = bd * e + a * f;
740 ret(1,1) = a * e - bd * f;
741 ret(1,2) = -b * c;
742 ret(2,0) = b * f - ad * e;
743 ret(2,1) = ad * f + b * e;
744 ret(2,2) = a * c;
745 return ret;
746}
747
748void QQuick3DParticleModelBlendParticle::handleEndNodeChanged()
749{
750 if (m_endNode && m_model) {
751 if (!m_model->rotation().isIdentity()) {
752 // Use the same function as the shader for end node rotation so that they produce same matrix
754 QMatrix3x3 r2 = m_model->rotation().toRotationMatrix();
756 m_endNodeRotation = m_endNode->eulerRotation();
757 m_endRotationMatrix = QMatrix4x4(r);
758 } else {
759 m_endNodeRotation = m_endNode->eulerRotation();
760 m_endRotationMatrix = QMatrix4x4(m_endNode->rotation().toRotationMatrix().transposed());
761 }
762 m_endNodePosition = m_endNode->position();
763 m_endNodeScale = m_endNode->scale();
764 } else {
765 m_endNodePosition = QVector3D();
766 m_endNodeRotation = QVector3D();
767 m_endNodeScale = QVector3D(1.0f, 1.0f, 1.0f);
768 m_endRotationMatrix.setToIdentity();
769 }
770}
771
773{
774 return m_endRotationMatrix.map(QVector3D(m_endNodeScale * m_centerData[idx])) + m_endNodePosition;
775}
776
778{
779 return m_endNodeRotation;
780}
781
783{
784 if (m_randomParticles.isEmpty()) {
785 m_randomParticles.resize(m_maxAmount);
786 for (int i = 0; i < m_maxAmount; i++)
787 m_randomParticles[i] = i;
788
789 // Randomize particle indices just once
790 QRandomGenerator rand(system()->rand()->generator());
791 for (int i = 0; i < m_maxAmount; i++) {
792 int ridx = rand.generate() % m_maxAmount;
793 if (i != ridx)
794 qSwap(m_randomParticles[i], m_randomParticles[ridx]);
795 }
796 }
797 return m_randomParticles[particleIndex];
798}
799
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2398
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
QList< T > & fill(parameter_type t, qsizetype size=-1)
Definition qlist.h:903
void resize(qsizetype size)
Definition qlist.h:403
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
bool contains(const Key &key) const
Definition qmap.h:341
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
QMatrix4x4 inverted(bool *invertible=nullptr) const
Returns the inverse of this matrix.
QPoint map(const QPoint &point) const
Maps point by multiplying this matrix by point.
Definition qmatrix4x4.h:908
void setToIdentity()
Sets this matrix to the identity.
Definition qmatrix4x4.h:316
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
The QQmlComponent class encapsulates a QML component definition.
QQmlContext * creationContext() const
Returns the QQmlContext the component was created in.
virtual QObject * create(QQmlContext *context=nullptr)
Create an object instance from this component, within the specified context.
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
static QQuick3DGeometry::Attribute::Semantic semanticFromName(const QByteArray &name)
static QQuick3DGeometry::Attribute::ComponentType toComponentType(QSSGMesh::Mesh::ComponentType componentType)
\qmltype Geometry \inherits Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DGeometry
Attribute::Semantic int int stride
Returns the byte stride of the vertex buffer.
void setPrimitiveType(PrimitiveType type)
Sets the primitive type used for rendering to type.
int attributeCount() const
Returns the number of attributes defined for this geometry.
void setStride(int stride)
Sets the stride of the vertex buffer to stride, measured in bytes.
void addAttribute(Attribute::Semantic semantic, int offset, Attribute::ComponentType componentType)
Adds vertex attribute description.
void setVertexData(const QByteArray &data)
Sets the vertex buffer data.
int const QVector3D const QVector3D & boundsMax
Returns the maximum coordinate of the bounding volume.
int const QVector3D & boundsMin
Returns the minimum coordinate of the bounding volume.
PrimitiveType primitiveType() const
Returns the primitive type used when rendering.
Attribute attribute(int index) const
Returns attribute definition number index.
void setBounds(const QVector3D &min, const QVector3D &max)
Sets the bounding volume of the geometry to the cube defined by the points min and max.
QByteArray vertexData() const
Returns the vertex buffer data set by setVertexData.
QByteArray indexData() const
Returns the index buffer data.
QQuick3DGeometry * geometry
void setGeometry(QQuick3DGeometry *geometry)
void setSource(const QUrl &source)
void rotationChanged()
QMatrix4x4 sceneTransform
void positionChanged()
QQuick3DNode * parentNode() const
QQuaternion rotation
QVector3D eulerRotation
void scaleChanged()
QVector3D position
QVector3D scale
static QSSGRenderGraphObject * updateSpatialNode(QQuick3DObject *o, QSSGRenderGraphObject *n)
static QQuick3DObjectPrivate * get(QQuick3DObject *item)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void setParentItem(QQuick3DObject *parentItem)
virtual void itemChange(ItemChange, const ItemChangeData &)
bool isComponentComplete() const
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
void itemChange(ItemChange, const ItemChangeData &) override
QVector3D particleEndPosition(int particleIndex) const
QQuick3DParticleModelBlendParticle(QQuick3DNode *parent=nullptr)
\qmltype ModelBlendParticle3D \inherits Particle3D \inqmlmodule QtQuick3D.Particles3D
int nextCurrentIndex(const QQuick3DParticleEmitter *emitter) override
void setParticleData(int particleIndex, const QVector3D &position, const QVector3D &rotation, const QVector4D &color, float size, float age)
QVector3D particleEndRotation(int particleIndex) const
void setFadeInEffect(QQuick3DParticle::FadeType fadeInEffect)
QList< QQuick3DParticleData > m_particleData
virtual int nextCurrentIndex(const QQuick3DParticleEmitter *emitter)
void setSystem(QQuick3DParticleSystem *system)
QQuick3DParticleSystem * system() const
void setFadeOutEffect(QQuick3DParticle::FadeType fadeOutEffect)
virtual void doSetMaxAmount(int amount)
\inmodule QtCore \reentrant
Definition qrandom.h:21
quint32 generate()
Generates a 32-bit random quantity and returns it.
Definition qrandom.h:48
constexpr QRect transposed() const noexcept
Definition qrect.h:267
Class representing 3D range or axis aligned bounding box.
Q_ALWAYS_INLINE void fatten(double distance)
void include(const QVector3D &v)
expands the volume to include v
static QSSGBounds3 transform(const QMatrix3x3 &matrix, const QSSGBounds3 &bounds)
gets the transformed bounds of the passed AABB (resulting in a bigger AABB).
static QString primitivePath(const QString &primitive)
bool isValid() const
Definition qssgmesh_p.h:159
static Mesh loadMesh(QIODevice *device, quint32 id=0)
Definition qssgmesh.cpp:581
VertexBuffer vertexBuffer() const
Definition qssgmesh_p.h:140
IndexBuffer indexBuffer() const
Definition qssgmesh_p.h:141
QVector< Subset > subsets() const
Definition qssgmesh_p.h:143
DrawMode drawMode() const
Definition qssgmesh_p.h:161
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:671
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:670
constexpr float z() const noexcept
Returns the z coordinate of this point.
Definition qvectornd.h:672
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
QPixmap p2
QPixmap p1
[0]
QVector3D Q_QUICK3DUTILS_EXPORT getScale(const QMatrix4x4 &m)
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
Definition qnumeric.h:366
static void * context
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
return ret
#define M_PI
Definition qmath.h:209
constexpr float qDegreesToRadians(float degrees)
Definition qmath.h:260
static QT_BEGIN_NAMESPACE QQuick3DGeometry::Attribute attributeBySemantic(const QQuick3DGeometry *geometry, QQuick3DGeometry::Attribute::Semantic semantic)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLenum GLenum GLsizei count
GLfloat GLfloat f
GLenum src
GLenum GLuint buffer
GLuint color
[2]
GLenum GLenum dst
GLenum GLuint GLintptr offset
GLuint name
GLint y
GLsizei GLsizei GLchar * source
GLuint GLenum GLenum transform
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLfloat GLfloat p
[1]
GLenum GLenum GLenum GLenum GLenum scale
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
static float calcTriangleRadius(const QVector3D &center, const QVector3D &p0, const QVector3D &p1, const QVector3D &p2)
static QVector3D getPosition(const quint8 *srcVertices, quint32 idx, quint32 vertexStride, quint32 posOffset)
static void getVertexCenterData(QVector< QVector3D > &centerData, float &maxTriangleRadius, const QByteArray &vertexBufferData, quint32 vertexStride, quint32 posOffset, quint32 primitiveCount)
static void copyToUnindexedVertices(QByteArray &unindexedVertexData, QVector< QVector3D > &centerData, float &maxTriangleRadius, const QByteArray &vertexBufferData, quint32 vertexStride, quint32 posOffset, const QByteArray &indexBufferData, bool u16Indices, quint32 primitiveCount)
static QMatrix3x3 qt_fromEulerRotation(const QVector3D &eulerRotation)
static QSSGMesh::Mesh loadModelBlendParticleMesh(const QString &source)
#define Q_QUICK3D_PROFILE_ASSIGN_ID_SG(obj, bgnode)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
#define Q_EMIT
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
unsigned char quint8
Definition qtypes.h:46
QSqlQueryModel * model
[16]
QRandomGenerator generator(sseq)
QFile file
[0]
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
rect sceneTransform().map(QPointF(0
\inmodule QtCore \reentrant
Definition qchar.h:18
static const char * getPositionAttrName()
Definition qssgmesh_p.h:392
void resize(int particleCount, int particleSize=sizeof(QSSGParticleSimple))
Definition moc.h:23