10#include <QtQml/qqmlfile.h>
11#include <QtQuick3D/private/qquick3dmodel_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrenderbuffermanager_p.h>
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
47QQuick3DParticleModelShape::QQuick3DParticleModelShape(QObject *parent)
48 : QQuick3DParticleAbstractShape(parent)
53QQuick3DParticleModelShape::~QQuick3DParticleModelShape()
59
60
61
62
63
64
65bool QQuick3DParticleModelShape::fill()
const
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88QQmlComponent *QQuick3DParticleModelShape::delegate()
const
93void QQuick3DParticleModelShape::setFill(
bool fill)
102QVector3D QQuick3DParticleModelShape::getPosition(
int particleIndex)
104 return randomPositionModel(particleIndex);
107QVector3D QQuick3DParticleModelShape::getSurfaceNormal(
int particleIndex)
109 if (m_cachedIndex != particleIndex)
110 getPosition(particleIndex);
111 return m_cachedNormal;
114void QQuick3DParticleModelShape::setDelegate(QQmlComponent *delegate)
116 if (delegate == m_delegate)
118 m_delegate = delegate;
119 clearModelVertexPositions();
121 Q_EMIT delegateChanged();
124void QQuick3DParticleModelShape::createModel()
130 auto *obj = m_delegate->create(m_delegate->creationContext());
131 m_model = qobject_cast<QQuick3DModel *>(obj);
136QVector3D QQuick3DParticleModelShape::randomPositionModel(
int particleIndex)
139 calculateModelVertexPositions();
141 const QVector<QVector3D> &positions = m_vertexPositions;
142 if (positions.size() > 0) {
143 auto rand = m_system->rand();
147 if (m_modelTriangleAreas.size() == 0) {
148 m_modelTriangleAreas.reserve(positions.size() / 3);
149 for (
int i = 0; i + 2 < positions.size(); i += 3) {
150 const QVector3D &v1 = positions[i];
151 const QVector3D &v2 = positions[i + 1];
152 const QVector3D &v3 = positions[i + 2];
153 const float area = QVector3D::crossProduct(v1 - v2, v1 - v3).length() * 0.5f;
154 m_modelTriangleAreasSum += area;
155 m_modelTriangleAreas.append(m_modelTriangleAreasSum);
156 m_modelTriangleCenter += v1 + v2 + v3;
158 m_modelTriangleCenter /= positions.size();
161 const float rndWeight = rand->get(particleIndex, QPRand::Shape1) * m_modelTriangleAreasSum;
164 int index = std::lower_bound(m_modelTriangleAreas.begin(), m_modelTriangleAreas.end(), rndWeight) - m_modelTriangleAreas.begin();
166 const QVector3D &v1 = positions[index * 3];
167 const QVector3D &v2 = positions[index * 3 + 1];
168 const QVector3D &v3 = positions[index * 3 + 2];
169 const float a = rand->get(particleIndex, QPRand::Shape2);
170 const float b = rand->get(particleIndex, QPRand::Shape3);
171 const float aSqrt = qSqrt(a);
174 QVector3D pos = (1.0 - aSqrt) * v1 + (aSqrt * (1.0 - b)) * v2 + (b * aSqrt) * v3;
180 const float uniform = rand->get(particleIndex, QPRand::Shape4);
181 const float lambda = 5.0f;
182 const float alpha = -qLn(1 - (1 - qExp(-lambda)) * uniform) / lambda;
183 pos += (m_modelTriangleCenter - pos) * alpha;
185 m_cachedIndex = particleIndex;
186 m_cachedNormal = QVector3D::crossProduct(v2 - v1, v3 - v2).normalized();
189 auto *parent = parentNode();
192 mat.rotate(parent->rotation() * m_model->rotation());
194 m_cachedNormal = mat.mapVector(m_cachedNormal);
195 return mat.mapVector(pos * parent->sceneScale() * m_model->scale());
199 return QVector3D(0, 0, 0);
202void QQuick3DParticleModelShape::clearModelVertexPositions()
204 m_vertexPositions.clear();
205 m_modelTriangleAreas.clear();
206 m_modelTriangleAreasSum = 0;
209void QQuick3DParticleModelShape::calculateModelVertexPositions()
211 if (m_vertexPositions.empty())
212 m_vertexPositions = positionsFromModel(m_model,
nullptr, qmlContext(
this));