4#include <QtQuick3D/private/qquick3dquaternionutils_p.h>
10#include <private/qqmldelegatemodel_p.h>
15#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
16#include <qtquick3d_tracepoints_p.h>
18#include <QtGui/qquaternion.h>
25
26
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
67QQuick3DParticleSystem::QQuick3DParticleSystem(QQuick3DNode *parent)
68 : QQuick3DNode(parent)
71 , m_initialized(
false)
72 , m_componentComplete(
false)
73 , m_animation(
new QQuick3DParticleSystemAnimation(
this))
74 , m_updateAnimation(
new QQuick3DParticleSystemUpdate(
this))
76 , m_loggingData(
new QQuick3DParticleSystemLogging(
this))
78 connect(m_loggingData, &QQuick3DParticleSystemLogging::loggingIntervalChanged, &m_loggingTimer, [
this]() {
79 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
83QQuick3DParticleSystem::~QQuick3DParticleSystem()
86 m_updateAnimation->stop();
88 for (
const auto &connection : std::as_const(m_connections))
89 QObject::disconnect(connection);
91 const auto particles = m_particles;
92 const auto emitters = m_emitters;
93 const auto trailEmitters = m_trailEmitters;
94 const auto affectors = m_affectors;
95 for (
auto *particle : particles)
96 particle->setSystem(
nullptr);
97 for (
auto *emitter : emitters)
98 emitter->setSystem(
nullptr);
99 for (
auto *emitter : trailEmitters)
100 emitter->setSystem(
nullptr);
101 for (
auto *affector : affectors)
102 affector->setSystem(
nullptr);
106
107
108
109
110
111
112
113
114
115
116bool QQuick3DParticleSystem::isRunning()
const
122
123
124
125
126
127
128
129
130bool QQuick3DParticleSystem::isPaused()
const
136
137
138
139
140
141
142
143
144
145int QQuick3DParticleSystem::startTime()
const
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171int QQuick3DParticleSystem::time()
const
177
178
179
180
181
182
183
184
185
186
187
188
189bool QQuick3DParticleSystem::useRandomSeed()
const
191 return m_useRandomSeed;
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209int QQuick3DParticleSystem::seed()
const
215
216
217
218
219
220
221
222
223
224
225bool QQuick3DParticleSystem::logging()
const
231
232
233
234
235
236
237
238
239
240
241
242QQuick3DParticleSystemLogging *QQuick3DParticleSystem::loggingData()
const
244 return m_loggingData;
248
249
250
251
252
253
254
255
256void QQuick3DParticleSystem::reset()
258 for (
auto emitter : std::as_const(m_emitters))
260 for (
auto emitter : std::as_const(m_trailEmitters))
262 for (
auto particle : std::as_const(m_particles))
264 m_particleIdIndex = 0;
268
269
270
271int QQuick3DParticleSystem::currentTime()
const
273 return m_currentTime;
276void QQuick3DParticleSystem::setRunning(
bool running)
278 if (m_running != running) {
280 Q_EMIT runningChanged();
286 if (m_componentComplete && !m_running && m_useRandomSeed)
287 doSeedRandomization();
289 (m_running && !isEditorModeOn()) ? m_animation->start() : m_animation->stop();
293void QQuick3DParticleSystem::setPaused(
bool paused)
295 if (m_paused != paused) {
297 if (m_animation->state() != QAbstractAnimation::Stopped)
298 m_paused ? m_animation->pause() : m_animation->resume();
299 Q_EMIT pausedChanged();
303void QQuick3DParticleSystem::setStartTime(
int startTime)
305 if (m_startTime == startTime)
308 m_startTime = startTime;
309 m_updateAnimation->setDirty(
true);
310 Q_EMIT startTimeChanged();
313void QQuick3DParticleSystem::setTime(
int time)
320 m_updateAnimation->setDirty(
true);
322 Q_EMIT timeChanged();
325void QQuick3DParticleSystem::setUseRandomSeed(
bool randomize)
327 if (m_useRandomSeed == randomize)
330 m_useRandomSeed = randomize;
334 doSeedRandomization();
335 m_rand.setDeterministic(!m_useRandomSeed);
336 Q_EMIT useRandomSeedChanged();
339void QQuick3DParticleSystem::setSeed(
int seed)
346 Q_EMIT seedChanged();
349void QQuick3DParticleSystem::setLogging(
bool logging)
351 if (m_logging == logging)
356 resetLoggingVariables();
357 m_loggingData->resetData();
360 m_loggingTimer.start();
362 m_loggingTimer.stop();
364 Q_EMIT loggingChanged();
368
369
370
371void QQuick3DParticleSystem::setEditorTime(
int time)
373 if (m_editorTime == time)
378 m_updateAnimation->setDirty(
true);
381void QQuick3DParticleSystem::componentComplete()
383 QQuick3DNode::componentComplete();
384 m_componentComplete =
true;
385 m_updateAnimation->start();
387 connect(&m_loggingTimer, &QTimer::timeout,
this, &QQuick3DParticleSystem::updateLoggingData);
388 m_loggingTimer.setInterval(m_loggingData->m_loggingInterval);
391 doSeedRandomization();
399 Q_EMIT timeChanged();
402 if (m_animation->state() == QAbstractAnimation::Running)
404 if (m_running && !isEditorModeOn())
405 m_animation->start();
407 m_animation->pause();
409 m_initialized =
true;
412void QQuick3DParticleSystem::refresh()
417 if (!m_running || m_paused || isEditorModeOn())
418 m_animation->setCurrentTime(isEditorModeOn() ? m_editorTime : m_time);
421void QQuick3DParticleSystem::markDirty()
424 m_updateAnimation->setDirty(
true);
427int QQuick3DParticleSystem::particleCount()
const
430 for (
auto particle : std::as_const(m_particles))
431 pCount += particle->maxAmount();
435void QQuick3DParticleSystem::registerParticle(QQuick3DParticle *particle)
437 auto *model = qobject_cast<QQuick3DParticleModelParticle *>(particle);
439 registerParticleModel(model);
442 auto *sprite = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
444 registerParticleSprite(sprite);
447 m_particles << particle;
450void QQuick3DParticleSystem::registerParticleModel(QQuick3DParticleModelParticle *m)
455void QQuick3DParticleSystem::registerParticleSprite(QQuick3DParticleSpriteParticle *m)
460void QQuick3DParticleSystem::unRegisterParticle(QQuick3DParticle *particle)
462 auto *model = qobject_cast<QQuick3DParticleModelParticle *>(particle);
464 m_particles.removeAll(particle);
467 auto *sprite = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
469 m_particles.removeAll(particle);
473 m_particles.removeAll(particle);
476void QQuick3DParticleSystem::registerParticleEmitter(QQuick3DParticleEmitter *e)
478 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
480 m_trailEmitters << te;
485void QQuick3DParticleSystem::unRegisterParticleEmitter(QQuick3DParticleEmitter *e)
487 auto te = qobject_cast<QQuick3DParticleTrailEmitter *>(e);
489 m_trailEmitters.removeAll(te);
491 m_emitters.removeAll(e);
494void QQuick3DParticleSystem::registerParticleAffector(QQuick3DParticleAffector *a)
497 m_connections.insert(a, connect(a, &QQuick3DParticleAffector::update,
this, &QQuick3DParticleSystem::markDirty));
500void QQuick3DParticleSystem::unRegisterParticleAffector(QQuick3DParticleAffector *a)
502 QObject::disconnect(m_connections[a]);
503 m_connections.remove(a);
504 m_affectors.removeAll(a);
507void QQuick3DParticleSystem::updateCurrentTime(
int currentTime)
509 if (!m_initialized || isGloballyDisabled() || (isEditorModeOn() && !visible()))
512 Q_QUICK3D_PROFILE_START(QQuick3DProfiler::Quick3DParticleUpdate);
514 Q_TRACE(QSSG_particleUpdate_entry);
516 m_currentTime = currentTime;
517 const float timeS =
float(m_currentTime / 1000.0f);
526 for (
auto emitter : std::as_const(m_emitters))
527 emitter->emitParticles();
530 for (
auto affector : std::as_const(m_affectors)) {
531 if (affector->m_enabled)
532 affector->prepareToAffect();
536 for (
auto particle : std::as_const(m_particles)) {
539 QVector<TrailEmits> trailEmits;
540 for (
auto emitter : std::as_const(m_trailEmitters)) {
541 if (emitter->follow() == particle) {
542 int emitAmount = emitter->getEmitAmount();
543 if (emitAmount > 0 || emitter->hasBursts()) {
546 e.amount = emitAmount;
552 m_particlesMax += particle->maxAmount();
554 QQuick3DParticleSpriteParticle *spriteParticle = qobject_cast<QQuick3DParticleSpriteParticle *>(particle);
555 if (spriteParticle) {
556 processSpriteParticle(spriteParticle, trailEmits, timeS);
559 QQuick3DParticleModelParticle *modelParticle = qobject_cast<QQuick3DParticleModelParticle *>(particle);
561 processModelParticle(modelParticle, trailEmits, timeS);
564 QQuick3DParticleModelBlendParticle *mbp = qobject_cast<QQuick3DParticleModelBlendParticle *>(particle);
566 processModelBlendParticle(mbp, trailEmits, timeS);
572 for (
auto emitter : std::as_const(m_trailEmitters))
573 emitter->clearBursts();
575 m_timeAnimation += m_perfTimer.nsecsElapsed();
576 m_updateAnimation->setDirty(
false);
577 Q_QUICK3D_PROFILE_END_WITH_ID(QQuick3DProfiler::Quick3DParticleUpdate, m_particlesUsed, Q_QUICK3D_PROFILE_GET_ID(
this));
579 Q_TRACE(QSSG_particleUpdate_exit, m_particlesUsed);
583void QQuick3DParticleSystem::processModelParticle(QQuick3DParticleModelParticle *modelParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
585 modelParticle->clearInstanceTable();
587 const int c = modelParticle->maxAmount();
589 for (
int i = 0; i < c; i++) {
590 const auto d = &modelParticle->m_particleData.at(i);
592 const float particleTimeEnd = d->startTime + d->lifetime;
594 if (timeS < d->startTime || timeS > particleTimeEnd) {
595 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
596 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
597 for (
auto trailEmit : std::as_const(trailEmits))
598 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
604 QQuick3DParticleDataCurrent currentData;
605 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
606 for (
auto trailEmit : std::as_const(trailEmits))
607 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
611 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
614 processParticleCommon(currentData, d, particleTimeS);
617 if (modelParticle->m_alignMode != QQuick3DParticle::AlignNone)
618 processParticleAlignment(currentData, modelParticle, d);
621 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
624 currentData.scale = modelParticle->m_initialScale * (d->endSize * timeChange + d->startSize * (1.0f - timeChange));
627 const float particleTimeLeftS = d->lifetime - particleTimeS;
628 processParticleFadeInOut(currentData, modelParticle, particleTimeS, particleTimeLeftS);
631 for (
auto affector : std::as_const(m_affectors)) {
633 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(modelParticle)))
634 affector->affectParticle(*d, ¤tData, particleTimeS);
638 for (
auto trailEmit : std::as_const(trailEmits))
639 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
641 const QColor color(currentData.color.r, currentData.color.g, currentData.color.b, currentData.color.a);
643 modelParticle->addInstance(currentData.position, currentData.scale, currentData.rotation, color, timeChange);
645 modelParticle->commitInstance();
650 return (b - a) * f + a;
653void QQuick3DParticleSystem::processModelBlendParticle(QQuick3DParticleModelBlendParticle *particle,
const QVector<TrailEmits> &trailEmits,
float timeS)
655 const int c = particle->maxAmount();
657 for (
int i = 0; i < c; i++) {
658 const auto d = &particle->m_particleData.at(i);
660 const float particleTimeEnd = d->startTime + d->lifetime;
662 if (timeS < d->startTime || timeS > particleTimeEnd) {
663 if (timeS > particleTimeEnd && d->lifetime > 0.0f) {
664 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
665 for (
auto trailEmit : std::as_const(trailEmits))
666 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
673 QVector4D color(
float(d->startColor.r)/ 255.0f,
674 float(d->startColor.g)/ 255.0f,
675 float(d->startColor.b)/ 255.0f,
676 float(d->startColor.a)/ 255.0f);
677 if (d->startTime > 0.0f && timeS > particleTimeEnd
678 && (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
679 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)) {
682 pos = particle->particleEndPosition(i);
683 rot = particle->particleEndRotation(i);
684 if (particle->fadeOutEffect() == QQuick3DParticle::FadeOpacity)
686 }
else if (particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Explode ||
687 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer) {
690 pos = particle->particleCenter(i);
691 if (particle->fadeInEffect() == QQuick3DParticle::FadeOpacity)
694 particle->setParticleData(i, pos, rot, color, size, age);
698 QQuick3DParticleDataCurrent currentData;
699 if (timeS >= d->startTime && d->lifetime <= 0.0f) {
700 for (
auto trailEmit : std::as_const(trailEmits))
701 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
705 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
708 processParticleCommon(currentData, d, particleTimeS);
711 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
714 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
715 currentData.scale = QVector3D(scale, scale, scale);
718 const float particleTimeLeftS = d->lifetime - particleTimeS;
719 processParticleFadeInOut(currentData, particle, particleTimeS, particleTimeLeftS);
722 for (
auto affector : std::as_const(m_affectors)) {
724 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(particle)))
725 affector->affectParticle(*d, ¤tData, particleTimeS);
729 for (
auto trailEmit : std::as_const(trailEmits))
730 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
733 const QVector4D color(
float(currentData.color.r) / 255.0f,
734 float(currentData.color.g) / 255.0f,
735 float(currentData.color.b) / 255.0f,
736 float(currentData.color.a) / 255.0f);
737 float endTimeS = particle->endTime() * 0.001f;
738 if ((particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Construct ||
739 particle->modelBlendMode() == QQuick3DParticleModelBlendParticle::Transfer)
740 && particleTimeLeftS < endTimeS) {
741 QVector3D endPosition = particle->particleEndPosition(i);
742 QVector3D endRotation = particle->particleEndRotation(i);
743 float factor = 1.0f - particleTimeLeftS / endTimeS;
744 currentData.position = mix(currentData.position, endPosition, factor);
745 currentData.rotation = mix(currentData.rotation, endRotation, factor);
747 particle->setParticleData(i, currentData.position, currentData.rotation,
748 color, currentData.scale.x(), timeChange);
750 particle->commitParticles();
753void QQuick3DParticleSystem::processSpriteParticle(QQuick3DParticleSpriteParticle *spriteParticle,
const QVector<TrailEmits> &trailEmits,
float timeS)
755 const int c = spriteParticle->maxAmount();
757 for (
int i = 0; i < c; i++) {
758 const auto d = &spriteParticle->m_particleData.at(i);
760 const float particleTimeEnd = d->startTime + d->lifetime;
761 auto &particleData = spriteParticle->m_spriteParticleData[i];
762 if (timeS < d->startTime || timeS > particleTimeEnd) {
763 if (timeS > particleTimeEnd && particleData.age > 0.0f) {
764 const auto pos = d->reversed ? d->startPosition : d->startPosition + (d->startVelocity * (particleTimeEnd - d->startTime));
765 for (
auto trailEmit : std::as_const(trailEmits))
766 trailEmit.emitter->emitTrailParticles(pos, 0, QQuick3DParticleDynamicBurst::TriggerEnd, d->surfaceNormal, d->startVelocity.normalized());
767 auto *lineParticle = qobject_cast<QQuick3DParticleLineParticle *>(spriteParticle);
769 lineParticle->saveLineSegment(i, timeS);
772 spriteParticle->resetParticleData(i);
776 QQuick3DParticleDataCurrent currentData;
777 if (timeS >= d->startTime && timeS < particleTimeEnd && particleData.age == 0.0f) {
778 for (
auto trailEmit : std::as_const(trailEmits))
779 trailEmit.emitter->emitTrailParticles(d->startPosition, 0, QQuick3DParticleDynamicBurst::TriggerStart, d->surfaceNormal, d->startVelocity.normalized());
783 const float particleTimeS = d->reversed ? particleTimeEnd - timeS : timeS - d->startTime;
786 processParticleCommon(currentData, d, particleTimeS);
789 if (!spriteParticle->m_billboard && spriteParticle->m_alignMode != QQuick3DParticle::AlignNone)
790 processParticleAlignment(currentData, spriteParticle, d);
793 const float timeChange = std::max(0.0f, std::min(1.0f, particleTimeS / d->lifetime));
796 const float scale = d->endSize * timeChange + d->startSize * (1.0f - timeChange);
797 currentData.scale = QVector3D(scale, scale, scale);
800 const float particleTimeLeftS = d->lifetime - particleTimeS;
801 processParticleFadeInOut(currentData, spriteParticle, particleTimeS, particleTimeLeftS);
803 float animationFrame = 0.0f;
804 if (
auto sequence = spriteParticle->m_spriteSequence) {
807 const bool isSingleFrame = (sequence->animationDirection() == QQuick3DParticleSpriteSequence::SingleFrame);
808 float startFrame = sequence->firstFrame(d->index, isSingleFrame);
809 if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Normal) {
810 animationFrame = fmodf(startFrame + particleTimeS / d->animationTime, 1.0f);
811 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Reverse) {
812 animationFrame = fmodf(startFrame + 0.9999f - fmodf(particleTimeS / d->animationTime, 1.0f), 1.0f);
813 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::Alternate) {
814 animationFrame = startFrame + particleTimeS / d->animationTime;
815 animationFrame = fabsf(fmodf(1.0f + animationFrame, 2.0f) - 1.0f);
816 }
else if (sequence->animationDirection() == QQuick3DParticleSpriteSequence::AlternateReverse) {
817 animationFrame = fmodf(startFrame + 0.9999f, 1.0f) - particleTimeS / d->animationTime;
818 animationFrame = fabsf(fmodf(fabsf(1.0f + animationFrame), 2.0f) - 1.0f);
821 animationFrame = startFrame;
823 animationFrame = std::clamp(animationFrame, 0.0f, 0.9999f);
827 for (
auto affector : std::as_const(m_affectors)) {
829 if (affector->m_enabled && (affector->m_particles.isEmpty() || affector->m_particles.contains(spriteParticle)))
830 affector->affectParticle(*d, ¤tData, particleTimeS);
834 for (
auto trailEmit : std::as_const(trailEmits))
835 trailEmit.emitter->emitTrailParticles(currentData.position, trailEmit.amount, QQuick3DParticleDynamicBurst::TriggerTime, d->surfaceNormal, d->startVelocity.normalized());
839 const QVector4D color(
float(currentData.color.r) / 255.0f,
840 float(currentData.color.g) / 255.0f,
841 float(currentData.color.b) / 255.0f,
842 float(currentData.color.a) / 255.0f);
843 const QVector3D offset(spriteParticle->offsetX(), spriteParticle->offsetY(), 0);
844 spriteParticle->setParticleData(i, currentData.position + (offset * currentData.scale.x()),
845 currentData.rotation, color, currentData.scale.x(), timeChange,
848 spriteParticle->commitParticles(timeS);
851void QQuick3DParticleSystem::processParticleCommon(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticleData *d,
float particleTimeS)
855 currentData.position = d->startPosition;
858 currentData.color = d->startColor;
861 currentData.position += d->startVelocity * particleTimeS;
864 constexpr float step = 360.0f / 127.0f;
865 currentData.rotation = QVector3D(
866 d->startRotation.x * step + abs(d->startRotationVelocity.x) * d->startRotationVelocity.x * particleTimeS,
867 d->startRotation.y * step + abs(d->startRotationVelocity.y) * d->startRotationVelocity.y * particleTimeS,
868 d->startRotation.z * step + abs(d->startRotationVelocity.z) * d->startRotationVelocity.z * particleTimeS);
871void QQuick3DParticleSystem::processParticleFadeInOut(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
float particleTimeS,
float particleTimeLeftS)
873 const float fadeInS = particle->m_fadeInDuration / 1000.0f;
874 const float fadeOutS = particle->m_fadeOutDuration / 1000.0f;
875 if (particleTimeS < fadeInS) {
877 const float fadeIn = particleTimeS / fadeInS;
878 if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeOpacity)
879 currentData.color.a *= fadeIn;
880 else if (particle->m_fadeInEffect == QQuick3DParticleModelParticle::FadeScale)
881 currentData.scale *= fadeIn;
883 if (particleTimeLeftS < fadeOutS) {
885 const float fadeOut = particleTimeLeftS / fadeOutS;
886 if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeOpacity)
887 currentData.color.a *= fadeOut;
888 else if (particle->m_fadeOutEffect == QQuick3DParticleModelParticle::FadeScale)
889 currentData.scale *= fadeOut;
893void QQuick3DParticleSystem::processParticleAlignment(QQuick3DParticleDataCurrent ¤tData,
const QQuick3DParticle *particle,
const QQuick3DParticleData *d)
895 if (particle->m_alignMode == QQuick3DParticle::AlignTowardsTarget) {
896 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(particle->alignTargetPosition(), currentData.position);
897 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
898 }
else if (particle->m_alignMode == QQuick3DParticle::AlignTowardsStartVelocity) {
899 QQuaternion alignQuat = QQuick3DQuaternionUtils::lookAt(d->startVelocity, QVector3D());
900 currentData.rotation = (alignQuat * QQuaternion::fromEulerAngles(currentData.rotation)).toEulerAngles();
904bool QQuick3DParticleSystem::isGloballyDisabled()
906 static const bool disabled = qEnvironmentVariableIntValue(
"QT_QUICK3D_DISABLE_PARTICLE_SYSTEMS");
910bool QQuick3DParticleSystem::isEditorModeOn()
912 static const bool editorMode = qEnvironmentVariableIntValue(
"QT_QUICK3D_EDITOR_PARTICLE_SYSTEMS");
916void QQuick3DParticleSystem::updateLoggingData()
921 if (m_loggingData->m_particlesMax != m_particlesMax) {
922 m_loggingData->m_particlesMax = m_particlesMax;
923 Q_EMIT m_loggingData->particlesMaxChanged();
925 if (m_loggingData->m_particlesUsed != m_particlesUsed) {
926 m_loggingData->m_particlesUsed = m_particlesUsed;
927 Q_EMIT m_loggingData->particlesUsedChanged();
929 if (m_loggingData->m_updates != m_updates) {
930 m_loggingData->m_updates = m_updates;
931 Q_EMIT m_loggingData->updatesChanged();
934 m_loggingData->updateTimes(m_timeAnimation);
936 Q_EMIT loggingDataChanged();
937 resetLoggingVariables();
940void QQuick3DParticleSystem::resetLoggingVariables()
948QPRand *QQuick3DParticleSystem::rand()
953void QQuick3DParticleSystem::doSeedRandomization()
956 setSeed(QRandomGenerator::global()->bounded(1 + (INT32_MAX - 1)));
959bool QQuick3DParticleSystem::isShared(
const QQuick3DParticle *particle)
const
962 for (
auto emitter : std::as_const(m_emitters)) {
963 count += emitter->particle() == particle;
967 for (
auto emitter : std::as_const(m_trailEmitters)) {
968 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)