1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qquick3dparticlerepeller_p.h"
5
6QT_BEGIN_NAMESPACE
7
8/*!
9 \qmltype Repeller3D
10 \inherits Affector3D
11 \inqmlmodule QtQuick3D.Particles3D
12 \brief Particle repeller.
13 \since 6.4
14
15 Repeller affector repels particles from the position it is placed.
16*/
17
18QQuick3DParticleRepeller::QQuick3DParticleRepeller(QQuick3DNode *parent)
19 : QQuick3DParticleAffector(parent)
20{
21
22}
23
24/*!
25 \qmlproperty real Repeller3D::radius
26
27 This property holds the radius(or inner radius) of the repeller. Particle is repelled
28 at full strength when it gets inside this radius. The default value is zero.
29*/
30float QQuick3DParticleRepeller::radius() const
31{
32 return m_radius;
33}
34
35/*!
36 \qmlproperty real Repeller3D::outerRadius
37
38 This property holds the outer radius of the repeller. The particle is not affected
39 until it gets inside this radius and the repel strength grows smoothly until the particle
40 gets to radius distance from the repeller. The default value is 50.0;
41*/
42float QQuick3DParticleRepeller::outerRadius() const
43{
44 return m_outerRadius;
45}
46
47/*!
48 \qmlproperty real Repeller3D::strength
49
50 This property holds the strength of the repeller. The default value is 50.0;
51*/
52float QQuick3DParticleRepeller::strength() const
53{
54 return m_strength;
55}
56
57void QQuick3DParticleRepeller::setRadius(float radius)
58{
59 radius = qMax(a: 0.0f, b: radius);
60 if (qFuzzyCompare(p1: radius, p2: m_radius)) return;
61
62 m_radius = radius;
63 Q_EMIT radiusChanged();
64}
65
66void QQuick3DParticleRepeller::setOuterRadius(float radius)
67{
68 radius = qMax(a: 0.0f, b: radius);
69 if (qFuzzyCompare(p1: radius, p2: m_outerRadius)) return;
70
71 m_outerRadius = radius;
72 Q_EMIT outerRadiusChanged();
73}
74
75void QQuick3DParticleRepeller::setStrength(float strength)
76{
77 strength = qMax(a: 0.0f, b: strength);
78 if (qFuzzyCompare(p1: strength, p2: m_strength)) return;
79
80 m_strength = strength;
81 Q_EMIT strengthChanged();
82}
83
84void QQuick3DParticleRepeller::prepareToAffect()
85{
86
87}
88
89static float qt_smoothstep(float edge0, float edge1, float x)
90{
91 float t;
92 t = qBound(min: 0.0f, val: (x - edge0) / (edge1 - edge0), max: 1.0f);
93 return t * t * (3.0f - 2.0f * t);
94}
95
96void QQuick3DParticleRepeller::affectParticle(const QQuick3DParticleData &, QQuick3DParticleDataCurrent *d, float )
97{
98 QVector3D pos = position();
99 QVector3D dir = d->position - pos;
100 float radius = dir.length();
101 float outerRadius = qMax(a: m_outerRadius, b: m_radius);
102 if (radius > outerRadius || qFuzzyIsNull(f: radius))
103 return;
104
105 if (radius < m_radius)
106 d->position += dir * m_strength / radius;
107 else
108 d->position += dir * m_strength * (1.0f - qt_smoothstep(edge0: m_radius, edge1: outerRadius, x: radius)) / radius;
109}
110
111QT_END_NAMESPACE
112

source code of qtquick3d/src/quick3dparticles/qquick3dparticlerepeller.cpp