Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquick3dparticlewander.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
6#include <QtCore/qmath.h>
10
12
13/*!
14 \qmltype Wander3D
15 \inherits Affector3D
16 \inqmlmodule QtQuick3D.Particles3D
17 \brief Applies random wave curves to particles.
18 \since 6.2
19
20 This element applies random wave curves to particles. Curves can combine
21 global values which are the same for all particles and unique values which
22 differ randomly.
23*/
24
25QQuick3DParticleWander::QQuick3DParticleWander(QQuick3DNode *parent)
26 : QQuick3DParticleAffector(parent)
27{
28}
29
30/*!
31 \qmlproperty vector3d Wander3D::globalAmount
32
33 This property defines how long distance each particle moves at the ends of curves.
34 So if the value is for example (100, 10, 0), all particles wander between (100, 10, 0)
35 and (-100, -10, 0).
36
37 The default value is \c (0.0, 0.0, 0.0).
38*/
39const QVector3D &QQuick3DParticleWander::globalAmount() const
40{
41 return m_globalAmount;
42}
43
44/*!
45 \qmlproperty vector3d Wander3D::globalPace
46
47 This property defines the pace (frequency) each particle wanders in curves per second.
48
49 The default value is \c (0.0, 0.0, 0.0).
50*/
51const QVector3D &QQuick3DParticleWander::globalPace() const
52{
53 return m_globalPace;
54}
55
56/*!
57 \qmlproperty vector3d Wander3D::globalPaceStart
58
59 This property defines the starting point for the pace (frequency). The meaningful range
60 is between 0 .. 2 * PI. For example, to animate the x-coordinate of the pace start:
61
62 \qml
63 PropertyAnimation on globalPaceStart {
64 loops: Animation.Infinite
65 duration: 2000
66 from: Qt.vector3d(0, 0, 0)
67 to: Qt.vector3d(Math.PI * 2, 0, 0)
68 }
69 \endqml
70
71 The default value is \c (0.0, 0.0, 0.0).
72*/
73const QVector3D &QQuick3DParticleWander::globalPaceStart() const
74{
75 return m_globalPaceStart;
76}
77
78/*!
79 \qmlproperty vector3d Wander3D::uniqueAmount
80
81 This property defines how long distance each particle moves at the ends of curves at maximum.
82
83 The default value is \c (0.0, 0.0, 0.0).
84*/
85const QVector3D &QQuick3DParticleWander::uniqueAmount() const
86{
87 return m_uniqueAmount;
88}
89
90/*!
91 \qmlproperty vector3d Wander3D::uniquePace
92
93 This property defines the unique pace (frequency) each particle wanders in curves per second.
94
95 The default value is \c (0.0, 0.0, 0.0).
96*/
97const QVector3D &QQuick3DParticleWander::uniquePace() const
98{
99 return m_uniquePace;
100}
101
102/*!
103 \qmlproperty real Wander3D::uniqueAmountVariation
104
105 This property defines variation for \l uniqueAmount between 0.0 and 1.0.
106 When the amount variation is 0.0, every particle reaches maximum amount. When it's 0.5,
107 every particle reaches between 0.5 - 1.5 of the amount.
108 For example if \l uniqueAmount is (100, 50, 20) and \l uniqueAmountVariation is 0.1,
109 the particles maximum wave distances are something random between (110, 55, 22)
110 and (90, 45, 18).
111
112 The default value is \c 0.0.
113*/
114float QQuick3DParticleWander::uniqueAmountVariation() const
115{
116 return m_uniqueAmountVariation;
117}
118
119/*!
120 \qmlproperty real Wander3D::uniquePaceVariation
121
122 This property defines the unique pace (frequency) variation for each particle
123 between 0.0 and 1.0. When the variation is 0.0, every particle wander at the same
124 frequency. For example if \l uniquePace is (1.0, 2.0, 4.0) and \l uniquePaceVariation
125 is 0.5, the particles wave paces are something random between (2.0, 4.0, 8.0)
126 and (0.5, 1.0, 2.0).
127
128 The default value is \c 0.0.
129*/
130float QQuick3DParticleWander::uniquePaceVariation() const
131{
132 return m_uniquePaceVariation;
133}
134
135/*!
136 \qmlproperty int Wander3D::fadeInDuration
137
138 This property defines the duration in milliseconds for fading in the affector.
139 After this duration, the wandering will be in full effect.
140 Setting this can be useful to emit from a specific position or shape,
141 otherwise wander will affect position also at the beginning.
142
143 The default value is \c 0.
144*/
145int QQuick3DParticleWander::fadeInDuration() const
146{
147 return m_fadeInDuration;
148}
149
150/*!
151 \qmlproperty int Wander3D::fadeOutDuration
152
153 This property defines the duration in milliseconds for fading out the affector.
154 Setting this can be useful to reduce the wander when the particle life
155 time ends, for example when combined with \l Attractor3D so end positions will
156 match the \l{Attractor3D::shape}{shape}.
157
158 The default value is \c 0.
159*/
160int QQuick3DParticleWander::fadeOutDuration() const
161{
162 return m_fadeOutDuration;
163}
164
165void QQuick3DParticleWander::setGlobalAmount(const QVector3D &globalAmount)
166{
167 if (m_globalAmount == globalAmount)
168 return;
169
170 m_globalAmount = globalAmount;
171 Q_EMIT globalAmountChanged();
172 Q_EMIT update();
173}
174
175void QQuick3DParticleWander::setGlobalPace(const QVector3D &globalPace)
176{
177 if (m_globalPace == globalPace)
178 return;
179
180 m_globalPace = globalPace;
181 Q_EMIT globalPaceChanged();
182 Q_EMIT update();
183}
184
185void QQuick3DParticleWander::setGlobalPaceStart(const QVector3D &globalPaceStart)
186{
187 if (m_globalPaceStart == globalPaceStart)
188 return;
189
190 m_globalPaceStart = globalPaceStart;
191 Q_EMIT globalPaceStartChanged();
192 Q_EMIT update();
193}
194
195void QQuick3DParticleWander::setUniqueAmount(const QVector3D &uniqueAmount)
196{
197 if (m_uniqueAmount == uniqueAmount)
198 return;
199
200 m_uniqueAmount = uniqueAmount;
201 Q_EMIT uniqueAmountChanged();
202 Q_EMIT update();
203}
204
205void QQuick3DParticleWander::setUniquePace(const QVector3D &uniquePace)
206{
207 if (m_uniquePace == uniquePace)
208 return;
209
210 m_uniquePace = uniquePace;
211 Q_EMIT uniquePaceChanged();
212 Q_EMIT update();
213}
214
215void QQuick3DParticleWander::setUniqueAmountVariation(float uniqueAmountVariation)
216{
217 if (qFuzzyCompare(m_uniqueAmountVariation, uniqueAmountVariation))
218 return;
219
220 uniqueAmountVariation = std::max(0.0f, std::min(1.0f, uniqueAmountVariation));
221 m_uniqueAmountVariation = uniqueAmountVariation;
222 Q_EMIT uniqueAmountVariationChanged();
223 Q_EMIT update();
224}
225
226void QQuick3DParticleWander::setUniquePaceVariation(float uniquePaceVariation)
227{
228 if (qFuzzyCompare(m_uniquePaceVariation, uniquePaceVariation))
229 return;
230
231 uniquePaceVariation = std::max(0.0f, std::min(1.0f, uniquePaceVariation));
232 m_uniquePaceVariation = uniquePaceVariation;
233 Q_EMIT uniquePaceVariationChanged();
234 Q_EMIT update();
235}
236
237void QQuick3DParticleWander::setFadeInDuration(int fadeInDuration)
238{
239 if (m_fadeInDuration == fadeInDuration)
240 return;
241
242 m_fadeInDuration = std::max(0, fadeInDuration);
243 Q_EMIT fadeInDurationChanged();
244 Q_EMIT update();
245}
246
247void QQuick3DParticleWander::setFadeOutDuration(int fadeOutDuration)
248{
249 if (m_fadeOutDuration == fadeOutDuration)
250 return;
251
252 m_fadeOutDuration = std::max(0, fadeOutDuration);
253 Q_EMIT fadeOutDurationChanged();
254 Q_EMIT update();
255}
256
257void QQuick3DParticleWander::affectParticle(const QQuick3DParticleData &sd, QQuick3DParticleDataCurrent *d, float time)
258{
259 if (!system())
260 return;
261 auto rand = system()->rand();
262
263 // Optionally smoothen the beginning & end of wander
264 float smooth = 1.0f;
265 if (m_fadeInDuration > 0) {
266 smooth = time / (float(m_fadeInDuration) / 1000.0f);
267 smooth = std::min(1.0f, smooth);
268 }
269 if (m_fadeOutDuration > 0) {
270 float timeLeft = (sd.lifetime - time);
271 float smoothOut = timeLeft / (float(m_fadeOutDuration) / 1000.0f);
272 // When fading both in & out, select smaller (which is always max 1.0)
273 smooth = std::min(smoothOut, smooth);
274 }
275
276 const float pi2 = float(M_PI * 2);
277 // Global
278 if (!qFuzzyIsNull(m_globalAmount.x()) && !qFuzzyIsNull(m_globalPace.x()))
279 d->position.setX(d->position.x() + smooth * QPSIN(m_globalPaceStart.x() + time * pi2 * m_globalPace.x()) * m_globalAmount.x());
280 if (!qFuzzyIsNull(m_globalAmount.y()) && !qFuzzyIsNull(m_globalPace.y()))
281 d->position.setY(d->position.y() + smooth * QPSIN(m_globalPaceStart.y() + time * pi2 * m_globalPace.y()) * m_globalAmount.y());
282 if (!qFuzzyIsNull(m_globalAmount.z()) && !qFuzzyIsNull(m_globalPace.z()))
283 d->position.setZ(d->position.z() + smooth * QPSIN(m_globalPaceStart.z() + time * pi2 * m_globalPace.z()) * m_globalAmount.z());
284
285 // Unique
286 // Rather simple to only use a single sin operation per direction
287 if (!qFuzzyIsNull(m_uniqueAmount.x()) && !qFuzzyIsNull(m_uniquePace.x())) {
288 // Values between 1.0 +/- variation
289 float paceVariation = 1.0f + m_uniquePaceVariation - 2.0f * rand->get(sd.index, QPRand::WanderXPV) * m_uniquePaceVariation;
290 float amountVariation = 1.0f + m_uniqueAmountVariation - 2.0f * rand->get(sd.index, QPRand::WanderXAV) * m_uniqueAmountVariation;
291 float startPace = rand->get(sd.index, QPRand::WanderXPS) * pi2;
292 float pace = startPace + paceVariation * time * pi2 * m_uniquePace.x();
293 float amount = amountVariation * m_uniqueAmount.x();
294 d->position.setX(d->position.x() + smooth * QPSIN(pace) * amount);
295 }
296 if (!qFuzzyIsNull(m_uniqueAmount.y()) && !qFuzzyIsNull(m_uniquePace.y())) {
297 // Values between 1.0 +/- variation
298 float paceVariation = 1.0f + m_uniquePaceVariation - 2.0f * rand->get(sd.index, QPRand::WanderYPV) * m_uniquePaceVariation;
299 float amountVariation = 1.0f + m_uniqueAmountVariation - 2.0f * rand->get(sd.index, QPRand::WanderYAV) * m_uniqueAmountVariation;
300 float startPace = rand->get(sd.index, QPRand::WanderYPS) * pi2;
301 float pace = startPace + paceVariation * time * pi2 * m_uniquePace.y();
302 float amount = amountVariation * m_uniqueAmount.y();
303 d->position.setY(d->position.y() + smooth * QPSIN(pace) * amount);
304 }
305 if (!qFuzzyIsNull(m_uniqueAmount.z()) && !qFuzzyIsNull(m_uniquePace.z())) {
306 // Values between 1.0 +/- variation
307 float paceVariation = 1.0f + m_uniquePaceVariation - 2.0f * rand->get(sd.index, QPRand::WanderZPV) * m_uniquePaceVariation;
308 float amountVariation = 1.0f + m_uniqueAmountVariation - 2.0f * rand->get(sd.index, QPRand::WanderZAV) * m_uniqueAmountVariation;
309 float startPace = rand->get(sd.index, QPRand::WanderZPS) * pi2;
310 float pace = startPace + paceVariation * time * pi2 * m_uniquePace.z();
311 float amount = amountVariation * m_uniqueAmount.z();
312 d->position.setZ(d->position.z() + smooth * QPSIN(pace) * amount);
313 }
314}
315
316QT_END_NAMESPACE
Combined button and popup list for selecting options.
#define M_PI
Definition qmath.h:200
#define QPSIN