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
qquick3dparticlecustomshape.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
"qquick3dparticlecustomshape_p.h"
7
#
include
"qquick3dparticlerandomizer_p.h"
8
#
include
"qquick3dparticlesystem_p.h"
9
#
include
"qquick3dparticleutils_p.h"
10
#
include
"qquick3dparticleshapedatautils_p.h"
11
#
include
<
QtQml
/
qqmlcontext
.
h
>
12
#
include
<
QtQml
/
qqmlfile
.
h
>
13
#
include
<
QtCore
/
qfile
.
h
>
14
15
QT_BEGIN_NAMESPACE
16
17
/*!
18
\qmltype ParticleCustomShape3D
19
\inherits ParticleAbstractShape3D
20
\inqmlmodule QtQuick3D.Particles3D
21
\brief Loads custom particle shapes for emitters and affectors.
22
\since 6.3
23
24
The ParticleCustomShape3D element can be used to load custom particle shapes.
25
26
For example, to emit particles from positions defined in heart.cbor:
27
28
\qml
29
ParticleEmitter3D {
30
shape: ParticleCustomShape3D {
31
source: "heart.cbor"
32
}
33
...
34
}
35
\endqml
36
37
The format of CBOR shape files is following:
38
\badcode
39
[
40
"QQ3D_SHAPE", // string
41
version, // integer
42
[
43
posX, // float
44
posY, // float
45
posZ, // float
46
posX, // float
47
...
48
]
49
]
50
\endcode
51
52
To assist in generating these shape files you can use the shapegen tool.
53
*/
54
55
QQuick3DParticleCustomShape::QQuick3DParticleCustomShape(QObject *parent)
56
: QQuick3DParticleAbstractShape(parent)
57
{
58
}
59
60
/*!
61
\qmlproperty url ParticleCustomShape3D::source
62
63
This property holds the location of the shape file.
64
65
\warning \a source is expected to contain trusted content. Application
66
developers are advised to carefully consider the potential implications
67
before passing in user-provided source files that are not part of the
68
application.
69
*/
70
71
QUrl QQuick3DParticleCustomShape::source()
const
72
{
73
return
m_source;
74
}
75
76
/*!
77
\qmlproperty bool ParticleCustomShape3D::randomizeData
78
79
This property holds whether the particles are used in random order instead
80
of in the order they are specified in the source.
81
82
The default value is \c false.
83
*/
84
bool
QQuick3DParticleCustomShape::randomizeData()
const
85
{
86
return
m_random;
87
}
88
89
void
QQuick3DParticleCustomShape::setSource(
const
QUrl &source)
90
{
91
if
(m_source == source)
92
return
;
93
94
m_source = source;
95
96
loadFromSource();
97
Q_EMIT sourceChanged();
98
}
99
100
void
QQuick3DParticleCustomShape::setRandomizeData(
bool
random)
101
{
102
if
(m_random == random)
103
return
;
104
105
m_random = random;
106
if
(m_random)
107
m_randomizeDirty =
true
;
108
Q_EMIT randomizeDataChanged();
109
}
110
111
void
QQuick3DParticleCustomShape::loadFromSource()
112
{
113
m_positions.clear();
114
115
// Get path to file
116
const
QQmlContext *context = qmlContext(
this
);
117
QString dataFilePath = QQmlFile::urlToLocalFileOrQrc(context ? context->resolvedUrl(m_source) : m_source);
118
119
QFile dataFile(dataFilePath);
120
if
(!dataFile.open(QIODevice::ReadOnly)) {
121
// Invalid file
122
qWarning() <<
"Unable to open file:"
<< dataFilePath;
123
return
;
124
}
125
QCborStreamReader reader(&dataFile);
126
127
// Check that file is proper CBOR and get the version
128
int
version = QQuick3DParticleShapeDataUtils::readShapeHeader(reader);
129
130
if
(version == -1) {
131
// Invalid file
132
qWarning() <<
"Invalid shape data version:"
<< version;
133
return
;
134
}
135
136
// Start positions array
137
reader.enterContainer();
138
139
m_center = QVector3D();
140
while
(reader.lastError() == QCborError::NoError && reader.hasNext()) {
141
QVector3D pos = QQuick3DParticleShapeDataUtils::readValue(reader, QMetaType::QVector3D).value<QVector3D>();
142
m_positions.append(pos);
143
m_center += pos;
144
}
145
if
(!m_positions.isEmpty())
146
m_center *= 1.0f /
float
(m_positions.size());
147
148
// Leave positions array
149
reader.leaveContainer();
150
151
// Leave root array
152
reader.leaveContainer();
153
154
if
(m_random)
155
m_randomizeDirty =
true
;
156
}
157
158
void
QQuick3DParticleCustomShape::doRandomizeData()
159
{
160
if
(!m_system || m_positions.isEmpty())
161
return
;
162
163
auto
rand = m_system->rand();
164
int
seed = rand->get(0, QPRand::Shape1) *
float
(INT_MAX);
165
std::shuffle(m_positions.begin(), m_positions.end(), std::default_random_engine(seed));
166
167
m_randomizeDirty =
false
;
168
}
169
170
QVector3D QQuick3DParticleCustomShape::getPosition(
int
particleIndex)
171
{
172
auto
*parent = parentNode();
173
if
(!parent || m_positions.isEmpty())
174
return
QVector3D();
175
176
if
(m_randomizeDirty)
177
doRandomizeData();
178
179
int
index = particleIndex % m_positions.size();
180
return
m_positions.at(index) * parent->scale();
181
}
182
183
QVector3D QQuick3DParticleCustomShape::getSurfaceNormal(
int
particleIndex)
184
{
185
auto
*parent = parentNode();
186
if
(!parent || m_positions.isEmpty())
187
return
QVector3D();
188
189
if
(m_randomizeDirty)
190
doRandomizeData();
191
192
int
index = particleIndex % m_positions.size();
193
return
(m_positions.at(index) - m_center).normalized();
194
}
195
196
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtquick3d
src
quick3dparticles
qquick3dparticlecustomshape.cpp
Generated on
for Qt by
1.18.0