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
qquick3dparticleemitter.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
10
12
35
37{
38 qDeleteAll(m_emitBursts);
39 m_emitBursts.clear();
40 if (m_system)
41 m_system->unRegisterParticleEmitter(this);
42}
43
55{
56 return m_enabled;
57}
59{
60 if (m_enabled == enabled)
61 return;
62
63 if (enabled && m_system) {
64 // When enabling, we need to reset the
65 // previous emit time as it might be a long time ago.
66 m_prevEmitTime = m_system->currentTime();
67 m_prevBurstTime = m_prevEmitTime;
68 }
69
70 m_enabled = enabled;
72}
73
82{
83 return m_velocity;
84}
85
87{
88 if (m_velocity == velocity)
89 return;
90
91 m_velocity = velocity;
92 if (m_velocity && m_system)
93 m_velocity->m_system = m_system;
94
96}
97
105{
106 return m_system;
107}
108
110{
111 if (m_system == system)
112 return;
113
114 if (m_system)
115 m_system->unRegisterParticleEmitter(this);
116
117 m_system = system;
118 if (m_system) {
119 m_system->registerParticleEmitter(this);
120 // Reset prev emit time to time of the new system
121 m_prevEmitTime = m_system->currentTime();
122 m_prevBurstTime = m_prevEmitTime;
123 }
124
125 if (m_particle)
126 m_particle->setSystem(m_system);
127
128 if (m_shape)
129 m_shape->m_system = m_system;
130
131 if (m_velocity)
132 m_velocity->m_system = m_system;
133
134 m_systemSharedParent = getSharedParentNode(this, m_system);
135
137}
138
149{
150 return m_emitRate;
151}
152
154{
155 if (qFuzzyCompare(m_emitRate, emitRate))
156 return;
157
158 if (m_emitRate == 0 && m_system) {
159 // When changing emit rate from 0 we need to reset
160 // previous emit time as it may be long time ago
161 m_prevEmitTime = m_system->currentTime();
162 }
163 m_emitRate = emitRate;
165}
166
167
179{
180 return m_particleScale;
181}
182
184{
185 if (qFuzzyCompare(m_particleScale, particleScale))
186 return;
187
188 m_particleScale = particleScale;
190}
191
206{
207 return m_particleEndScale;
208}
209
211{
212 if (qFuzzyCompare(m_particleEndScale, particleEndScale))
213 return;
214
215 m_particleEndScale = particleEndScale;
217}
218
238{
239 return m_particleScaleVariation;
240}
241
243{
244 if (qFuzzyCompare(m_particleScaleVariation, particleScaleVariation))
245 return;
246
247 m_particleScaleVariation = particleScaleVariation;
249}
250
274{
275 return m_particleEndScaleVariation;
276}
277
278void QQuick3DParticleEmitter::setParticleEndScaleVariation(float particleEndScaleVariation)
279{
280 if (qFuzzyCompare(m_particleEndScaleVariation, particleEndScaleVariation))
281 return;
282
283 m_particleEndScaleVariation = particleEndScaleVariation;
285}
286
297{
298 return m_lifeSpan;
299}
300
302{
303 if (m_lifeSpan == lifeSpan)
304 return;
305
306 m_lifeSpan = lifeSpan;
308}
309
330{
331 return m_lifeSpanVariation;
332}
333
335{
336 if (m_lifeSpanVariation == lifeSpanVariation)
337 return;
338
339 m_lifeSpanVariation = lifeSpanVariation;
341}
342
351{
352 return m_particle;
353}
354
356{
357 if (m_particle == particle)
358 return;
359 if (particle && particle->system() != nullptr && m_system && particle->system() != m_system) {
360 qWarning("ParticleEmitter3D: Emitter and Particle must be in the same system.");
361 return;
362 }
363
364 if (m_particle && m_system && !m_system->isShared(m_particle))
365 m_particle->setSystem(nullptr);
366 m_particle = particle;
367 if (particle) {
368 particle->setDepthBias(m_depthBias);
371 m_particle->setDepthBias(m_depthBias);
372 });
373 }
375}
376
393
395{
396 if (m_shape == shape)
397 return;
398
399 m_shape = shape;
400 if (m_shape && m_system)
401 m_shape->m_system = m_system;
403}
404
414{
415 return m_particleRotation;
416}
417
419{
420 if (m_particleRotation == particleRotation)
421 return;
422
423 m_particleRotation = particleRotation;
425}
426
445{
446 return m_particleRotationVariation;
447}
448
450{
451 if (m_particleRotationVariation == particleRotationVariation)
452 return;
453
454 m_particleRotationVariation = particleRotationVariation;
456}
457
467{
468 return m_particleRotationVelocity;
469}
470
472{
473 if (m_particleRotationVelocity == particleRotationVelocity)
474 return;
475
476 m_particleRotationVelocity = particleRotationVelocity;
478}
479
500{
501 return m_particleRotationVelocityVariation;
502}
503
505{
506 if (m_particleRotationVelocityVariation == particleRotationVelocityVariation)
507 return;
508
509 m_particleRotationVelocityVariation = particleRotationVelocityVariation;
511}
512
522{
523 return m_depthBias;
524}
525
527{
528 if (qFuzzyCompare(bias, m_depthBias))
529 return;
530
531 m_depthBias = bias;
533}
534
535// Called to reset when system stop/continue
537{
538 m_prevEmitTime = 0;
539 m_unemittedF = 0.0f;
540 m_prevBurstTime = 0;
541 m_burstEmitData.clear();
542}
543
553
561{
562 burst(count, duration, QVector3D());
563}
564
573{
574 if (!m_system)
575 return;
577 burst.time = m_system->currentTime();
578 burst.amount = count;
579 burst.duration = duration;
580 burst.position = position;
582}
583
585{
586 if (!m_system)
587 return;
588
589 if (!m_particle)
590 return;
591
592 if (m_emitBursts.isEmpty()) {
593 m_burstGenerated = true;
594 return;
595 }
596
597 // Generating burst causes all particle data reseting
598 // as bursts take first particles in the list.
599 m_particle->reset();
600
601 // TODO: In trail emitter case centerPos should be calculated
602 // taking into account each particle position at emitburst time
604 QQuaternion rotation = calculateParticleRotation(parentNode(), m_systemSharedParent);
605 QVector3D centerPos = position();
606
607 for (auto emitBurst : std::as_const(m_emitBursts)) {
608 // Ignore all dynamic bursts here
609 if (qobject_cast<QQuick3DParticleDynamicBurst *>(emitBurst))
610 continue;
611 int emitAmount = emitBurst->amount();
612 if (emitAmount <= 0)
613 return;
614 // Distribute start times between burst time and time+duration.
615 float startTime = float(emitBurst->time() / 1000.0f);
616 float timeStep = float(emitBurst->duration() / 1000.0f) / emitAmount;
617 for (int i = 0; i < emitAmount; i++) {
618 emitParticle(m_particle, startTime, transform, rotation, centerPos);
619 startTime += timeStep;
620 }
621 // Increase burst index (for statically allocated particles)
622 m_particle->updateBurstIndex(emitBurst->amount());
623 }
624 m_burstGenerated = true;
625}
626
628{
629 m_emitBursts.removeAll(emitBurst);
630 m_emitBursts << emitBurst;
631 m_burstGenerated = false;
632}
633
635{
636 m_emitBursts.removeAll(emitBurst);
637 m_burstGenerated = false;
638}
639
640void QQuick3DParticleEmitter::emitParticle(QQuick3DParticle *particle, float startTime, const QMatrix4x4 &transform, const QQuaternion &parentRotation, const QVector3D &centerPos, int index)
641{
642 if (!m_system)
643 return;
644 auto rand = m_system->rand();
645
646 QQuick3DParticleModelBlendParticle *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(particle);
647 if (mbp && mbp->lastParticle())
648 return;
649
650 int particleDataIndex = index == -1 ? particle->nextCurrentIndex(this) : index;
651 if (index == -1 && mbp && mbp->emitMode() == QQuick3DParticleModelBlendParticle::Random)
652 particleDataIndex = mbp->randomIndex(particleDataIndex);
653
654 auto d = &particle->m_particleData[particleDataIndex];
655 int particleIdIndex = m_system->m_particleIdIndex++;
656 if (m_system->m_particleIdIndex == INT_MAX)
657 m_system->m_particleIdIndex = 0;
658
659 *d = m_clearData; // Reset the data as it might be reused
660 d->index = particleIdIndex;
661 d->startTime = startTime;
662
663 // Life time in seconds
664 float lifeSpanMs = m_lifeSpanVariation / 1000.0f;
665 float lifeSpanVariationMs = lifeSpanMs - 2.0f * rand->get(particleIdIndex, QPRand::LifeSpanV) * lifeSpanMs;
666 d->lifetime = (m_lifeSpan / 1000.0f) + lifeSpanVariationMs;
667
668 // Size
669 float sVar = m_particleScaleVariation - 2.0f * rand->get(particleIdIndex, QPRand::ScaleV) * m_particleScaleVariation;
670 float endScale = (m_particleEndScale < 0.0f) ? m_particleScale : m_particleEndScale;
671 float sEndVar = (m_particleEndScaleVariation < 0.0f)
672 ? sVar
673 : m_particleEndScaleVariation - 2.0f * rand->get(particleIdIndex, QPRand::ScaleEV) * m_particleEndScaleVariation;
674 d->startSize = std::max(0.0f, float(m_particleScale + sVar));
675 d->endSize = std::max(0.0f, float(endScale + sEndVar));
676
677 // Emiting area/shape
678 if (mbp && mbp->modelBlendMode() != QQuick3DParticleModelBlendParticle::Construct) {
679 // We emit from model position unless in construct mode
680 d->startPosition = mbp->particleCenter(particleDataIndex);
681 } else {
682 // When shape is not set, default to node center point.
683 QVector3D pos = centerPos;
684 if (m_shape)
685 pos += m_shape->getPosition(particleIdIndex);
686 d->startPosition = transform.map(pos);
687 }
688
689 // Velocity
690 if (m_velocity) {
691 // Rotate velocity based on parent node rotation and emitter rotation
692 d->startVelocity = parentRotation * rotation() * m_velocity->sample(*d);
693 }
694
695 // Rotation
696 if (!m_particleRotation.isNull() || !m_particleRotationVariation.isNull()) {
697 Vector3b rot;
698 constexpr float step = 127.0f / 360.0f; // +/- 360-degrees as qint8 (-127..127)
699 rot.x = m_particleRotation.x() * step;
700 rot.y = m_particleRotation.y() * step;
701 rot.z = m_particleRotation.z() * step;
702 rot.x += (m_particleRotationVariation.x() - 2.0f * rand->get(particleIdIndex, QPRand::RotXV) * m_particleRotationVariation.x()) * step;
703 rot.y += (m_particleRotationVariation.y() - 2.0f * rand->get(particleIdIndex, QPRand::RotYV) * m_particleRotationVariation.y()) * step;
704 rot.z += (m_particleRotationVariation.z() - 2.0f * rand->get(particleIdIndex, QPRand::RotZV) * m_particleRotationVariation.z()) * step;
705 d->startRotation = rot;
706 }
707 // Rotation velocity
708 if (!m_particleRotationVelocity.isNull() || !m_particleRotationVelocityVariation.isNull()) {
709 float rotVelX = m_particleRotationVelocity.x();
710 float rotVelY = m_particleRotationVelocity.y();
711 float rotVelZ = m_particleRotationVelocity.z();
712 rotVelX += (m_particleRotationVelocityVariation.x() - 2.0f * rand->get(particleIdIndex, QPRand::RotXVV) * m_particleRotationVelocityVariation.x());
713 rotVelY += (m_particleRotationVelocityVariation.y() - 2.0f * rand->get(particleIdIndex, QPRand::RotYVV) * m_particleRotationVelocityVariation.y());
714 rotVelZ += (m_particleRotationVelocityVariation.z() - 2.0f * rand->get(particleIdIndex, QPRand::RotZVV) * m_particleRotationVelocityVariation.z());
715 // Particle data rotations are in qint8 vec3 to save memory.
716 // max value 127*127 = 16129 degrees/second
717 float sign;
718 sign = rotVelX < 0.0f ? -1.0f : 1.0f;
719 rotVelX = std::max(-127.0f, std::min<float>(127.0f, sign * std::sqrt(abs(rotVelX))));
720 sign = rotVelY < 0.0f ? -1.0f : 1.0f;
721 rotVelY = std::max(-127.0f, std::min<float>(127.0f, sign * std::sqrt(abs(rotVelY))));
722 sign = rotVelZ < 0.0f ? -1.0f : 1.0f;
723 rotVelZ = std::max(-127.0f, std::min<float>(127.0f, sign * std::sqrt(abs(rotVelZ))));
724 d->startRotationVelocity = { qint8(rotVelX), qint8(rotVelY), qint8(rotVelZ) };
725 }
726
727 // Colors
728 QColor pc = particle->color();
730 uchar r, g, b, a;
732 // Vary all color channels using the same random amount
733 const int randVar = int(rand->get(particleIdIndex, QPRand::ColorAV) * 256);
734 r = pc.red() * (1.0f - pcv.x()) + randVar * pcv.x();
735 g = pc.green() * (1.0f - pcv.y()) + randVar * pcv.y();
736 b = pc.blue() * (1.0f - pcv.z()) + randVar * pcv.z();
737 a = pc.alpha() * (1.0f - pcv.w()) + randVar * pcv.w();
738 } else {
739 r = pc.red() * (1.0f - pcv.x()) + int(rand->get(particleIdIndex, QPRand::ColorRV) * 256) * pcv.x();
740 g = pc.green() * (1.0f - pcv.y()) + int(rand->get(particleIdIndex, QPRand::ColorGV) * 256) * pcv.y();
741 b = pc.blue() * (1.0f - pcv.z()) + int(rand->get(particleIdIndex, QPRand::ColorBV) * 256) * pcv.z();
742 a = pc.alpha() * (1.0f - pcv.w()) + int(rand->get(particleIdIndex, QPRand::ColorAV) * 256) * pcv.w();
743 }
744 d->startColor = {r, g, b, a};
745
746 // Sprite sequence animation
747 if (auto sequence = particle->m_spriteSequence) {
748 if (sequence->duration() > 0) {
749 float animationTimeMs = float(sequence->duration()) / 1000.0f;
750 float animationTimeVarMs = float(sequence->durationVariation()) / 1000.0f;
751 animationTimeVarMs = animationTimeVarMs - 2.0f * rand->get(particleIdIndex, QPRand::SpriteAnimationV) * animationTimeVarMs;
752 // Sequence duration to be at least 1ms
753 const float MIN_DURATION = 0.001f;
754 d->animationTime = std::max(MIN_DURATION, animationTimeMs + animationTimeVarMs);
755 } else {
756 // Duration not set, so use the lifetime of the particle
757 d->animationTime = d->lifetime;
758 }
759 }
760}
761
763{
764 int amount = 0;
765 const int currentTime = m_system->time();
766 const int prevTime = m_prevBurstTime;
767 // First go through dynamic bursts and see if any of them tiggers
768 for (auto *burst : std::as_const(m_emitBursts)) {
769 auto *burstPtr = qobject_cast<QQuick3DParticleDynamicBurst *>(burst);
770 if (!burstPtr)
771 continue;
772 if (!burstPtr->m_enabled)
773 continue;
774 // Trigering on trail emitter start / end
775 const bool trailTriggering = triggerType && (burstPtr->m_triggerMode) == triggerType;
776 // Triggering on time for the first time
777 const bool timeTriggeringStart = !triggerType && currentTime >= burstPtr->m_time && prevTime <= burstPtr->m_time;
778 if (trailTriggering || timeTriggeringStart) {
779 int burstAmount = burstPtr->m_amount;
780 if (burstPtr->m_amountVariation > 0) {
781 auto rand = m_system->rand();
782 int randAmount = 2 * rand->get() * burstPtr->m_amountVariation;
783 burstAmount += burstPtr->m_amountVariation - randAmount;
784 }
785 if (burstAmount > 0) {
786 if (timeTriggeringStart && burstPtr->m_duration > 0) {
787 // Burst with duration, so generate burst data
788 BurstEmitData emitData;
789 emitData.startTime = currentTime;
790 emitData.endTime = currentTime + burstPtr->m_duration;
791 emitData.emitAmount = burstAmount;
792 emitData.prevBurstTime = prevTime;
793 m_burstEmitData << emitData;
794 } else {
795 // Directly trigger the amount
796 amount += burstAmount;
797 }
798 }
799 }
800 }
801 // Then go through the triggered emit bursts list
802 for (int burstIndex = 0; burstIndex < m_burstEmitData.size(); ++burstIndex) {
803 auto &burstData = m_burstEmitData[burstIndex];
804 const int amountLeft = burstData.emitAmount - burstData.emitCounter;
805 if (currentTime >= burstData.endTime) {
806 // Burst time has ended, emit all rest of the particles and remove the burst
807 amount += amountLeft;
808 m_burstEmitData.removeAt(burstIndex);
809 } else {
810 // Otherwise burst correct amount depending on burst duration
811 const int durationTime = currentTime - burstData.prevBurstTime;
812 const int burstDurationTime = burstData.endTime - burstData.startTime;
813 int burstAmount = burstData.emitAmount * (float(durationTime) / float(burstDurationTime));
814 burstAmount = std::min(amountLeft, burstAmount);
815 if (burstAmount > 0) {
816 amount += burstAmount;
817 burstData.emitCounter += burstAmount;
818 burstData.prevBurstTime = currentTime;
819 }
820 }
821 }
822 // Reset the prev burst time
823 m_prevBurstTime = currentTime;
824 return amount;
825}
826
828{
829 if (!m_system)
830 return 0;
831
832 if (!m_enabled)
833 return 0;
834
835 if (m_emitRate <= 0.0f)
836 return 0;
837
838 float timeChange = m_system->currentTime() - m_prevEmitTime;
839 float emitAmountF = timeChange / (1000.0f / m_emitRate);
840 int emitAmount = floorf(emitAmountF);
841 // Store the partly unemitted particles
842 // When emitAmount = 0, we just let the timeChange grow.
843 if (emitAmount > 0) {
844 m_unemittedF += (emitAmountF - emitAmount);
845 // When unemitted grow to a full particle, emit it
846 // This way if emit rate is 140 emitAmounts can be e.g. 2,2,3,2,2,3 etc.
847 if (m_unemittedF >= 1.0f) {
848 emitAmount++;
849 m_unemittedF--;
850 }
851 }
852 return emitAmount;
853}
854
856{
857 if (!m_system)
858 return;
859
860 if (!m_enabled)
861 return;
862
863 if (!m_particle)
864 return;
865
867 QQuaternion rotation = calculateParticleRotation(parentNode(), m_systemSharedParent);
868 QVector3D centerPos = position() + burst.position;
869
870 int emitAmount = std::min(burst.amount, int(m_particle->maxAmount()));
871 for (int i = 0; i < emitAmount; i++) {
872 // Distribute evenly between time and time+duration.
873 float startTime = (burst.time / 1000.0f) + (float(1 + i) / emitAmount) * ((burst.duration) / 1000.0f);
874 emitParticle(m_particle, startTime, transform, rotation, centerPos);
875 }
876}
877
878// Called to emit set of particles
880{
881 if (!m_system)
882 return;
883
884 if (!m_enabled)
885 return;
886
887 if (!m_particle)
888 return;
889
890 auto *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(m_particle);
891 if (mbp && mbp->activationNode() && mbp->emitMode() == QQuick3DParticleModelBlendParticle::Activation) {
892 // The particles are emitted using the activationNode instead of regular emit
894 return;
895 }
896
897 const int systemTime = m_system->currentTime();
898
899 if (systemTime < m_prevEmitTime) {
900 // If we are goint backwards, reset previous emit time to current time.
901 m_prevEmitTime = systemTime;
902 } else {
903 // Keep previous emitting time within max the life span.
904 // This way emitting is reasonable also with big time jumps.
905 const int maxLifeSpan = m_lifeSpan + m_lifeSpanVariation;
906 m_prevEmitTime = std::max(m_prevEmitTime, systemTime - maxLifeSpan);
907 }
908
909 // If bursts have changed, generate them first in the beginning
910 if (!m_burstGenerated)
912
913 int emitAmount = getEmitAmount() + getEmitAmountFromDynamicBursts();
914
915 // With lower emitRates, let timeChange grow until at least 1 particle is emitted
916 if (emitAmount < 1)
917 return;
918
920 QQuaternion rotation = calculateParticleRotation(parentNode(), m_systemSharedParent);
921 QVector3D centerPos = position();
922
923 emitAmount = std::min(emitAmount, int(m_particle->maxAmount()));
924 for (int i = 0; i < emitAmount; i++) {
925 // Distribute evenly between previous and current time, important especially
926 // when time has jumped a lot (like a starttime).
927 float startTime = (m_prevEmitTime / 1000.0f) + (float(1+i) / emitAmount) * ((systemTime - m_prevEmitTime) / 1000.0f);
928 emitParticle(m_particle, startTime, transform, rotation, centerPos);
929 }
930
931 m_prevEmitTime = systemTime;
932}
933
935{
936 QMatrix4x4 matrix = particle->activationNode()->sceneTransform();
937 QMatrix4x4 actTransform = sceneTransform().inverted() * matrix;
938 QVector3D front = actTransform.column(2).toVector3D();
939 QVector3D pos = actTransform.column(3).toVector3D();
940 float d = QVector3D::dotProduct(pos, front);
941
942 const int systemTime = m_system->currentTime();
943
944 // Keep previous emitting time within max the life span.
945 // This way emitting is reasonable also with big time jumps.
946 const int maxLifeSpan = m_lifeSpan + m_lifeSpanVariation;
947 m_prevEmitTime = std::max(m_prevEmitTime, systemTime - maxLifeSpan);
948
949 float startTime = systemTime / 1000.0f;
950
952 QQuaternion rotation = calculateParticleRotation(parentNode(), m_systemSharedParent);
953 QVector3D centerPos = position();
954
955 for (int i = 0; i < particle->maxAmount(); i++) {
956 if (particle->m_particleData[i].startTime >= 0)
957 continue;
958 const QVector3D pc = particle->particleCenter(i);
959 if (QVector3D::dotProduct(front, pc) - d > 0.0f)
961 }
962
963 m_prevEmitTime = systemTime;
964}
965
967{
968 if (!m_system && qobject_cast<QQuick3DParticleSystem *>(parentItem()))
969 setSystem(qobject_cast<QQuick3DParticleSystem *>(parentItem()));
970
971 // When dynamically creating emitters, start from the current time.
972 if (m_system)
973 m_prevEmitTime = m_system->currentTime();
974
976}
977
978// EmitBursts - list handling
979
1006QQmlListProperty<QQuick3DParticleEmitBurst> QQuick3DParticleEmitter::emitBursts()
1007{
1008 return {this, this,
1015}
1016
1020
1022{
1023 return m_emitBursts.size();
1024}
1025
1030
1032 m_emitBursts.clear();
1033}
1034
1039
1041{
1042 m_emitBursts.removeLast();
1043}
1044
1045// EmitBursts - static
1046void QQuick3DParticleEmitter::appendEmitBurst(QQmlListProperty<QQuick3DParticleEmitBurst> *list, QQuick3DParticleEmitBurst *p) {
1047 reinterpret_cast< QQuick3DParticleEmitter *>(list->data)->appendEmitBurst(p);
1048}
1049
1050void QQuick3DParticleEmitter::clearEmitBursts(QQmlListProperty<QQuick3DParticleEmitBurst> *list) {
1051 reinterpret_cast< QQuick3DParticleEmitter *>(list->data)->clearEmitBursts();
1052}
1053
1054void QQuick3DParticleEmitter::replaceEmitBurst(QQmlListProperty<QQuick3DParticleEmitBurst> *list, qsizetype i, QQuick3DParticleEmitBurst *p)
1055{
1056 reinterpret_cast< QQuick3DParticleEmitter *>(list->data)->replaceEmitBurst(i, p);
1057}
1058
1059void QQuick3DParticleEmitter::removeLastEmitBurst(QQmlListProperty<QQuick3DParticleEmitBurst> *list)
1060{
1061 reinterpret_cast< QQuick3DParticleEmitter *>(list->data)->removeLastEmitBurst();
1062}
1063
1064QQuick3DParticleEmitBurst* QQuick3DParticleEmitter::emitBurst(QQmlListProperty<QQuick3DParticleEmitBurst> *list, qsizetype i) {
1065 return reinterpret_cast< QQuick3DParticleEmitter *>(list->data)->emitBurst(i);
1066}
1067
1068qsizetype QQuick3DParticleEmitter::emitBurstCount(QQmlListProperty<QQuick3DParticleEmitBurst> *list) {
1069 return reinterpret_cast< QQuick3DParticleEmitter *>(list->data)->emitBurstCount();
1070}
1071
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
int alpha() const noexcept
Returns the alpha color component of this color.
Definition qcolor.cpp:1466
int red() const noexcept
Returns the red color component of this color.
Definition qcolor.cpp:1528
int blue() const noexcept
Returns the blue color component of this color.
Definition qcolor.cpp:1583
int green() const noexcept
Returns the green color component of this color.
Definition qcolor.cpp:1555
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
void removeAt(qsizetype i)
Definition qlist.h:590
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
qsizetype removeAll(const AT &t)
Definition qlist.h:592
pointer data()
Definition qlist.h:431
void removeLast() noexcept
Definition qlist.h:815
void append(parameter_type t)
Definition qlist.h:458
void clear()
Definition qlist.h:434
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.
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
float get(int particleIndex, UserType user=Default)
The QQuaternion class represents a quaternion consisting of a vector and scalar.
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QMatrix4x4 sceneTransform
QQuick3DNode * parentNode() const
QQuaternion rotation
QVector3D position
virtual QVector3D getPosition(int particleIndex)=0
virtual QVector3D sample(const QQuick3DParticleData &d)=0
void setShape(QQuick3DParticleAbstractShape *shape)
void setParticleEndScaleVariation(float particleEndScaleVariation)
QQmlListProperty< QQuick3DParticleEmitBurst > emitBursts
\qmlproperty List<EmitBurst3D> ParticleEmitter3D::emitBursts
void setParticleRotationVelocityVariation(const QVector3D &particleRotationVelocityVariation)
void appendEmitBurst(QQuick3DParticleEmitBurst *)
void setParticleRotation(const QVector3D &particleRotation)
void setLifeSpanVariation(int lifeSpanVariation)
void particleRotationVariationChanged()
void setParticleEndScale(float particleEndScale)
void setParticleScaleVariation(float particleScaleVariation)
void particleRotationVelocityChanged()
void particleScaleVariationChanged()
void setParticleRotationVariation(const QVector3D &particleRotationVariation)
int getEmitAmountFromDynamicBursts(int triggerType=0)
QQuick3DParticleSystem * system
void emitActivationNodeParticles(QQuick3DParticleModelBlendParticle *particle)
void particleEndScaleVariationChanged()
void setVelocity(QQuick3DParticleDirection *velocity)
void setParticle(QQuick3DParticle *particle)
void emitParticlesBurst(const QQuick3DParticleEmitBurstData &burst)
QQuick3DParticleEmitBurst * emitBurst(qsizetype) const
QQuick3DParticleAbstractShape * shape
QQuick3DParticleDirection * velocity
void replaceEmitBurst(qsizetype, QQuick3DParticleEmitBurst *)
virtual Q_INVOKABLE void burst(int count)
\qmlmethod vector3d ParticleEmitter3D::burst(int count)
void setParticleRotationVelocity(const QVector3D &particleRotationVelocity)
void emitParticle(QQuick3DParticle *particle, float startTime, const QMatrix4x4 &transform, const QQuaternion &parentRotation, const QVector3D &centerPos, int index=-1)
void registerEmitBurst(QQuick3DParticleEmitBurst *emitBurst)
void unRegisterEmitBurst(QQuick3DParticleEmitBurst *emitBurst)
QQuick3DParticleEmitter(QQuick3DNode *parent=nullptr)
\qmltype ParticleEmitter3D \inherits Node \inqmlmodule QtQuick3D.Particles3D
void setParticleScale(float particleScale)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void setSystem(QQuick3DParticleSystem *system)
void particleRotationVariationVelocityChanged()
void unRegisterParticleEmitter(QQuick3DParticleEmitter *e)
bool isShared(const QQuick3DParticle *particle) const
void registerParticleEmitter(QQuick3DParticleEmitter *e)
int currentTime() const
Returns the current time of the system (m_time + m_startTime).
QList< QQuick3DParticleData > m_particleData
QQuick3DParticleSpriteSequence * m_spriteSequence
virtual int nextCurrentIndex(const QQuick3DParticleEmitter *emitter)
void setSystem(QQuick3DParticleSystem *system)
QQuick3DParticleSystem * system() const
virtual void setDepthBias(float bias)
void updateBurstIndex(int amount)
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
constexpr bool isNull() const noexcept
Returns true if the x, y, and z coordinates are set to 0.0, otherwise returns false.
Definition qvectornd.h:665
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
static constexpr float dotProduct(QVector3D v1, QVector3D v2) noexcept
Returns the dot product of v1 and v2.
Definition qvectornd.h:770
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
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
qint64 startTime
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
#define qWarning
Definition qlogging.h:166
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLboolean r
[2]
GLenum GLenum GLsizei count
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLboolean GLboolean g
GLfloat n
GLuint GLenum GLenum transform
GLfloat bias
GLuint GLenum matrix
GLfloat GLfloat p
[1]
QT_BEGIN_NAMESPACE const float MIN_DURATION
\qmltype Attractor3D \inherits Affector3D \inqmlmodule QtQuick3D.Particles3D
QQuick3DNode * getSharedParentNode(QQuick3DNode *node, QQuick3DNode *system)
QMatrix4x4 calculateParticleTransform(const QQuick3DNode *parent, const QQuick3DNode *systemSharedParent)
QQuaternion calculateParticleRotation(const QQuick3DNode *parent, const QQuick3DNode *systemSharedParent)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define Q_EMIT
#define emit
unsigned char uchar
Definition qtypes.h:32
ptrdiff_t qsizetype
Definition qtypes.h:165
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:45
static double currentTime()
static int sign(int x)
QList< int > list
[14]