1 | // Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "uniform_p.h" |
5 | #include "qabstracttexture.h" |
6 | #include <QVariant> |
7 | |
8 | QT_BEGIN_NAMESPACE |
9 | |
10 | namespace Qt3DRender { |
11 | namespace Render { |
12 | |
13 | namespace { |
14 | |
15 | const int qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); |
16 | const int qVector3DTypeId = qMetaTypeId<Vector3D>(); |
17 | const int qVector4DTypeId = qMetaTypeId<Vector4D>(); |
18 | const int qMatrix4x4TypeId = qMetaTypeId<Matrix4x4>(); |
19 | |
20 | // glUniform*fv/glUniform*iv/glUniform*uiv -> only handles sizeof(float)/sizeof(int) |
21 | int byteSizeForMetaType(int type) |
22 | { |
23 | if (type == qMatrix4x4TypeId) |
24 | return sizeof(Matrix4x4); |
25 | if (type == qVector3DTypeId) |
26 | return sizeof(Vector3D); |
27 | if (type == qVector4DTypeId) |
28 | return sizeof(Vector4D); |
29 | if (type == qNodeIdTypeId) |
30 | return sizeof(Qt3DCore::QNodeId); |
31 | |
32 | switch (type) { |
33 | case QMetaType::Bool: |
34 | case QMetaType::Int: |
35 | case QMetaType::UInt: |
36 | case QMetaType::ULongLong: |
37 | case QMetaType::LongLong: |
38 | case QMetaType::Long: |
39 | case QMetaType::ULong: |
40 | case QMetaType::Short: |
41 | case QMetaType::UShort: |
42 | case QMetaType::Char: |
43 | case QMetaType::UChar: |
44 | return sizeof(int); |
45 | |
46 | case QMetaType::Float: |
47 | case QMetaType::Double: // Assumes conversion to float |
48 | return sizeof(float); |
49 | |
50 | case QMetaType::QPoint: |
51 | case QMetaType::QSize: |
52 | return 2 * sizeof(int); |
53 | |
54 | case QMetaType::QRect: |
55 | return 4 * sizeof(int); |
56 | |
57 | case QMetaType::QPointF: |
58 | case QMetaType::QSizeF: |
59 | case QMetaType::QVector2D: |
60 | return 2 * sizeof(float); |
61 | |
62 | case QMetaType::QVector3D: |
63 | return 3 * sizeof(float); |
64 | |
65 | case QMetaType::QRectF: |
66 | case QMetaType::QVector4D: |
67 | case QMetaType::QColor: |
68 | return 4 * sizeof(float); |
69 | case QMetaType::QMatrix4x4: |
70 | return 16 * sizeof(float); |
71 | |
72 | default: |
73 | Q_UNREACHABLE_RETURN(-1); |
74 | } |
75 | } |
76 | |
77 | } // anonymous |
78 | |
79 | UniformValue UniformValue::fromVariant(const QVariant &variant) |
80 | { |
81 | // Texture/Buffer case |
82 | const int type = variant.userType(); |
83 | |
84 | if (type == qNodeIdTypeId) |
85 | return UniformValue(variant.value<Qt3DCore::QNodeId>()); |
86 | |
87 | if (type == qMatrix4x4TypeId) |
88 | return UniformValue(variant.value<Matrix4x4>()); |
89 | |
90 | if (type == qVector3DTypeId) |
91 | return UniformValue(variant.value<Vector3D>()); |
92 | |
93 | if (type == qVector4DTypeId) |
94 | return UniformValue(variant.value<Vector4D>()); |
95 | |
96 | UniformValue v; |
97 | switch (type) { |
98 | case QMetaType::Bool: |
99 | v.data<bool>()[0] = variant.toBool(); |
100 | break; |
101 | case QMetaType::Int: |
102 | case QMetaType::UInt: |
103 | case QMetaType::Long: |
104 | case QMetaType::LongLong: |
105 | case QMetaType::Short: |
106 | case QMetaType::ULong: |
107 | case QMetaType::ULongLong: |
108 | case QMetaType::UShort: |
109 | case QMetaType::Char: |
110 | case QMetaType::UChar: |
111 | v.data<int>()[0] = variant.toInt(); |
112 | v.m_storedType = Int; |
113 | break; |
114 | case QMetaType::Float: |
115 | case QMetaType::Double: // Convert double to floats |
116 | v.m_data[0] = variant.toFloat(); |
117 | break; |
118 | case QMetaType::QPoint: { |
119 | const QPoint p = variant.toPoint(); |
120 | v.data<int>()[0] = p.x(); |
121 | v.data<int>()[1] = p.y(); |
122 | break; |
123 | } |
124 | case QMetaType::QSize: { |
125 | const QSize s = variant.toSize(); |
126 | v.data<int>()[0] = s.width(); |
127 | v.data<int>()[1] = s.height(); |
128 | break; |
129 | } |
130 | case QMetaType::QRect: { |
131 | const QRect r = variant.toRect(); |
132 | v.data<int>()[0] = r.x(); |
133 | v.data<int>()[1] = r.y(); |
134 | v.data<int>()[2] = r.width(); |
135 | v.data<int>()[3] = r.height(); |
136 | break; |
137 | } |
138 | case QMetaType::QSizeF: { |
139 | const QSizeF s = variant.toSize(); |
140 | v.m_data[0] = s.width(); |
141 | v.m_data[1] = s.height(); |
142 | break; |
143 | } |
144 | case QMetaType::QPointF: { |
145 | const QPointF p = variant.toPointF(); |
146 | v.m_data[0] = p.x(); |
147 | v.m_data[1] = p.y(); |
148 | break; |
149 | } |
150 | case QMetaType::QRectF: { |
151 | const QRectF r = variant.toRect(); |
152 | v.m_data[0] = r.x(); |
153 | v.m_data[1] = r.y(); |
154 | v.m_data[2] = r.width(); |
155 | v.m_data[3] = r.height(); |
156 | break; |
157 | } |
158 | case QMetaType::QVector2D: { |
159 | const QVector2D vec2 = variant.value<QVector2D>(); |
160 | v.m_data[0] = vec2.x(); |
161 | v.m_data[1] = vec2.y(); |
162 | break; |
163 | } |
164 | case QMetaType::QVector3D: { |
165 | const QVector3D vec3 = variant.value<QVector3D>(); |
166 | v.m_data[0] = vec3.x(); |
167 | v.m_data[1] = vec3.y(); |
168 | v.m_data[2] = vec3.z(); |
169 | break; |
170 | } |
171 | case QMetaType::QVector4D: { |
172 | const QVector4D vec4 = variant.value<QVector4D>(); |
173 | v.m_data[0] = vec4.x(); |
174 | v.m_data[1] = vec4.y(); |
175 | v.m_data[2] = vec4.z(); |
176 | v.m_data[3] = vec4.w(); |
177 | break; |
178 | } |
179 | case QMetaType::QColor: { |
180 | const QColor col = variant.value<QColor>(); |
181 | v.m_data[0] = col.redF(); |
182 | v.m_data[1] = col.greenF(); |
183 | v.m_data[2] = col.blueF(); |
184 | v.m_data[3] = col.alphaF(); |
185 | break; |
186 | } |
187 | case QMetaType::QMatrix4x4: { |
188 | const QMatrix4x4 mat44 = variant.value<QMatrix4x4>(); |
189 | // Use constData because we want column-major layout |
190 | v.m_data.resize(sz: 16); |
191 | memcpy(dest: v.data<float>(), src: mat44.constData(), n: 16 * sizeof(float)); |
192 | break; |
193 | } |
194 | case QMetaType::QVariantList: { |
195 | const QVariantList variants = variant.toList(); |
196 | if (variants.size() < 1) |
197 | break; |
198 | |
199 | const int listEntryType = variants.first().userType(); |
200 | |
201 | // array of textures |
202 | if (listEntryType == qNodeIdTypeId) |
203 | v.m_valueType = NodeId; |
204 | |
205 | v.m_elementByteSize = byteSizeForMetaType(type: listEntryType); |
206 | const int stride = v.m_elementByteSize / sizeof(float); |
207 | |
208 | // Resize v.m_data |
209 | v.m_data.resize(sz: stride * variants.size()); |
210 | |
211 | int idx = 0; |
212 | for (const QVariant &variant : variants) { |
213 | Q_ASSERT_X(variant.userType() == listEntryType, |
214 | Q_FUNC_INFO, |
215 | "Uniform array doesn't contain elements of the same type" ); |
216 | UniformValue vi = UniformValue::fromVariant(variant); |
217 | memcpy(dest: v.data<float>() + idx, src: vi.data<float>(), n: stride * sizeof(float)); |
218 | idx += stride; |
219 | } |
220 | break; |
221 | } |
222 | |
223 | default: { |
224 | if (variant.userType() == qMetaTypeId<QMatrix3x3>()) { |
225 | const QMatrix3x3 mat33 = variant.value<QMatrix3x3>(); |
226 | // Use constData because we want column-major layout |
227 | v.m_data.resize(sz: 9); |
228 | memcpy(dest: v.data<float>(), src: mat33.constData(), n: 9 * sizeof(float)); |
229 | break; |
230 | } |
231 | if (variant.userType() == qMetaTypeId<Qt3DRender::QAbstractTexture *>()) { |
232 | // silently ignore null texture pointers as they are common while textures are loading |
233 | if (variant.value<Qt3DRender::QAbstractTexture *>() == nullptr) |
234 | break; |
235 | } |
236 | qWarning() << "Unknown uniform type or value:" << variant << "Please check your QParameters" ; |
237 | } |
238 | } |
239 | return v; |
240 | } |
241 | |
242 | template<> |
243 | void UniformValue::setData<QMatrix4x4>(const QVector<QMatrix4x4> &v) |
244 | { |
245 | m_data.resize(sz: 16 * v.size()); |
246 | m_valueType = ScalarValue; |
247 | int offset = 0; |
248 | const int byteSize = 16 * sizeof(float); |
249 | float *data = m_data.data(); |
250 | for (const auto &m : v) { |
251 | memcpy(dest: data + offset, src: m.constData(), n: byteSize); |
252 | offset += 16; |
253 | } |
254 | } |
255 | |
256 | } // namespace Render |
257 | } // namespace Qt3DRender |
258 | |
259 | QT_END_NAMESPACE |
260 | |