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 auto *model = qobject_cast<QQuick3DParticleModelParticle *>(particle);
441 registerParticleModel(model);
444 auto *sprite = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
446 registerParticleSprite(sprite);
449 m_particles << particle;
452void QQuick3DParticleSystem::registerParticleModel(QQuick3DParticleModelParticle *m)
457void QQuick3DParticleSystem::registerParticleSprite(QQuick3DParticleSpriteParticle *m)
462void QQuick3DParticleSystem::unRegisterParticle(QQuick3DParticle *particle)
464 auto *model = qobject_cast<QQuick3DParticleModelParticle *>(particle);
466 m_particles.removeAll(particle);
469 auto *sprite = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
471 m_particles.removeAll(particle);
475 m_particles.removeAll(particle);
478void QQuick3DParticleSystem::registerParticleEmitter(QQuick3DParticleEmitter *e)
480 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
482 m_trailEmitters << te;
487void QQuick3DParticleSystem::unRegisterParticleEmitter(QQuick3DParticleEmitter *e)
489 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
491 m_trailEmitters.removeAll(te);
493 m_emitters.removeAll(e);
496void QQuick3DParticleSystem::registerParticleAffector(QQuick3DParticleAffector *a)
499 m_connections.insert(a, connect(a, &QQuick3DParticleAffector::update,
this, &QQuick3DParticleSystem::markDirty));
502void QQuick3DParticleSystem::unRegisterParticleAffector(QQuick3DParticleAffector *a)
504 QObject::disconnect(m_connections[a]);
505 m_connections.remove(a);
506 m_affectors.removeAll(a);
509void QQuick3DParticleSystem::updateCurrentTime(
int currentTime)
511 if (!m_initialized || isGloballyDisabled() || (isEditorModeOn() && !visible()))
514 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DParticleUpdate);
516 Q_TRACE(QSSG_particleUpdate_entry);
518 m_currentTime = currentTime;
519 const float timeS =
float(m_currentTime / 1000.0f);
528 for (
auto emitter : std::as_const(m_emitters))
529 emitter->emitParticles();
532 for (
auto affector : std::as_const(m_affectors)) {
533 if (affector->m_enabled)
534 affector->prepareToAffect();
538 for (
auto particle : std::as_const(m_particles)) {
541 QVector<TrailEmits> trailEmits;
542 for (
auto emitter : std::as_const(m_trailEmitters)) {
543 if (emitter->follow() == particle) {
544 int emitAmount = emitter->getEmitAmount();
545 if (emitAmount > 0 || emitter->hasBursts()) {
548 e.amount = emitAmount;
554 m_particlesMax += particle->maxAmount();
556 QQuick3DParticleSpriteParticle *spriteParticle = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
557 if (spriteParticle) {
558 processSpriteParticle(spriteParticle, trailEmits, timeS);
561 QQuick3DParticleModelParticle *modelParticle = qobject_cast<QQuick3DParticleModelParticle *>(particle);
563 processModelParticle(modelParticle, trailEmits, timeS);
566 QQuick3DParticleModelBlendParticle *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(particle);
568 processModelBlendParticle(mbp, trailEmits, timeS);
574 for (
auto emitter : std::as_const(m_trailEmitters))
575 emitter->clearBursts();
577 m_timeAnimation += m_perfTimer.nsecsElapsed();
578 m_updateAnimation->setDirty(
false);
579 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DParticleUpdate, m_particlesUsed, Q_QUICK3D_PROFILE_GET_ID(
this));
581 Q_TRACE(QSSG_particleUpdate_exit, m_particlesUsed);
585void QQuick3DParticleSystem::processModelParticle(QQuick3DParticleModelParticle *modelParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
587 modelParticle->clearInstanceTable();
589 const int c = modelParticle->maxAmount();
591 for (
int i = 0; i < c; i++) {
592 const auto d = &modelParticle->m_particleData.at(i);
594 const float particleTimeEnd = d->startTime + d->lifetime;
596 if (timeS < d->startTime || timeS > particleTimeEnd) {
597 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
598 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
599 for (
auto trailEmit : std::as_const(trailEmits))
600 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
606 QQuick3DParticleDataCurrent currentData;
607 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
608 for (
auto trailEmit : std::as_const(trailEmits))
609 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
613 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
616 processParticleCommon(currentData, d, particleTimeS);
619 if (modelParticle->m_alignMode != QQuick3DParticle::AlignNone)
620 processParticleAlignment(currentData, modelParticle, d);
623 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
626 currentData.scale = modelParticle->m_initialScale * (d->endSize * timeChange + d->startSize * (1.0f - timeChange));
629 const float particleTimeLeftS = d->lifetime - particleTimeS;
630 processParticleFadeInOut(currentData, modelParticle, particleTimeS, particleTimeLeftS);
633 for (
auto affector : std::as_const(m_affectors)) {
635 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(modelParticle)))
636 affector->affectParticle(*d, ¤tData, particleTimeS);
640 for (
auto trailEmit : std::as_const(trailEmits))
641 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
643 const QColor color(currentData.color.r, currentData.color.g, currentData.color.b, currentData.color.a);
645 modelParticle->addInstance(currentData.position, currentData.scale, currentData.rotation, color, timeChange);
647 modelParticle->commitInstance();
652 return (b - a) * f + a;
655void QQuick3DParticleSystem::processModelBlendParticle(QQuick3DParticleModelBlendParticle *particle,
const QVector<TrailEmits> &trailEmits,
float timeS)
657 const int c = particle->maxAmount();
659 for (
int i = 0; i < c; i++) {
660 const auto d = &particle->m_particleData.at(i);
662 const float particleTimeEnd = d->startTime + d->lifetime;
664 if (timeS < d->startTime || timeS > particleTimeEnd) {
665 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
666 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
667 for (
auto trailEmit : std::as_const(trailEmits))
668 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
675 QVector4D color(
float(d->startColor.r)/ 255.0f,
676 float(d->startColor.g)/ 255.0f,
677 float(d->startColor.b)/ 255.0f,
678 float(d->startColor.a)/ 255.0f);
679 if (d->startTime > 0.0f && timeS > particleTimeEnd
680 && (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
681 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)) {
684 pos = particle->particleEndPosition(i);
685 rot = particle->particleEndRotation(i);
686 if (particle->fadeOutEffect() == QQuick3DParticle::FadeOpacity)
688 }
else if (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Explode ||
689 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer) {
692 pos = particle->particleCenter(i);
693 if (particle->fadeInEffect() == QQuick3DParticle::FadeOpacity)
696 particle->setParticleData(i, pos, rot, color, size, age);
700 QQuick3DParticleDataCurrent currentData;
701 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
702 for (
auto trailEmit : std::as_const(trailEmits))
703 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
707 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
710 processParticleCommon(currentData, d, particleTimeS);
713 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
716 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
717 currentData.scale = QVector3D(scale, scale, scale);
720 const float particleTimeLeftS = d->lifetime - particleTimeS;
721 processParticleFadeInOut(currentData, particle, particleTimeS, particleTimeLeftS);
724 for (
auto affector : std::as_const(m_affectors)) {
726 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(particle)))
727 affector->affectParticle(*d, ¤tData, particleTimeS);
731 for (
auto trailEmit : std::as_const(trailEmits))
732 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
735 const QVector4D color(
float(currentData.color.r) / 255.0f,
736 float(currentData.color.g) / 255.0f,
737 float(currentData.color.b) / 255.0f,
738 float(currentData.color.a) / 255.0f);
739 float endTimeS = particle->endTime() * 0.001f;
740 if ((particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
741 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)
742 && particleTimeLeftS < endTimeS) {
743 QVector3D endPosition = particle->particleEndPosition(i);
744 QVector3D endRotation = particle->particleEndRotation(i);
745 float factor = 1.0f - particleTimeLeftS / endTimeS;
746 currentData.position = mix(currentData.position, endPosition, factor);
747 currentData.rotation = mix(currentData.rotation, endRotation, factor);
749 particle->setParticleData(i, currentData.position, currentData.rotation,
750 color, currentData.scale.x(), timeChange);
752 particle->commitParticles();
755void QQuick3DParticleSystem::processSpriteParticle(QQuick3DParticleSpriteParticle *spriteParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
757 const int c = spriteParticle->maxAmount();
759 for (
int i = 0; i < c; i++) {
760 const auto d = &spriteParticle->m_particleData.at(i);
762 const float particleTimeEnd = d->startTime + d->lifetime;
763 auto &particleData = spriteParticle->m_spriteParticleData[i];
764 if (timeS < d->startTime || timeS > particleTimeEnd) {
765 if (timeS > particleTimeEnd && particleData.age > 0.0f) {
766 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
767 for (
auto trailEmit : std::as_const(trailEmits))
768 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
769 auto *lineParticle = qobject_cast<QQuick3DParticleLineParticle *>(spriteParticle);
771 lineParticle->saveLineSegment(i, timeS);
774 spriteParticle->resetParticleData(i);
778 QQuick3DParticleDataCurrent currentData;
779 if (timeS >= d->startTime && timeS < particleTimeEnd && particleData.age == 0.0f) {
780 for (
auto trailEmit : std::as_const(trailEmits))
781 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
785 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
788 processParticleCommon(currentData, d, particleTimeS);
791 if (!spriteParticle->m_billboard && spriteParticle->m_alignMode != QQuick3DParticle::AlignNone)
792 processParticleAlignment(currentData, spriteParticle, d);
795 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
798 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
799 currentData.scale = QVector3D(scale, scale, scale);
802 const float particleTimeLeftS = d->lifetime - particleTimeS;
803 processParticleFadeInOut(currentData, spriteParticle, particleTimeS, particleTimeLeftS);
805 float animationFrame = 0.0f;
806 if (
auto sequence = spriteParticle->m_spriteSequence) {
809 const bool isSingleFrame = (sequence->animationDirection() == QQuick3DParticleSpriteSequence::SingleFrame);
810 float startFrame = sequence->firstFrame(d->index, isSingleFrame);
811 if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Normal) {
812 animationFrame = fmodf(startFrame + particleTimeS / d->animationTime, 1.0f);
813 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Reverse) {
814 animationFrame = fmodf(startFrame + 0.9999f - fmodf(particleTimeS / d->animationTime, 1.0f), 1.0f);
815 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Alternate) {
816 animationFrame = startFrame + particleTimeS / d->animationTime;
817 animationFrame = fabsf(fmodf(1.0f + animationFrame, 2.0f) - 1.0f);
818 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::AlternateReverse) {
819 animationFrame = fmodf(startFrame + 0.9999f, 1.0f) - particleTimeS / d->animationTime;
820 animationFrame = fabsf(fmodf(fabsf(1.0f + animationFrame), 2.0f) - 1.0f);
823 animationFrame = startFrame;
825 animationFrame = std::clamp(animationFrame, 0.0f, 0.9999f);
829 for (
auto affector : std::as_const(m_affectors)) {
831 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(spriteParticle)))
832 affector->affectParticle(*d, ¤tData, particleTimeS);
836 for (
auto trailEmit : std::as_const(trailEmits))
837 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
841 const QVector4D color(
float(currentData.color.r) / 255.0f,
842 float(currentData.color.g) / 255.0f,
843 float(currentData.color.b) / 255.0f,
844 float(currentData.color.a) / 255.0f);
845 const QVector3D offset(spriteParticle->offsetX(), spriteParticle->offsetY(), 0);
846 spriteParticle->setParticleData(i, currentData.position + (offset * currentData.scale.x()),
847 currentData.rotation, color, currentData.scale.x(), timeChange,
850 spriteParticle->commitParticles(timeS);
853void QQuick3DParticleSystem::processParticleCommon(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticleData *d,
float particleTimeS)
857 currentData.position = d->startPosition;
860 currentData.color = d->startColor;
863 currentData.position += d->startVelocity * particleTimeS;
866 constexpr float step = 360.0f / 127.0f;
867 currentData.rotation = QVector3D(
868 d->startRotation.x * step + abs(d->startRotationVelocity.x) * d->startRotationVelocity.x * particleTimeS,
869 d->startRotation.y * step + abs(d->startRotationVelocity.y) * d->startRotationVelocity.y * particleTimeS,
870 d->startRotation.z * step + abs(d->startRotationVelocity.z) * d->startRotationVelocity.z * particleTimeS);
873void QQuick3DParticleSystem::processParticleFadeInOut(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
float particleTimeS,
float particleTimeLeftS)
875 const float fadeInS = particle->m_fadeInDuration / 1000.0f;
876 const float fadeOutS = particle->m_fadeOutDuration / 1000.0f;
877 if (particleTimeS < fadeInS) {
879 const float fadeIn = particleTimeS / fadeInS;
880 if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeOpacity)
881 currentData.color.a *= fadeIn;
882 else if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeScale)
883 currentData.scale *= fadeIn;
885 if (particleTimeLeftS < fadeOutS) {
887 const float fadeOut = particleTimeLeftS / fadeOutS;
888 if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeOpacity)
889 currentData.color.a *= fadeOut;
890 else if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeScale)
891 currentData.scale *= fadeOut;
895void QQuick3DParticleSystem::processParticleAlignment(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
const QQuick3DParticleData *d)
897 if (particle->m_alignMode == QQuick3DParticle::AlignTowardsTarget) {
898 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(particle->alignTargetPosition(), currentData.position);
899 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
900 }
else if (particle->m_alignMode == QQuick3DParticle::AlignTowardsStartVelocity) {
901 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(d->startVelocity, QVector3D());
902 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
906bool QQuick3DParticleSystem::isGloballyDisabled()
908 static const bool disabled = qEnvironmentVariableIntValue(
"QT_QUICK3D_DISABLE_PARTICLE_SYSTEMS");
912bool QQuick3DParticleSystem::isEditorModeOn()
914 static const bool editorMode = qEnvironmentVariableIntValue(
"QT_QUICK3D_EDITOR_PARTICLE_SYSTEMS");
918void QQuick3DParticleSystem::updateLoggingData()
923 if (m_loggingData->m_particlesMax != m_particlesMax) {
924 m_loggingData->m_particlesMax = m_particlesMax;
925 Q_EMIT m_loggingData->particlesMaxChanged();
927 if (m_loggingData->m_particlesUsed != m_particlesUsed) {
928 m_loggingData->m_particlesUsed = m_particlesUsed;
929 Q_EMIT m_loggingData->particlesUsedChanged();
931 if (m_loggingData->m_updates != m_updates) {
932 m_loggingData->m_updates = m_updates;
933 Q_EMIT m_loggingData->updatesChanged();
936 m_loggingData->updateTimes(m_timeAnimation);
938 Q_EMIT loggingDataChanged();
939 resetLoggingVariables();
942void QQuick3DParticleSystem::resetLoggingVariables()
950QPRand *QQuick3DParticleSystem::rand()
955void QQuick3DParticleSystem::doSeedRandomization()
958 setSeed(QRandomGenerator::global()->bounded(1 + (INT32_MAX - 1)));
961bool QQuick3DParticleSystem::isShared(
const QQuick3DParticle *particle)
const
964 for (
auto emitter : std::as_const(m_emitters)) {
965 count += emitter->particle() == particle;
969 for (
auto emitter : std::as_const(m_trailEmitters)) {
970 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)