1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef QQUICK3DPARTICLEUTILS_H
5#define QQUICK3DPARTICLEUTILS_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 <qmath.h>
19#include <qmatrix4x4.h>
20#include <QtQuick3DParticles/qtquick3dparticlesglobal.h>
21#include <private/qglobal_p.h>
22
23class QQuick3DNode;
24
25QT_BEGIN_NAMESPACE
26
27// Define this to use C++ std::sinf & std::cosf for particles.
28// Those are more accurate, but also potentially less performant
29// than the lookup table versions.
30#ifdef QT_QUICK3D_PARTICLES_USE_STANDARD_SIN
31#define QPSIN sinf
32#define QPCOS cosf
33#else
34#define QPSIN qLookupSin
35#define QPCOS qLookupCos
36#endif
37
38// These sin & cos implementations are copied from qmath.h qFastSin & qFastCos.
39// Changes:
40// - Modified to use float instead of qreal (double).
41// - Use constexpr for optimization.
42//
43// With input values between 0 .. 2*M_PI, the accuracy of qLookupSin is quite good
44// (max delta ~2.5e-06). When the input values grow, accuracy decreases. For example
45// with value 2058, diff is ~0.00014 and with value 9632 diff is ~0.00074.
46// So these methods should not be used with a large input range if accuracy is important.
47
48#define QT_QUICK3D_SINE_TABLE_SIZE 256
49
50// Precalculated constexpr helpers
51static constexpr float QT_QUICK3D_SINE_H1 = 0.5f * float(QT_QUICK3D_SINE_TABLE_SIZE / M_PI);
52static constexpr float QT_QUICK3D_SINE_H2 = 2.0f * float(M_PI / QT_QUICK3D_SINE_TABLE_SIZE);
53
54extern Q_QUICK3DPARTICLES_EXPORT const float qt_quick3d_sine_table[QT_QUICK3D_SINE_TABLE_SIZE];
55
56inline float qLookupSin(float x)
57{
58 int si = int(x * QT_QUICK3D_SINE_H1); // Would be more accurate with qRound, but slower.
59 float d = x - si * QT_QUICK3D_SINE_H2;
60 int ci = si + QT_QUICK3D_SINE_TABLE_SIZE / 4;
61 si &= QT_QUICK3D_SINE_TABLE_SIZE - 1;
62 ci &= QT_QUICK3D_SINE_TABLE_SIZE - 1;
63 return qt_quick3d_sine_table[si] + (qt_quick3d_sine_table[ci] - 0.5f * qt_quick3d_sine_table[si] * d) * d;
64}
65
66inline float qLookupCos(float x)
67{
68 int ci = int(x * QT_QUICK3D_SINE_H1); // Would be more accurate with qRound, but slower.
69 float d = x - ci * QT_QUICK3D_SINE_H2;
70 int si = ci + QT_QUICK3D_SINE_TABLE_SIZE / 4;
71 si &= QT_QUICK3D_SINE_TABLE_SIZE - 1;
72 ci &= QT_QUICK3D_SINE_TABLE_SIZE - 1;
73 return qt_quick3d_sine_table[si] - (qt_quick3d_sine_table[ci] + 0.5f * qt_quick3d_sine_table[si] * d) * d;
74}
75
76QQuick3DNode *getSharedParentNode(QQuick3DNode *node, QQuick3DNode *system);
77QMatrix4x4 calculateParticleTransform(const QQuick3DNode *parent, const QQuick3DNode *systemSharedParent);
78QQuaternion calculateParticleRotation(const QQuick3DNode *parent, const QQuick3DNode *systemSharedParent);
79
80QT_END_NAMESPACE
81
82#endif // QQUICK3DPARTICLEUTILS_H
83

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