1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef QQUICK3DPARTICLERANDOMIZER_H
5#define QQUICK3DPARTICLERANDOMIZER_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QRandomGenerator>
19#include <QList>
20#include <private/qglobal_p.h>
21
22QT_BEGIN_NAMESPACE
23
24/*
25
26Simple helper to get pseudo-random numbers which remain the same per particle & user.
27Particles don't need strong randomization and the ability to seed can be useful.
28
29Based on brief testing on my laptop, getting 1.000.000 random numbers:
30
311) Using QRandomGenerator::global()->generateDouble()
32-> ~120ms
33
342) Using QPRand::get(), with m_size 4096
35-> ~8ms
36
373) Using QPRand::get(i, j), with m_size 4096
38-> ~10ms
39
404) Using QPRand::get(i, j), with m_size 100000
41-> ~10ms
42
43So QPRand seems fast and increasing keys amount doesn't notably affect the performance,
44just the memory usage. With more particles m_size should be relatively big to make sure
45particles appear random enough.
46
47Bounded usage tips:
48- qrg->bounded(4.0) == QPRand::get() * 4.0
49- qrg->bounded(4) == int(QPRand::get() * 4)
50
51*/
52
53class QPRand
54{
55public:
56
57 // Add here new enums for diferent "users".
58 // This way e.g. particle can vary little on colors but more on sizes.
59 enum UserType {
60 Default = 0,
61 WanderXPS, // PaceStart
62 WanderYPS,
63 WanderZPS,
64 WanderXPV, // PaceVariation
65 WanderYPV,
66 WanderZPV,
67 WanderXAV, // AmountVariation
68 WanderYAV,
69 WanderZAV,
70 AttractorDurationV,
71 AttractorPosVX,
72 AttractorPosVY,
73 AttractorPosVZ,
74 Shape1, // Shape
75 Shape2,
76 Shape3,
77 Shape4,
78 SpriteAnimationI,
79 DeterministicSeparator, // Note: Enums before this must always be
80 // deterministic based on the particle index
81 LifeSpanV, // Emitter
82 ScaleV,
83 ScaleEV,
84 RotXV,
85 RotYV,
86 RotZV,
87 RotXVV,
88 RotYVV,
89 RotZVV,
90 ColorRV,
91 ColorGV,
92 ColorBV,
93 ColorAV,
94 TDirPosXV, // TargetDirection
95 TDirPosYV,
96 TDirPosZV,
97 TDirMagV,
98 VDirXV, // VectorDirection
99 VDirYV,
100 VDirZV,
101 SpriteAnimationV
102 };
103
104 void init(quint32 seed, int size = 65536) {
105 m_size = size;
106 m_generator.seed(s: seed);
107 m_randomList.clear();
108 m_randomList.reserve(asize: m_size);
109 for (int i = 0; i < m_size; i++)
110 m_randomList << float(m_generator.generateDouble());
111 }
112
113 void setDeterministic(bool deterministic) {
114 m_deterministic = deterministic;
115 }
116
117 // Return float 0.0 - 1.0
118 // With the same input values, returns always the same output.
119 inline float get(int particleIndex, UserType user = Default) {
120 if (!m_deterministic && user > DeterministicSeparator)
121 return get();
122 int i = (particleIndex + user) % m_size;
123 return m_randomList.at(i);
124 }
125
126 // Return float 0.0 - 1.0 from random list
127 // Note: Not deterministic between runs
128 inline float get() {
129 m_index = (m_index < m_size - 1) ? m_index + 1 : 0;
130 return m_randomList.at(i: m_index);
131 }
132 QRandomGenerator generator() const
133 {
134 return m_generator;
135 }
136private:
137 QRandomGenerator m_generator;
138 int m_size = 0;
139 int m_index = 0;
140 bool m_deterministic = false;
141 QList<float> m_randomList;
142
143};
144
145QT_END_NAMESPACE
146
147#endif // QQUICK3DPARTICLERANDOMIZER_H
148

source code of qtquick3d/src/quick3dparticles/qquick3dparticlerandomizer_p.h