6#include <QtQuick3D/private/qquick3dquaternionutils_p.h>
12#include <private/qqmldelegatemodel_p.h>
17#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
18#include <qtquick3d_tracepoints_p.h>
20#include <QtGui/qquaternion.h>
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
69QQuick3DParticleSystem::QQuick3DParticleSystem(QQuick3DNode *parent)
70 : QQuick3DNode(parent)
73 , m_initialized(
false)
74 , m_componentComplete(
false)
75 , m_animation(
new QQuick3DParticleSystemAnimation(
this))
76 , m_updateAnimation(
new QQuick3DParticleSystemUpdate(
this))
78 , m_loggingData(
new QQuick3DParticleSystemLogging(
this))
80 connect(m_loggingData, &QQuick3DParticleSystemLogging::loggingIntervalChanged, &m_loggingTimer, [
this]() {
81 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
85QQuick3DParticleSystem::~QQuick3DParticleSystem()
88 m_updateAnimation->stop();
90 for (
const auto &connection : std::as_const(m_connections))
91 QObject::disconnect(connection);
93 const auto particles = m_particles;
94 const auto emitters = m_emitters;
95 const auto trailEmitters = m_trailEmitters;
96 const auto affectors = m_affectors;
97 for (
auto *particle : particles)
98 particle->setSystem(
nullptr);
99 for (
auto *emitter : emitters)
100 emitter->setSystem(
nullptr);
101 for (
auto *emitter : trailEmitters)
102 emitter->setSystem(
nullptr);
103 for (
auto *affector : affectors)
104 affector->setSystem(
nullptr);
108
109
110
111
112
113
114
115
116
117
118bool QQuick3DParticleSystem::isRunning()
const
124
125
126
127
128
129
130
131
132bool QQuick3DParticleSystem::isPaused()
const
138
139
140
141
142
143
144
145
146
147int QQuick3DParticleSystem::startTime()
const
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173int QQuick3DParticleSystem::time()
const
179
180
181
182
183
184
185
186
187
188
189
190
191bool QQuick3DParticleSystem::useRandomSeed()
const
193 return m_useRandomSeed;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211int QQuick3DParticleSystem::seed()
const
217
218
219
220
221
222
223
224
225
226
227bool QQuick3DParticleSystem::logging()
const
233
234
235
236
237
238
239
240
241
242
243
244QQuick3DParticleSystemLogging *QQuick3DParticleSystem::loggingData()
const
246 return m_loggingData;
250
251
252
253
254
255
256
257
258void QQuick3DParticleSystem::reset()
260 for (
auto emitter : std::as_const(m_emitters))
262 for (
auto emitter : std::as_const(m_trailEmitters))
264 for (
auto particle : std::as_const(m_particles))
266 m_particleIdIndex = 0;
270
271
272
273int QQuick3DParticleSystem::currentTime()
const
275 return m_currentTime;
278void QQuick3DParticleSystem::setRunning(
bool running)
280 if (m_running != running) {
282 Q_EMIT runningChanged();
288 if (m_componentComplete && !m_running && m_useRandomSeed)
289 doSeedRandomization();
291 (m_running && !isEditorModeOn()) ? m_animation->start() : m_animation->stop();
295void QQuick3DParticleSystem::setPaused(
bool paused)
297 if (m_paused != paused) {
299 if (m_animation->state() != QAbstractAnimation::Stopped)
300 m_paused ? m_animation->pause() : m_animation->resume();
301 Q_EMIT pausedChanged();
305void QQuick3DParticleSystem::setStartTime(
int startTime)
307 if (m_startTime == startTime)
310 m_startTime = startTime;
311 m_updateAnimation->setDirty(
true);
312 Q_EMIT startTimeChanged();
315void QQuick3DParticleSystem::setTime(
int time)
322 m_updateAnimation->setDirty(
true);
324 Q_EMIT timeChanged();
327void QQuick3DParticleSystem::setUseRandomSeed(
bool randomize)
329 if (m_useRandomSeed == randomize)
332 m_useRandomSeed = randomize;
336 doSeedRandomization();
337 m_rand.setDeterministic(!m_useRandomSeed);
338 Q_EMIT useRandomSeedChanged();
341void QQuick3DParticleSystem::setSeed(
int seed)
348 Q_EMIT seedChanged();
351void QQuick3DParticleSystem::setLogging(
bool logging)
353 if (m_logging == logging)
358 resetLoggingVariables();
359 m_loggingData->resetData();
362 m_loggingTimer.start();
364 m_loggingTimer.stop();
366 Q_EMIT loggingChanged();
370
371
372
373void QQuick3DParticleSystem::setEditorTime(
int time)
375 if (m_editorTime == time)
380 m_updateAnimation->setDirty(
true);
383void QQuick3DParticleSystem::componentComplete()
385 QQuick3DNode::componentComplete();
386 m_componentComplete =
true;
387 m_updateAnimation->start();
389 connect(&m_loggingTimer, &QTimer::timeout,
this, &QQuick3DParticleSystem::updateLoggingData);
390 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
393 doSeedRandomization();
401 Q_EMIT timeChanged();
404 if (m_animation->state() == QAbstractAnimation::Running)
406 if (m_running && !isEditorModeOn())
407 m_animation->start();
409 m_animation->pause();
411 m_initialized =
true;
414void QQuick3DParticleSystem::refresh()
419 if (!m_running || m_paused || isEditorModeOn())
420 m_animation->setCurrentTime(isEditorModeOn() ? m_editorTime : m_time);
423void QQuick3DParticleSystem::markDirty()
426 m_updateAnimation->setDirty(
true);
429int QQuick3DParticleSystem::particleCount()
const
432 for (
auto particle : std::as_const(m_particles))
433 pCount += particle->maxAmount();
437void QQuick3DParticleSystem::registerParticle(QQuick3DParticle *particle)
439 m_particles << particle;
442void QQuick3DParticleSystem::unRegisterParticle(QQuick3DParticle *particle)
444 m_particles.removeAll(particle);
447void QQuick3DParticleSystem::registerParticleEmitter(QQuick3DParticleEmitter *e)
449 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
451 m_trailEmitters << te;
456void QQuick3DParticleSystem::unRegisterParticleEmitter(QQuick3DParticleEmitter *e)
458 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
460 m_trailEmitters.removeAll(te);
462 m_emitters.removeAll(e);
465void QQuick3DParticleSystem::registerParticleAffector(QQuick3DParticleAffector *a)
468 m_connections.insert(a, connect(a, &QQuick3DParticleAffector::update,
this, &QQuick3DParticleSystem::markDirty));
471void QQuick3DParticleSystem::unRegisterParticleAffector(QQuick3DParticleAffector *a)
473 QObject::disconnect(m_connections[a]);
474 m_connections.remove(a);
475 m_affectors.removeAll(a);
478void QQuick3DParticleSystem::updateCurrentTime(
int currentTime)
480 if (!m_initialized || isGloballyDisabled() || (isEditorModeOn() && !visible()))
483 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DParticleUpdate);
485 Q_TRACE(QSSG_particleUpdate_entry);
487 m_currentTime = currentTime;
488 const float timeS =
float(m_currentTime / 1000.0f);
497 for (
auto emitter : std::as_const(m_emitters))
498 emitter->emitParticles();
501 for (
auto affector : std::as_const(m_affectors)) {
502 if (affector->m_enabled)
503 affector->prepareToAffect();
507 for (
auto particle : std::as_const(m_particles)) {
510 QVector<TrailEmits> trailEmits;
511 for (
auto emitter : std::as_const(m_trailEmitters)) {
512 if (emitter->follow() == particle) {
513 int emitAmount = emitter->getEmitAmount();
514 if (emitAmount > 0 || emitter->hasBursts()) {
517 e.amount = emitAmount;
523 m_particlesMax += particle->maxAmount();
525 QQuick3DParticleSpriteParticle *spriteParticle = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
526 if (spriteParticle) {
527 processSpriteParticle(spriteParticle, trailEmits, timeS);
530 QQuick3DParticleModelParticle *modelParticle = qobject_cast<QQuick3DParticleModelParticle *>(particle);
532 processModelParticle(modelParticle, trailEmits, timeS);
535 QQuick3DParticleModelBlendParticle *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(particle);
537 processModelBlendParticle(mbp, trailEmits, timeS);
543 for (
auto emitter : std::as_const(m_trailEmitters))
544 emitter->clearBursts();
546 m_timeAnimation += m_perfTimer.nsecsElapsed();
547 m_updateAnimation->setDirty(
false);
548 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DParticleUpdate, m_particlesUsed, Q_QUICK3D_PROFILE_GET_ID(
this));
550 Q_TRACE(QSSG_particleUpdate_exit, m_particlesUsed);
554void QQuick3DParticleSystem::processModelParticle(QQuick3DParticleModelParticle *modelParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
556 modelParticle->clearInstanceTable();
558 const int c = modelParticle->maxAmount();
560 for (
int i = 0; i < c; i++) {
561 const auto d = &modelParticle->m_particleData.at(i);
563 const float particleTimeEnd = d->startTime + d->lifetime;
565 if (timeS < d->startTime || timeS > particleTimeEnd) {
566 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
567 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
568 for (
auto trailEmit : std::as_const(trailEmits))
569 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
575 QQuick3DParticleDataCurrent currentData;
576 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
577 for (
auto trailEmit : std::as_const(trailEmits))
578 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
582 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
585 processParticleCommon(currentData, d, particleTimeS);
588 if (modelParticle->m_alignMode != QQuick3DParticle::AlignNone)
589 processParticleAlignment(currentData, modelParticle, d);
592 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
595 currentData.scale = modelParticle->m_initialScale * (d->endSize * timeChange + d->startSize * (1.0f - timeChange));
598 const float particleTimeLeftS = d->lifetime - particleTimeS;
599 processParticleFadeInOut(currentData, modelParticle, particleTimeS, particleTimeLeftS);
602 for (
auto affector : std::as_const(m_affectors)) {
604 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(modelParticle)))
605 affector->affectParticle(*d, ¤tData, particleTimeS);
609 for (
auto trailEmit : std::as_const(trailEmits))
610 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
612 const QColor color(currentData.color.r, currentData.color.g, currentData.color.b, currentData.color.a);
614 modelParticle->addInstance(currentData.position, currentData.scale, currentData.rotation, color, timeChange);
616 modelParticle->commitInstance();
621 return (b - a) * f + a;
624void QQuick3DParticleSystem::processModelBlendParticle(QQuick3DParticleModelBlendParticle *particle,
const QVector<TrailEmits> &trailEmits,
float timeS)
626 const int c = particle->maxAmount();
628 for (
int i = 0; i < c; i++) {
629 const auto d = &particle->m_particleData.at(i);
631 const float particleTimeEnd = d->startTime + d->lifetime;
633 if (timeS < d->startTime || timeS > particleTimeEnd) {
634 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
635 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
636 for (
auto trailEmit : std::as_const(trailEmits))
637 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
644 QVector4D color(
float(d->startColor.r)/ 255.0f,
645 float(d->startColor.g)/ 255.0f,
646 float(d->startColor.b)/ 255.0f,
647 float(d->startColor.a)/ 255.0f);
648 if (d->startTime > 0.0f && timeS > particleTimeEnd
649 && (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
650 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)) {
653 pos = particle->particleEndPosition(i);
654 rot = particle->particleEndRotation(i);
655 if (particle->fadeOutEffect() == QQuick3DParticle::FadeOpacity)
657 }
else if (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Explode ||
658 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer) {
661 pos = particle->particleCenter(i);
662 if (particle->fadeInEffect() == QQuick3DParticle::FadeOpacity)
665 particle->setParticleData(i, pos, rot, color, size, age);
669 QQuick3DParticleDataCurrent currentData;
670 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
671 for (
auto trailEmit : std::as_const(trailEmits))
672 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
676 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
679 processParticleCommon(currentData, d, particleTimeS);
682 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
685 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
686 currentData.scale = QVector3D(scale, scale, scale);
689 const float particleTimeLeftS = d->lifetime - particleTimeS;
690 processParticleFadeInOut(currentData, particle, particleTimeS, particleTimeLeftS);
693 for (
auto affector : std::as_const(m_affectors)) {
695 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(particle)))
696 affector->affectParticle(*d, ¤tData, particleTimeS);
700 for (
auto trailEmit : std::as_const(trailEmits))
701 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
704 const QVector4D color(
float(currentData.color.r) / 255.0f,
705 float(currentData.color.g) / 255.0f,
706 float(currentData.color.b) / 255.0f,
707 float(currentData.color.a) / 255.0f);
708 float endTimeS = particle->endTime() * 0.001f;
709 if ((particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
710 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)
711 && particleTimeLeftS < endTimeS) {
712 QVector3D endPosition = particle->particleEndPosition(i);
713 QVector3D endRotation = particle->particleEndRotation(i);
714 float factor = 1.0f - particleTimeLeftS / endTimeS;
715 currentData.position = mix(currentData.position, endPosition, factor);
716 currentData.rotation = mix(currentData.rotation, endRotation, factor);
718 particle->setParticleData(i, currentData.position, currentData.rotation,
719 color, currentData.scale.x(), timeChange);
721 particle->commitParticles();
724void QQuick3DParticleSystem::processSpriteParticle(QQuick3DParticleSpriteParticle *spriteParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
726 const int c = spriteParticle->maxAmount();
728 for (
int i = 0; i < c; i++) {
729 const auto d = &spriteParticle->m_particleData.at(i);
731 const float particleTimeEnd = d->startTime + d->lifetime;
732 auto &particleData = spriteParticle->m_spriteParticleData[i];
733 if (timeS < d->startTime || timeS > particleTimeEnd) {
734 if (timeS > particleTimeEnd && particleData.age > 0.0f) {
735 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
736 for (
auto trailEmit : std::as_const(trailEmits))
737 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
738 auto *lineParticle = qobject_cast<QQuick3DParticleLineParticle *>(spriteParticle);
740 lineParticle->saveLineSegment(i, timeS);
743 spriteParticle->resetParticleData(i);
747 QQuick3DParticleDataCurrent currentData;
748 if (timeS >= d->startTime && timeS < particleTimeEnd && particleData.age == 0.0f) {
749 for (
auto trailEmit : std::as_const(trailEmits))
750 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
754 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
757 processParticleCommon(currentData, d, particleTimeS);
760 if (!spriteParticle->m_billboard && spriteParticle->m_alignMode != QQuick3DParticle::AlignNone)
761 processParticleAlignment(currentData, spriteParticle, d);
764 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
767 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
768 currentData.scale = QVector3D(scale, scale, scale);
771 const float particleTimeLeftS = d->lifetime - particleTimeS;
772 processParticleFadeInOut(currentData, spriteParticle, particleTimeS, particleTimeLeftS);
774 float animationFrame = 0.0f;
775 if (
auto sequence = spriteParticle->m_spriteSequence) {
778 const bool isSingleFrame = (sequence->animationDirection() == QQuick3DParticleSpriteSequence::SingleFrame);
779 float startFrame = sequence->firstFrame(d->index, isSingleFrame);
780 if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Normal) {
781 animationFrame = fmodf(startFrame + particleTimeS / d->animationTime, 1.0f);
782 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Reverse) {
783 animationFrame = fmodf(startFrame + 0.9999f - fmodf(particleTimeS / d->animationTime, 1.0f), 1.0f);
784 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Alternate) {
785 animationFrame = startFrame + particleTimeS / d->animationTime;
786 animationFrame = fabsf(fmodf(1.0f + animationFrame, 2.0f) - 1.0f);
787 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::AlternateReverse) {
788 animationFrame = fmodf(startFrame + 0.9999f, 1.0f) - particleTimeS / d->animationTime;
789 animationFrame = fabsf(fmodf(fabsf(1.0f + animationFrame), 2.0f) - 1.0f);
792 animationFrame = startFrame;
794 animationFrame = std::clamp(animationFrame, 0.0f, 0.9999f);
798 for (
auto affector : std::as_const(m_affectors)) {
800 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(spriteParticle)))
801 affector->affectParticle(*d, ¤tData, particleTimeS);
805 for (
auto trailEmit : std::as_const(trailEmits))
806 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
810 const QVector4D color(
float(currentData.color.r) / 255.0f,
811 float(currentData.color.g) / 255.0f,
812 float(currentData.color.b) / 255.0f,
813 float(currentData.color.a) / 255.0f);
814 const QVector3D offset(spriteParticle->offsetX(), spriteParticle->offsetY(), 0);
815 spriteParticle->setParticleData(i, currentData.position + (offset * currentData.scale.x()),
816 currentData.rotation, color, currentData.scale.x(), timeChange,
819 spriteParticle->commitParticles(timeS);
822void QQuick3DParticleSystem::processParticleCommon(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticleData *d,
float particleTimeS)
826 currentData.position = d->startPosition;
829 currentData.color = d->startColor;
832 currentData.position += d->startVelocity * particleTimeS;
835 constexpr float step = 360.0f / 127.0f;
836 currentData.rotation = QVector3D(
837 d->startRotation.x * step + abs(d->startRotationVelocity.x) * d->startRotationVelocity.x * particleTimeS,
838 d->startRotation.y * step + abs(d->startRotationVelocity.y) * d->startRotationVelocity.y * particleTimeS,
839 d->startRotation.z * step + abs(d->startRotationVelocity.z) * d->startRotationVelocity.z * particleTimeS);
842void QQuick3DParticleSystem::processParticleFadeInOut(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
float particleTimeS,
float particleTimeLeftS)
844 const float fadeInS = particle->m_fadeInDuration / 1000.0f;
845 const float fadeOutS = particle->m_fadeOutDuration / 1000.0f;
846 if (particleTimeS < fadeInS) {
848 const float fadeIn = particleTimeS / fadeInS;
849 if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeOpacity)
850 currentData.color.a *= fadeIn;
851 else if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeScale)
852 currentData.scale *= fadeIn;
854 if (particleTimeLeftS < fadeOutS) {
856 const float fadeOut = particleTimeLeftS / fadeOutS;
857 if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeOpacity)
858 currentData.color.a *= fadeOut;
859 else if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeScale)
860 currentData.scale *= fadeOut;
864void QQuick3DParticleSystem::processParticleAlignment(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
const QQuick3DParticleData *d)
866 if (particle->m_alignMode == QQuick3DParticle::AlignTowardsTarget) {
867 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(particle->alignTargetPosition(), currentData.position);
868 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
869 }
else if (particle->m_alignMode == QQuick3DParticle::AlignTowardsStartVelocity) {
870 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(d->startVelocity, QVector3D());
871 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
875bool QQuick3DParticleSystem::isGloballyDisabled()
877 static const bool disabled = qEnvironmentVariableIntValue(
"QT_QUICK3D_DISABLE_PARTICLE_SYSTEMS");
881bool QQuick3DParticleSystem::isEditorModeOn()
883 static const bool editorMode = qEnvironmentVariableIntValue(
"QT_QUICK3D_EDITOR_PARTICLE_SYSTEMS");
887void QQuick3DParticleSystem::updateLoggingData()
892 if (m_loggingData->m_particlesMax != m_particlesMax) {
893 m_loggingData->m_particlesMax = m_particlesMax;
894 Q_EMIT m_loggingData->particlesMaxChanged();
896 if (m_loggingData->m_particlesUsed != m_particlesUsed) {
897 m_loggingData->m_particlesUsed = m_particlesUsed;
898 Q_EMIT m_loggingData->particlesUsedChanged();
900 if (m_loggingData->m_updates != m_updates) {
901 m_loggingData->m_updates = m_updates;
902 Q_EMIT m_loggingData->updatesChanged();
905 m_loggingData->updateTimes(m_timeAnimation);
907 Q_EMIT loggingDataChanged();
908 resetLoggingVariables();
911void QQuick3DParticleSystem::resetLoggingVariables()
919QPRand *QQuick3DParticleSystem::rand()
924void QQuick3DParticleSystem::doSeedRandomization()
927 setSeed(QRandomGenerator::global()->bounded(1 + (INT32_MAX - 1)));
930bool QQuick3DParticleSystem::isShared(
const QQuick3DParticle *particle)
const
933 for (
auto emitter : std::as_const(m_emitters)) {
934 count += emitter->particle() == particle;
938 for (
auto emitter : std::as_const(m_trailEmitters)) {
939 count += emitter->particle() == particle;
Q_TRACE_POINT(qtcore, QCoreApplication_postEvent_exit)
Q_TRACE_POINT(qtquick3d, QSSG_particleUpdate_exit, int particleCount)
static QVector3D mix(const QVector3D &a, const QVector3D &b, float f)