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);
85 connect(
this, &QQuick3DNode::layersChanged,
this, [
this]() {
86 for (
auto *particle : std::as_const(m_particles))
87 particle->updateNodeLayers();
91QQuick3DParticleSystem::~QQuick3DParticleSystem()
94 m_updateAnimation->stop();
96 for (
auto &connection : std::exchange(m_connections, {}))
97 QObject::disconnect(connection);
99 const auto particles = std::exchange(m_particles, {});
100 const auto emitters = std::exchange(m_emitters, {});
101 const auto trailEmitters = std::exchange(m_trailEmitters, {});
102 const auto affectors = std::exchange(m_affectors, {});
103 for (
auto *particle : particles)
104 particle->setSystem(
nullptr);
105 for (
auto *emitter : emitters)
106 emitter->setSystem(
nullptr);
107 for (
auto *emitter : trailEmitters)
108 emitter->setSystem(
nullptr);
109 for (
auto *affector : affectors)
110 affector->setSystem(
nullptr);
114
115
116
117
118
119
120
121
122
123
124bool QQuick3DParticleSystem::isRunning()
const
130
131
132
133
134
135
136
137
138bool QQuick3DParticleSystem::isPaused()
const
144
145
146
147
148
149
150
151
152
153int QQuick3DParticleSystem::startTime()
const
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179int QQuick3DParticleSystem::time()
const
185
186
187
188
189
190
191
192
193
194
195
196
197bool QQuick3DParticleSystem::useRandomSeed()
const
199 return m_useRandomSeed;
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217int QQuick3DParticleSystem::seed()
const
223
224
225
226
227
228
229
230
231
232
233bool QQuick3DParticleSystem::logging()
const
239
240
241
242
243
244
245
246
247
248
249
250QQuick3DParticleSystemLogging *QQuick3DParticleSystem::loggingData()
const
252 return m_loggingData;
256
257
258
259
260
261
262
263
264void QQuick3DParticleSystem::reset()
266 for (
auto emitter : std::as_const(m_emitters))
268 for (
auto emitter : std::as_const(m_trailEmitters))
270 for (
auto particle : std::as_const(m_particles))
272 m_particleIdIndex = 0;
276
277
278
279int QQuick3DParticleSystem::currentTime()
const
281 return m_currentTime;
284void QQuick3DParticleSystem::setRunning(
bool running)
286 if (m_running != running) {
288 Q_EMIT runningChanged();
294 if (m_componentComplete && !m_running && m_useRandomSeed)
295 doSeedRandomization();
297 (m_running && !isEditorModeOn()) ? m_animation->start() : m_animation->stop();
301void QQuick3DParticleSystem::setPaused(
bool paused)
303 if (m_paused != paused) {
305 if (m_animation->state() != QAbstractAnimation::Stopped)
306 m_paused ? m_animation->pause() : m_animation->resume();
307 Q_EMIT pausedChanged();
311void QQuick3DParticleSystem::setStartTime(
int startTime)
313 if (m_startTime == startTime)
316 m_startTime = startTime;
317 m_updateAnimation->setDirty(
true);
318 Q_EMIT startTimeChanged();
321void QQuick3DParticleSystem::setTime(
int time)
328 m_updateAnimation->setDirty(
true);
330 Q_EMIT timeChanged();
333void QQuick3DParticleSystem::setUseRandomSeed(
bool randomize)
335 if (m_useRandomSeed == randomize)
338 m_useRandomSeed = randomize;
342 doSeedRandomization();
343 m_rand.setDeterministic(!m_useRandomSeed);
344 Q_EMIT useRandomSeedChanged();
347void QQuick3DParticleSystem::setSeed(
int seed)
354 Q_EMIT seedChanged();
357void QQuick3DParticleSystem::setLogging(
bool logging)
359 if (m_logging == logging)
364 resetLoggingVariables();
365 m_loggingData->resetData();
368 m_loggingTimer.start();
370 m_loggingTimer.stop();
372 Q_EMIT loggingChanged();
376
377
378
379void QQuick3DParticleSystem::setEditorTime(
int time)
381 if (m_editorTime == time)
386 m_updateAnimation->setDirty(
true);
389void QQuick3DParticleSystem::componentComplete()
391 QQuick3DNode::componentComplete();
392 m_componentComplete =
true;
393 m_updateAnimation->start();
395 connect(&m_loggingTimer, &QTimer::timeout,
this, &QQuick3DParticleSystem::updateLoggingData);
396 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
399 doSeedRandomization();
407 Q_EMIT timeChanged();
410 if (m_animation->state() == QAbstractAnimation::Running)
412 if (m_running && !isEditorModeOn())
413 m_animation->start();
415 m_animation->pause();
417 m_initialized =
true;
420void QQuick3DParticleSystem::refresh()
425 if (!m_running || m_paused || isEditorModeOn())
426 m_animation->setCurrentTime(isEditorModeOn() ? m_editorTime : m_time);
429void QQuick3DParticleSystem::markDirty()
432 m_updateAnimation->setDirty(
true);
435int QQuick3DParticleSystem::particleCount()
const
438 for (
auto particle : std::as_const(m_particles))
439 pCount += particle->maxAmount();
443void QQuick3DParticleSystem::registerParticle(QQuick3DParticle *particle)
445 m_particles << particle;
448void QQuick3DParticleSystem::unRegisterParticle(QQuick3DParticle *particle)
450 m_particles.removeAll(particle);
453void QQuick3DParticleSystem::registerParticleEmitter(QQuick3DParticleEmitter *e)
455 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
457 m_trailEmitters << te;
462void QQuick3DParticleSystem::unRegisterParticleEmitter(QQuick3DParticleEmitter *e)
464 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
466 m_trailEmitters.removeAll(te);
468 m_emitters.removeAll(e);
471void QQuick3DParticleSystem::registerParticleAffector(QQuick3DParticleAffector *a)
474 m_connections.insert(a, connect(a, &QQuick3DParticleAffector::update,
this, &QQuick3DParticleSystem::markDirty));
477void QQuick3DParticleSystem::unRegisterParticleAffector(QQuick3DParticleAffector *a)
479 QObject::disconnect(m_connections.take(a));
480 m_affectors.removeAll(a);
483void QQuick3DParticleSystem::updateCurrentTime(
int currentTime)
485 if (!m_initialized || isGloballyDisabled() || (isEditorModeOn() && !visible()))
488 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DParticleUpdate);
490 Q_TRACE(QSSG_particleUpdate_entry);
492 m_currentTime = currentTime;
493 const float timeS =
float(m_currentTime / 1000.0f);
502 for (
auto emitter : std::as_const(m_emitters))
503 emitter->emitParticles();
506 for (
auto affector : std::as_const(m_affectors)) {
507 if (affector->m_enabled)
508 affector->prepareToAffect();
512 for (
auto particle : std::as_const(m_particles)) {
515 QVector<TrailEmits> trailEmits;
516 for (
auto emitter : std::as_const(m_trailEmitters)) {
517 if (emitter->follow() == particle) {
518 int emitAmount = emitter->getEmitAmount();
519 if (emitAmount > 0 || emitter->hasBursts()) {
522 e.amount = emitAmount;
528 m_particlesMax += particle->maxAmount();
530 QQuick3DParticleSpriteParticle *spriteParticle = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
531 if (spriteParticle) {
532 processSpriteParticle(spriteParticle, trailEmits, timeS);
535 QQuick3DParticleModelParticle *modelParticle = qobject_cast<QQuick3DParticleModelParticle *>(particle);
537 processModelParticle(modelParticle, trailEmits, timeS);
540 QQuick3DParticleModelBlendParticle *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(particle);
542 processModelBlendParticle(mbp, trailEmits, timeS);
548 for (
auto emitter : std::as_const(m_trailEmitters))
549 emitter->clearBursts();
551 m_timeAnimation += m_perfTimer.nsecsElapsed();
552 m_updateAnimation->setDirty(
false);
553 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DParticleUpdate, m_particlesUsed, Q_QUICK3D_PROFILE_GET_ID(
this));
555 Q_TRACE(QSSG_particleUpdate_exit, m_particlesUsed);
559void QQuick3DParticleSystem::processModelParticle(QQuick3DParticleModelParticle *modelParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
561 modelParticle->clearInstanceTable();
563 const int c = modelParticle->maxAmount();
565 for (
int i = 0; i < c; i++) {
566 const auto d = &modelParticle->m_particleData.at(i);
568 const float particleTimeEnd = d->startTime + d->lifetime;
570 if (timeS < d->startTime || timeS > particleTimeEnd) {
571 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
572 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
573 for (
auto trailEmit : std::as_const(trailEmits))
574 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
580 QQuick3DParticleDataCurrent currentData;
581 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
582 for (
auto trailEmit : std::as_const(trailEmits))
583 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
587 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
590 processParticleCommon(currentData, d, particleTimeS);
593 if (modelParticle->m_alignMode != QQuick3DParticle::AlignNone)
594 processParticleAlignment(currentData, modelParticle, d);
597 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
600 currentData.scale = modelParticle->m_initialScale * (d->endSize * timeChange + d->startSize * (1.0f - timeChange));
603 const float particleTimeLeftS = d->lifetime - particleTimeS;
604 processParticleFadeInOut(currentData, modelParticle, particleTimeS, particleTimeLeftS);
607 for (
auto affector : std::as_const(m_affectors)) {
609 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(modelParticle)))
610 affector->affectParticle(*d, ¤tData, particleTimeS);
614 for (
auto trailEmit : std::as_const(trailEmits))
615 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
617 const QColor color(currentData.color.r, currentData.color.g, currentData.color.b, currentData.color.a);
619 modelParticle->addInstance(currentData.position, currentData.scale, currentData.rotation, color, timeChange);
621 modelParticle->commitInstance();
626 return (b - a) * f + a;
629void QQuick3DParticleSystem::processModelBlendParticle(QQuick3DParticleModelBlendParticle *particle,
const QVector<TrailEmits> &trailEmits,
float timeS)
631 const int c = particle->maxAmount();
633 for (
int i = 0; i < c; i++) {
634 const auto d = &particle->m_particleData.at(i);
636 const float particleTimeEnd = d->startTime + d->lifetime;
638 if (timeS < d->startTime || timeS > particleTimeEnd) {
639 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
640 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
641 for (
auto trailEmit : std::as_const(trailEmits))
642 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
649 QVector4D color(
float(d->startColor.r)/ 255.0f,
650 float(d->startColor.g)/ 255.0f,
651 float(d->startColor.b)/ 255.0f,
652 float(d->startColor.a)/ 255.0f);
653 if (d->startTime > 0.0f && timeS > particleTimeEnd
654 && (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
655 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)) {
658 pos = particle->particleEndPosition(i);
659 rot = particle->particleEndRotation(i);
660 if (particle->fadeOutEffect() == QQuick3DParticle::FadeOpacity)
662 }
else if (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Explode ||
663 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer) {
666 pos = particle->particleCenter(i);
667 if (particle->fadeInEffect() == QQuick3DParticle::FadeOpacity)
670 particle->setParticleData(i, pos, rot, color, size, age);
674 QQuick3DParticleDataCurrent currentData;
675 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
676 for (
auto trailEmit : std::as_const(trailEmits))
677 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
681 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
684 processParticleCommon(currentData, d, particleTimeS);
687 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
690 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
691 currentData.scale = QVector3D(scale, scale, scale);
694 const float particleTimeLeftS = d->lifetime - particleTimeS;
695 processParticleFadeInOut(currentData, particle, particleTimeS, particleTimeLeftS);
698 for (
auto affector : std::as_const(m_affectors)) {
700 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(particle)))
701 affector->affectParticle(*d, ¤tData, particleTimeS);
705 for (
auto trailEmit : std::as_const(trailEmits))
706 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
709 const QVector4D color(
float(currentData.color.r) / 255.0f,
710 float(currentData.color.g) / 255.0f,
711 float(currentData.color.b) / 255.0f,
712 float(currentData.color.a) / 255.0f);
713 float endTimeS = particle->endTime() * 0.001f;
714 if ((particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
715 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)
716 && particleTimeLeftS < endTimeS) {
717 QVector3D endPosition = particle->particleEndPosition(i);
718 QVector3D endRotation = particle->particleEndRotation(i);
719 float factor = 1.0f - particleTimeLeftS / endTimeS;
720 currentData.position = mix(currentData.position, endPosition, factor);
721 currentData.rotation = mix(currentData.rotation, endRotation, factor);
723 particle->setParticleData(i, currentData.position, currentData.rotation,
724 color, currentData.scale.x(), timeChange);
726 particle->commitParticles();
729void QQuick3DParticleSystem::processSpriteParticle(QQuick3DParticleSpriteParticle *spriteParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
731 const int c = spriteParticle->maxAmount();
733 for (
int i = 0; i < c; i++) {
734 const auto d = &spriteParticle->m_particleData.at(i);
736 const float particleTimeEnd = d->startTime + d->lifetime;
737 auto &particleData = spriteParticle->m_spriteParticleData[i];
738 if (timeS < d->startTime || timeS > particleTimeEnd) {
739 if (timeS > particleTimeEnd && particleData.age > 0.0f) {
740 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
741 for (
auto trailEmit : std::as_const(trailEmits))
742 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
743 auto *lineParticle = qobject_cast<QQuick3DParticleLineParticle *>(spriteParticle);
745 lineParticle->saveLineSegment(i, timeS);
748 spriteParticle->resetParticleData(i);
752 QQuick3DParticleDataCurrent currentData;
753 if (timeS >= d->startTime && timeS < particleTimeEnd && particleData.age == 0.0f) {
754 for (
auto trailEmit : std::as_const(trailEmits))
755 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
759 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
762 processParticleCommon(currentData, d, particleTimeS);
765 if (!spriteParticle->m_billboard && spriteParticle->m_alignMode != QQuick3DParticle::AlignNone)
766 processParticleAlignment(currentData, spriteParticle, d);
769 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
772 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
773 currentData.scale = QVector3D(scale, scale, scale);
776 const float particleTimeLeftS = d->lifetime - particleTimeS;
777 processParticleFadeInOut(currentData, spriteParticle, particleTimeS, particleTimeLeftS);
779 float animationFrame = 0.0f;
780 if (
auto sequence = spriteParticle->m_spriteSequence) {
783 const bool isSingleFrame = (sequence->animationDirection() == QQuick3DParticleSpriteSequence::SingleFrame);
784 float startFrame = sequence->firstFrame(d->index, isSingleFrame);
785 if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Normal) {
786 animationFrame = fmodf(startFrame + particleTimeS / d->animationTime, 1.0f);
787 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Reverse) {
788 animationFrame = fmodf(startFrame + 0.9999f - fmodf(particleTimeS / d->animationTime, 1.0f), 1.0f);
789 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Alternate) {
790 animationFrame = startFrame + particleTimeS / d->animationTime;
791 animationFrame = fabsf(fmodf(1.0f + animationFrame, 2.0f) - 1.0f);
792 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::AlternateReverse) {
793 animationFrame = fmodf(startFrame + 0.9999f, 1.0f) - particleTimeS / d->animationTime;
794 animationFrame = fabsf(fmodf(fabsf(1.0f + animationFrame), 2.0f) - 1.0f);
797 animationFrame = startFrame;
799 animationFrame = std::clamp(animationFrame, 0.0f, 0.9999f);
803 for (
auto affector : std::as_const(m_affectors)) {
805 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(spriteParticle)))
806 affector->affectParticle(*d, ¤tData, particleTimeS);
810 for (
auto trailEmit : std::as_const(trailEmits))
811 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
815 const QVector4D color(
float(currentData.color.r) / 255.0f,
816 float(currentData.color.g) / 255.0f,
817 float(currentData.color.b) / 255.0f,
818 float(currentData.color.a) / 255.0f);
819 const QVector3D offset(spriteParticle->offsetX(), spriteParticle->offsetY(), 0);
820 spriteParticle->setParticleData(i, currentData.position + (offset * currentData.scale.x()),
821 currentData.rotation, color, currentData.scale.x(), timeChange,
824 spriteParticle->commitParticles(timeS);
827void QQuick3DParticleSystem::processParticleCommon(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticleData *d,
float particleTimeS)
831 currentData.position = d->startPosition;
834 currentData.color = d->startColor;
837 currentData.position += d->startVelocity * particleTimeS;
840 constexpr float step = 360.0f / 127.0f;
841 currentData.rotation = QVector3D(
842 d->startRotation.x * step + abs(d->startRotationVelocity.x) * d->startRotationVelocity.x * particleTimeS,
843 d->startRotation.y * step + abs(d->startRotationVelocity.y) * d->startRotationVelocity.y * particleTimeS,
844 d->startRotation.z * step + abs(d->startRotationVelocity.z) * d->startRotationVelocity.z * particleTimeS);
847void QQuick3DParticleSystem::processParticleFadeInOut(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
float particleTimeS,
float particleTimeLeftS)
849 const float fadeInS = particle->m_fadeInDuration / 1000.0f;
850 const float fadeOutS = particle->m_fadeOutDuration / 1000.0f;
851 if (particleTimeS < fadeInS) {
853 const float fadeIn = particleTimeS / fadeInS;
854 if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeOpacity)
855 currentData.color.a *= fadeIn;
856 else if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeScale)
857 currentData.scale *= fadeIn;
859 if (particleTimeLeftS < fadeOutS) {
861 const float fadeOut = particleTimeLeftS / fadeOutS;
862 if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeOpacity)
863 currentData.color.a *= fadeOut;
864 else if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeScale)
865 currentData.scale *= fadeOut;
869void QQuick3DParticleSystem::processParticleAlignment(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
const QQuick3DParticleData *d)
871 if (particle->m_alignMode == QQuick3DParticle::AlignTowardsTarget) {
872 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(particle->alignTargetPosition(), currentData.position);
873 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
874 }
else if (particle->m_alignMode == QQuick3DParticle::AlignTowardsStartVelocity) {
875 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(d->startVelocity, QVector3D());
876 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
880bool QQuick3DParticleSystem::isGloballyDisabled()
882 static const bool disabled = qEnvironmentVariableIntValue(
"QT_QUICK3D_DISABLE_PARTICLE_SYSTEMS");
886bool QQuick3DParticleSystem::isEditorModeOn()
888 static const bool editorMode = qEnvironmentVariableIntValue(
"QT_QUICK3D_EDITOR_PARTICLE_SYSTEMS");
892void QQuick3DParticleSystem::updateLoggingData()
897 if (m_loggingData->m_particlesMax != m_particlesMax) {
898 m_loggingData->m_particlesMax = m_particlesMax;
899 Q_EMIT m_loggingData->particlesMaxChanged();
901 if (m_loggingData->m_particlesUsed != m_particlesUsed) {
902 m_loggingData->m_particlesUsed = m_particlesUsed;
903 Q_EMIT m_loggingData->particlesUsedChanged();
905 if (m_loggingData->m_updates != m_updates) {
906 m_loggingData->m_updates = m_updates;
907 Q_EMIT m_loggingData->updatesChanged();
910 m_loggingData->updateTimes(m_timeAnimation);
912 Q_EMIT loggingDataChanged();
913 resetLoggingVariables();
916void QQuick3DParticleSystem::resetLoggingVariables()
924QPRand *QQuick3DParticleSystem::rand()
929void QQuick3DParticleSystem::doSeedRandomization()
932 setSeed(QRandomGenerator::global()->bounded(1 + (INT32_MAX - 1)));
935bool QQuick3DParticleSystem::isShared(
const QQuick3DParticle *particle)
const
938 for (
auto emitter : std::as_const(m_emitters)) {
939 count += emitter->particle() == particle;
943 for (
auto emitter : std::as_const(m_trailEmitters)) {
944 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)