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
qquickturbulence.cpp
Go to the documentation of this file.
1
// Copyright (C) 2016 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
#
include
<
QtCore
/
qtconfigmacros
.
h
>
5
#
undef
QT_NO_FOREACH
// this file contains unported legacy Q_FOREACH uses
6
7
#
include
"qquickturbulence_p.h"
8
#
include
"qquickparticlepainter_p.h"
//TODO: Why was this needed again?
9
#
include
<
cmath
>
10
#
include
<
cstdlib
>
11
#
include
<
QDebug
>
12
#
include
<
QQmlFile
>
13
QT_BEGIN_NAMESPACE
14
15
/*!
16
\qmltype Turbulence
17
\nativetype QQuickTurbulenceAffector
18
\inqmlmodule QtQuick.Particles
19
\ingroup qtquick-particles
20
\inherits ParticleAffector
21
\brief Provides fluid-like forces from a noise image.
22
23
The Turbulence Element scales the noise source over the area it affects,
24
and uses the curl of that source to generate force vectors.
25
26
Turbulence requires a fixed size. Unlike other affectors, a 0x0 Turbulence element
27
will affect no particles.
28
29
The source should be relatively smooth black and white noise, such as perlin noise.
30
*/
31
/*!
32
\qmlproperty real QtQuick.Particles::Turbulence::strength
33
34
The magnitude of the velocity vector at any point varies between zero and
35
the square root of two. It will then be multiplied by strength to get the
36
velocity per second for the particles affected by the turbulence.
37
*/
38
/*!
39
\qmlproperty url QtQuick.Particles::Turbulence::noiseSource
40
41
The source image to generate the turbulence from. It will be scaled to the size of the element,
42
so equal or larger sizes will give better results. Tweaking this image is the only way to tweak
43
behavior such as where vortices are or how many exist.
44
45
The source should be a relatively smooth black and white noise image, such as perlin noise.
46
A default image will be used if none is provided.
47
*/
48
49
QQuickTurbulenceAffector::QQuickTurbulenceAffector(QQuickItem *parent) :
50
QQuickParticleAffector(parent),
51
m_strength(10), m_gridSize(0), m_field(
nullptr
), m_vectorField(
nullptr
), m_inited(
false
)
52
{
53
}
54
55
void
QQuickTurbulenceAffector::geometryChange(
const
QRectF &,
const
QRectF &)
56
{
57
initializeGrid();
58
}
59
60
QQuickTurbulenceAffector::~QQuickTurbulenceAffector()
61
{
62
if
(m_field) {
63
for
(
int
i=0; i<m_gridSize; i++)
64
free(m_field[i]);
65
free(m_field);
66
}
67
if
(m_vectorField) {
68
for
(
int
i=0; i<m_gridSize; i++)
69
free(m_vectorField[i]);
70
free(m_vectorField);
71
}
72
}
73
74
void
QQuickTurbulenceAffector::initializeGrid()
75
{
76
if
(!m_inited)
77
return
;
78
79
int
arg = qMax(width(), height());
80
if
(m_gridSize != arg) {
81
if
(m_field){
//deallocate and then reallocate grid
82
for
(
int
i=0; i<m_gridSize; i++)
83
free(m_field[i]);
84
free(m_field);
85
}
86
if
(m_vectorField) {
87
for
(
int
i=0; i<m_gridSize; i++)
88
free(m_vectorField[i]);
89
free(m_vectorField);
90
}
91
m_gridSize = arg;
92
}
93
94
m_field = (qreal**)malloc(m_gridSize *
sizeof
(qreal*));
95
for
(
int
i=0; i<m_gridSize; i++)
96
m_field[i] = (qreal*)malloc(m_gridSize *
sizeof
(qreal));
97
m_vectorField = (QPointF**)malloc(m_gridSize *
sizeof
(QPointF*));
98
for
(
int
i=0; i<m_gridSize; i++)
99
m_vectorField[i] = (QPointF*)malloc(m_gridSize *
sizeof
(QPointF));
100
101
QImage image;
102
if
(!m_noiseSource.isEmpty())
103
image = QImage(QQmlFile::urlToLocalFileOrQrc(m_noiseSource)).scaled(QSize(m_gridSize, m_gridSize));
104
if
(image.isNull())
105
image = QImage(QStringLiteral(
":particleresources/noise.png"
)).scaled(QSize(m_gridSize, m_gridSize));
106
107
for
(
int
i=0; i<m_gridSize; i++)
108
for
(
int
j=0; j<m_gridSize; j++)
109
m_field[i][j] = qGray(image.pixel(QPoint(i,j)));
110
for
(
int
i=0; i<m_gridSize; i++){
111
for
(
int
j=0; j<m_gridSize; j++){
112
m_vectorField[i][j].setX(boundsRespectingField(i-1,j) - boundsRespectingField(i,j));
113
m_vectorField[i][j].setY(boundsRespectingField(i,j) - boundsRespectingField(i,j-1));
114
}
115
}
116
}
117
118
qreal QQuickTurbulenceAffector::boundsRespectingField(
int
x,
int
y)
119
{
120
if
(x < 0)
121
x = 0;
122
if
(x >= m_gridSize)
123
x = m_gridSize - 1;
124
if
(y < 0)
125
y = 0;
126
if
(y >= m_gridSize)
127
y = m_gridSize - 1;
128
return
m_field[x][y];
129
}
130
131
void
QQuickTurbulenceAffector::ensureInit()
132
{
133
if
(m_inited)
134
return
;
135
m_inited =
true
;
136
initializeGrid();
137
}
138
139
void
QQuickTurbulenceAffector::affectSystem(qreal dt)
140
{
141
if
(!m_system || !m_enabled)
142
return
;
143
ensureInit();
144
if
(!m_gridSize)
145
return
;
146
147
updateOffsets();
//### Needed if an ancestor is transformed.
148
149
QRect boundsRect(0,0,m_gridSize,m_gridSize);
150
for
(QQuickParticleGroupData *gd : m_system->groupData) {
151
if
(!activeGroup(gd->index))
152
continue
;
153
foreach (QQuickParticleData *d, gd->data){
154
if
(!shouldAffect(d))
155
continue
;
156
QPoint pos = (QPointF(d->curX(m_system), d->curY(m_system)) - m_offset).toPoint();
157
if
(!boundsRect.contains(pos,
true
))
//Need to redo bounds checking due to quantization.
158
continue
;
159
qreal fx = 0.0;
160
qreal fy = 0.0;
161
fx += m_vectorField[pos.x()][pos.y()].x() * m_strength;
162
fy += m_vectorField[pos.x()][pos.y()].y() * m_strength;
163
if
(fx || fy){
164
d->setInstantaneousVX(d->curVX(m_system)+ fx * dt, m_system);
165
d->setInstantaneousVY(d->curVY(m_system)+ fy * dt, m_system);
166
postAffect(d);
167
}
168
}
169
}
170
}
171
172
QT_END_NAMESPACE
173
174
#
include
"moc_qquickturbulence_p.cpp"
qtdeclarative
src
particles
qquickturbulence.cpp
Generated on
for Qt by
1.18.0