Qt 6.x
The Qt SDK
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
59{
63}
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
140{
141 return m_modelBlendMode;
142}
143
154{
155 return m_endTime;
156}
157
169{
170 return m_activationNode;
171}
172
191{
192 return m_emitMode;
193}
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
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();
411 auto indexAttribute = attributeBySemantic(geometry, QQuick3DGeometry::Attribute::IndexSemantic);
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(),
426 attributeBySemantic(geometry, QQuick3DGeometry::Attribute::PositionSemantic).offset,
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(),
442 attributeBySemantic(geometry, QQuick3DGeometry::Attribute::PositionSemantic).offset,
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 {
477 a.componentType = QQuick3DGeometryPrivate::toComponentType(e.componentType);
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 auto *geometrySpatialNode = QQuick3DObjectPrivate::get(m_modelGeometry)->spatialNode;
571 if (geometrySpatialNode)
572 Q_QUICK3D_PROFILE_ASSIGN_ID_SG(this, geometrySpatialNode);
573
574 QSSGRenderModel *model = static_cast<QSSGRenderModel *>(spatialNode);
575
576 if (!model->particleBuffer) {
577 QSSGParticleBuffer *buffer = model->particleBuffer = new QSSGParticleBuffer;
578 buffer->resize(m_particleCount, sizeof(QSSGTriangleParticle));
579 }
581 QMatrix4x4 particleMatrix = psystem->sceneTransform().inverted() * m_model->sceneTransform();
582 model->particleMatrix = particleMatrix.inverted();
584 updateParticleBuffer(model->particleBuffer, psystem->sceneTransform());
585
586 return node;
587}
588
590{
591 if (!system() && qobject_cast<QQuick3DParticleSystem *>(parentItem()))
592 setSystem(qobject_cast<QQuick3DParticleSystem *>(parentItem()));
593
594 // don't call particles componentComplete, we don't wan't to emit maxAmountChanged yet
596 regenerate();
597}
598
600{
601 qWarning() << "ModelBlendParticle3D.maxAmount: Unable to set maximum amount, because it is set from the model.";
602 return;
603}
604
606{
607 if (!m_perEmitterData.contains(emitter)) {
608 m_perEmitterData.insert(emitter, PerEmitterData());
609 auto &perEmitter = m_perEmitterData[emitter];
610 perEmitter.emitter = emitter;
611 perEmitter.emitterIndex = m_nextEmitterIndex++;
612 }
613 auto &perEmitter = m_perEmitterData[emitter];
615 if (m_triangleParticleData[index].emitterIndex != perEmitter.emitterIndex) {
616 if (m_triangleParticleData[index].emitterIndex >= 0)
617 perEmitterData(m_triangleParticleData[index].emitterIndex).particleCount--;
618 perEmitter.particleCount++;
619 }
620 m_triangleParticleData[index].emitterIndex = perEmitter.emitterIndex;
621 return index;
622}
623
624
626 const QVector3D &position,
627 const QVector3D &rotation,
628 const QVector4D &color,
629 float size, float age)
630{
631 auto &dst = m_triangleParticleData[particleIndex];
632 dst = {position, rotation, dst.center, color, age, size, dst.emitterIndex};
633 m_dataChanged = true;
634}
635
636QQuick3DParticleModelBlendParticle::PerEmitterData &QQuick3DParticleModelBlendParticle::perEmitterData(int emitterIndex)
637{
638 for (auto &perEmitter : m_perEmitterData) {
639 if (perEmitter.emitterIndex == emitterIndex)
640 return perEmitter;
641 }
642 return n_noPerEmitterData;
643}
644
645void QQuick3DParticleModelBlendParticle::updateParticleBuffer(QSSGParticleBuffer *buffer, const QMatrix4x4 &sceneTransform)
646{
647 const auto &particles = m_triangleParticleData;
648
649 if (!buffer || !m_dataChanged)
650 return;
651
652 const int particleCount = m_particleCount;
653
654 char *dest = buffer->pointer();
655 const TriangleParticleData *src = particles.data();
656 const int pps = buffer->particlesPerSlice();
657 const int ss = buffer->sliceStride();
658 const int slices = buffer->sliceCount();
659 const float c_degToRad = float(M_PI / 180.0f);
660 int i = 0;
661 QSSGBounds3 bounds;
662 for (int s = 0; s < slices; s++) {
663 QSSGTriangleParticle *dp = reinterpret_cast<QSSGTriangleParticle *>(dest);
664 for (int p = 0; p < pps && i < particleCount; ) {
665 if (src->size > 0.0f)
666 bounds.include(src->position);
667 dp->position = src->position;
668 dp->rotation = src->rotation * c_degToRad;
669 dp->color = src->color;
670 dp->age = src->age;
671 dp->center = src->center;
672 dp->size = src->size;
673 dp++;
674 p++;
675 i++;
676 src++;
677 }
678 dest += ss;
679 }
680
681 bounds.fatten(m_maxTriangleRadius);
683 buffer->setBounds(bounds);
684 m_dataChanged = false;
685}
686
687void QQuick3DParticleModelBlendParticle::itemChange(QQuick3DObject::ItemChange change,
688 const QQuick3DObject::ItemChangeData &value)
689{
691 if (change == ItemParentHasChanged && value.sceneManager)
692 regenerate();
693}
694
696{
698 if (m_particleCount) {
699 for (int i = 0; i < m_particleCount; i++) {
700 if (m_modelBlendMode == Construct) {
701 m_triangleParticleData[i].size = 0.0f;
702 } else {
703 m_triangleParticleData[i].size = 1.0f;
704 m_triangleParticleData[i].position = m_triangleParticleData[i].center;
705 }
706 }
707 }
708}
709
711{
712 return m_centerData[particleIndex];
713}
714
716{
717 return m_currentIndex >= m_maxAmount - 1;
718}
719
720static QMatrix3x3 qt_fromEulerRotation(const QVector3D &eulerRotation)
721{
722 float x = qDegreesToRadians(eulerRotation.x());
723 float y = qDegreesToRadians(eulerRotation.y());
724 float z = qDegreesToRadians(eulerRotation.z());
725 float a = cos(x);
726 float b = sin(x);
727 float c = cos(y);
728 float d = sin(y);
729 float e = cos(z);
730 float f = sin(z);
732 float bd = b * d;
733 float ad = a * d;
734 ret(0,0) = c * e;
735 ret(0,1) = -c * f;
736 ret(0,2) = d;
737 ret(1,0) = bd * e + a * f;
738 ret(1,1) = a * e - bd * f;
739 ret(1,2) = -b * c;
740 ret(2,0) = b * f - ad * e;
741 ret(2,1) = ad * f + b * e;
742 ret(2,2) = a * c;
743 return ret;
744}
745
746void QQuick3DParticleModelBlendParticle::handleEndNodeChanged()
747{
748 if (m_endNode && m_model) {
749 if (!m_model->rotation().isIdentity()) {
750 // Use the same function as the shader for end node rotation so that they produce same matrix
752 QMatrix3x3 r2 = m_model->rotation().toRotationMatrix();
754 m_endNodeRotation = m_endNode->eulerRotation();
755 m_endRotationMatrix = QMatrix4x4(r);
756 } else {
757 m_endNodeRotation = m_endNode->eulerRotation();
758 m_endRotationMatrix = QMatrix4x4(m_endNode->rotation().toRotationMatrix().transposed());
759 }
760 m_endNodePosition = m_endNode->position();
761 m_endNodeScale = m_endNode->scale();
762 } else {
763 m_endNodePosition = QVector3D();
764 m_endNodeRotation = QVector3D();
765 m_endNodeScale = QVector3D(1.0f, 1.0f, 1.0f);
766 m_endRotationMatrix.setToIdentity();
767 }
768}
769
771{
772 return m_endRotationMatrix.map(QVector3D(m_endNodeScale * m_centerData[idx])) + m_endNodePosition;
773}
774
776{
777 return m_endNodeRotation;
778}
779
781{
782 if (m_randomParticles.isEmpty()) {
783 m_randomParticles.resize(m_maxAmount);
784 for (int i = 0; i < m_maxAmount; i++)
785 m_randomParticles[i] = i;
786
787 // Randomize particle indices just once
788 QRandomGenerator rand(system()->rand()->generator());
789 for (int i = 0; i < m_maxAmount; i++) {
790 int ridx = rand.generate() % m_maxAmount;
791 if (i != ridx)
792 qSwap(m_randomParticles[i], m_randomParticles[ridx]);
793 }
794 }
795 return m_randomParticles[particleIndex];
796}
797
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:534
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first byte in the byte-array.
Definition qbytearray.h:428
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2395
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
QGenericMatrix< M, N, T > transposed() const
Returns this matrix, transposed about its diagonal.
Definition qlist.h:74
QList< T > & fill(parameter_type t, qsizetype size=-1)
Definition qlist.h:896
void resize(qsizetype size)
Definition qlist.h:392
iterator insert(const Key &key, const T &value)
Definition qmap.h:687
bool contains(const Key &key) const
Definition qmap.h:340
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:2823
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
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 QFile.
Definition qqmlfile.cpp:643
bool isIdentity() const
Returns true if the x, y, and z components of this quaternion are set to 0.0, and the scalar componen...
QMatrix3x3 toRotationMatrix() const
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)
QSSGRenderGraphObject * spatialNode
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:266
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:116
static Mesh loadMesh(QIODevice *device, quint32 id=0)
Definition qssgmesh.cpp:581
VertexBuffer vertexBuffer() const
Definition qssgmesh_p.h:97
IndexBuffer indexBuffer() const
Definition qssgmesh_p.h:98
QVector< Subset > subsets() const
Definition qssgmesh_p.h:100
DrawMode drawMode() const
Definition qssgmesh_p.h:118
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
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]
qSwap(pi, e)
double e
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
Definition qnumeric.h:366
QVector3D Q_QUICK3DUTILS_EXPORT getScale(const QMatrix4x4 &m)
static void * context
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:162
return ret
#define M_PI
Definition qmath.h:209
constexpr float qDegreesToRadians(float degrees)
Definition qmath.h:260
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
GLenum GLenum dst
GLenum GLuint GLintptr offset
GLuint name
GLint y
GLsizei GLsizei GLchar * source
GLuint GLenum GLenum transform
GLhandleARB obj
[2]
const GLubyte * c
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLenum GLenum GLenum GLenum GLenum scale
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
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
#define Q_EMIT
unsigned int quint32
Definition qtypes.h:45
unsigned short quint16
Definition qtypes.h:43
unsigned char quint8
Definition qtypes.h:41
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:17
static const char * getPositionAttrName()
Definition qssgmesh_p.h:349
void resize(int particleCount, int particleSize=sizeof(QSSGParticleSimple))
Definition moc.h:24
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent