Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qquick3dparticleattractor.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
"qquick3dparticleattractor_p.h"
7
#
include
"qquick3dparticlerandomizer_p.h"
8
#
include
"qquick3dparticleutils_p.h"
9
10
QT_BEGIN_NAMESPACE
11
12
/*!
13
\qmltype Attractor3D
14
\inherits Affector3D
15
\inqmlmodule QtQuick3D.Particles3D
16
\brief Attracts particles towards a position or a shape.
17
\since 6.2
18
19
This element attracts particles towards a position inside the 3D view. To model
20
the gravity of a massive object whose center of gravity is far away, use \l Gravity3D.
21
22
The attraction position is defined either with the \l {Node::position}{position} and
23
\l positionVariation or with \l shape. If both are defined, \l shape is used.
24
*/
25
26
// Minimum duration in seconds
27
const
float
MIN_DURATION
= 0.001f;
28
29
QQuick3DParticleAttractor::QQuick3DParticleAttractor(QQuick3DNode *parent)
30
: QQuick3DParticleAffector(parent)
31
, m_duration(-1)
32
, m_durationVariation(0)
33
{
34
}
35
36
/*!
37
\qmlproperty vector3d Attractor3D::positionVariation
38
39
This property defines the variation on attract position. It can be used to not attract
40
into a single point, but randomly towards a wider area. Here is an example how to attract
41
particles into some random point inside (50, 50, 50) cube at position (100, 0, 0) within
42
2 to 4 seconds:
43
44
\qml
45
Attractor3D {
46
position: Qt.vector3d(100, 0, 0)
47
positionVariation: Qt.vector3d(50, 50, 50)
48
duration: 3000
49
durationVariation: 1000
50
}
51
\endqml
52
53
The default value is \c (0, 0, 0) (no variation).
54
55
\sa {Node::position}, shape
56
*/
57
QVector3D QQuick3DParticleAttractor::positionVariation()
const
58
{
59
return
m_positionVariation;
60
}
61
62
void
QQuick3DParticleAttractor::setPositionVariation(
const
QVector3D &positionVariation)
63
{
64
if
(m_positionVariation == positionVariation)
65
return
;
66
67
m_positionVariation = positionVariation;
68
Q_EMIT positionVariationChanged();
69
Q_EMIT update();
70
}
71
72
/*!
73
\qmlproperty ParticleAbstractShape3D Attractor3D::shape
74
75
This property defines a \l ParticleAbstractShape3D for particles attraction.
76
Each particle will be attracted into a random position inside this shape. This is an
77
alternative for defining \l {Node::position}{position} and \l positionVariation. Here
78
is an example how to attract particles into some random point inside sphere by the end
79
of the particles \l {ParticleEmitter3D::}{lifeSpan}:
80
81
\qml
82
Attractor3D {
83
position: Qt.vector3d(100, 0, 0)
84
shape: ParticleShape3D {
85
type: ParticleShape3D.Sphere
86
fill: true
87
}
88
}
89
\endqml
90
91
\sa {Node::position}, positionVariation
92
*/
93
QQuick3DParticleAbstractShape *QQuick3DParticleAttractor::shape()
const
94
{
95
return
m_shape;
96
}
97
98
void
QQuick3DParticleAttractor::setShape(QQuick3DParticleAbstractShape *shape)
99
{
100
if
(m_shape == shape)
101
return
;
102
103
m_shape = shape;
104
m_shapeDirty =
true
;
105
Q_EMIT shapeChanged();
106
Q_EMIT update();
107
}
108
109
/*!
110
\qmlproperty int Attractor3D::duration
111
112
This property defines the duration in milliseconds how long it takes for particles to
113
reach the attaction position. When the value is -1, particle lifeSpan is used
114
as the duration.
115
116
The default value is \c -1.
117
*/
118
int
QQuick3DParticleAttractor::duration()
const
119
{
120
return
m_duration;
121
}
122
123
void
QQuick3DParticleAttractor::setDuration(
int
duration)
124
{
125
if
(m_duration == duration)
126
return
;
127
128
m_duration = duration;
129
Q_EMIT durationChanged();
130
Q_EMIT update();
131
}
132
133
/*!
134
\qmlproperty int Attractor3D::durationVariation
135
136
This property defines the duration variation in milliseconds. The actual duration to
137
reach attractor is between \c duration - \c durationVariation and \c duration + \c durationVariation.
138
139
The default value is \c 0 (no variation).
140
*/
141
int
QQuick3DParticleAttractor::durationVariation()
const
142
{
143
return
m_durationVariation;
144
}
145
146
void
QQuick3DParticleAttractor::setDurationVariation(
int
durationVariation)
147
{
148
if
(m_durationVariation == durationVariation)
149
return
;
150
151
m_durationVariation = durationVariation;
152
Q_EMIT durationVariationChanged();
153
Q_EMIT update();
154
}
155
156
/*!
157
\qmlproperty bool Attractor3D::hideAtEnd
158
159
This property defines if the particle should disappear when it reaches the attractor.
160
161
The default value is \c false.
162
*/
163
bool
QQuick3DParticleAttractor::hideAtEnd()
const
164
{
165
return
m_hideAtEnd;
166
}
167
168
/*!
169
\qmlproperty bool Attractor3D::useCachedPositions
170
171
This property defines if the attractor caches possible positions within its shape.
172
Cached positions give less random results but are better for performance.
173
174
The default value is \c true.
175
*/
176
bool
QQuick3DParticleAttractor::useCachedPositions()
const
177
{
178
return
m_useCachedPositions;
179
}
180
181
/*!
182
\qmlproperty int Attractor3D::positionsAmount
183
184
This property defines the amount of possible positions stored within the attractor shape.
185
By default the amount equals the particle count, but a lower amount can be used for a smaller cache.
186
Higher amount can be used for additional randomization.
187
*/
188
int
QQuick3DParticleAttractor::positionsAmount()
const
189
{
190
return
m_positionsAmount;
191
}
192
193
void
QQuick3DParticleAttractor::setHideAtEnd(
bool
hideAtEnd)
194
{
195
if
(m_hideAtEnd == hideAtEnd)
196
return
;
197
198
m_hideAtEnd = hideAtEnd;
199
Q_EMIT hideAtEndChanged();
200
Q_EMIT update();
201
}
202
203
void
QQuick3DParticleAttractor::setUseCachedPositions(
bool
useCachedPositions)
204
{
205
if
(m_useCachedPositions == useCachedPositions)
206
return
;
207
208
m_useCachedPositions = useCachedPositions;
209
Q_EMIT useCachedPositionsChanged();
210
m_shapeDirty =
true
;
211
}
212
213
void
QQuick3DParticleAttractor::setPositionsAmount(
int
positionsAmount)
214
{
215
if
(m_positionsAmount == positionsAmount)
216
return
;
217
218
m_positionsAmount = positionsAmount;
219
Q_EMIT positionsAmountChanged();
220
m_shapeDirty =
true
;
221
}
222
223
void
QQuick3DParticleAttractor::updateShapePositions()
224
{
225
m_shapePositionList.clear();
226
if
(!system() || !m_shape)
227
return
;
228
229
m_shape->m_system = system();
230
231
if
(m_useCachedPositions) {
232
// Get count of particles positions needed
233
int
pCount = 0;
234
if
(m_positionsAmount > 0) {
235
pCount = m_positionsAmount;
236
}
else
{
237
if
(!m_particles.isEmpty()) {
238
for
(
auto
*p : std::as_const(m_particles)) {
239
auto
pp = qobject_cast<QQuick3DParticle *>(p);
240
pCount += pp->maxAmount();
241
}
242
}
else
{
243
pCount = system()->particleCount();
244
}
245
}
246
247
m_shapePositionList.reserve(pCount);
248
for
(
int
i = 0; i < pCount; i++)
249
m_shapePositionList << m_shape->getPosition(i);
250
}
else
{
251
m_shapePositionList.clear();
252
m_shapePositionList.squeeze();
253
}
254
255
m_shapeDirty =
false
;
256
}
257
258
void
QQuick3DParticleAttractor::prepareToAffect()
259
{
260
if
(m_shapeDirty)
261
updateShapePositions();
262
m_centerPos = position();
263
m_particleTransform = calculateParticleTransform(parentNode(), m_systemSharedParent);
264
}
265
266
void
QQuick3DParticleAttractor::affectParticle(
const
QQuick3DParticleData &sd, QQuick3DParticleDataCurrent *d,
float
time)
267
{
268
if
(!system())
269
return
;
270
271
auto
rand = system()->rand();
272
float
duration = m_duration < 0 ? sd.lifetime : (m_duration / 1000.0f);
273
float
durationVariation = m_durationVariation == 0
274
? 0.0f
275
: (m_durationVariation / 1000.0f) - 2.0f * rand->get(sd.index, QPRand::AttractorDurationV) * (m_durationVariation / 1000.0f);
276
duration = std::max(duration + durationVariation, MIN_DURATION);
277
float
pEnd = std::min(1.0f, std::max(0.0f, time / duration));
278
// TODO: Should we support easing?
279
//pEnd = easeInOutQuad(pEnd);
280
281
if
(m_hideAtEnd && pEnd >= 1.0f) {
282
d->color.a = 0;
283
return
;
284
}
285
286
float
pStart = 1.0f - pEnd;
287
QVector3D pos = m_centerPos;
288
289
if
(m_shape) {
290
if
(m_useCachedPositions)
291
pos += m_shapePositionList[sd.index % m_shapePositionList.size()];
292
else
293
pos += m_shape->getPosition(sd.index);
294
}
295
296
if
(!m_positionVariation.isNull()) {
297
pos.setX(pos.x() + m_positionVariation.x() - 2.0f * rand->get(sd.index, QPRand::AttractorPosVX) * m_positionVariation.x());
298
pos.setY(pos.y() + m_positionVariation.y() - 2.0f * rand->get(sd.index, QPRand::AttractorPosVY) * m_positionVariation.y());
299
pos.setZ(pos.z() + m_positionVariation.z() - 2.0f * rand->get(sd.index, QPRand::AttractorPosVZ) * m_positionVariation.z());
300
}
301
302
d->position = (pStart * d->position) + (pEnd * m_particleTransform.map(pos));
303
}
304
305
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
MIN_DURATION
QT_BEGIN_NAMESPACE const float MIN_DURATION
\qmltype Attractor3D \inherits Affector3D \inqmlmodule QtQuick3D.Particles3D
Definition
qquick3dparticleattractor.cpp:27
qtquick3d
src
quick3dparticles
qquick3dparticleattractor.cpp
Generated on
for Qt by
1.18.0