1// Copyright (C) 2014 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#ifndef QT3DRENDER_RENDER_OPENGL_QGRAPHICSUTILS_P_H
5#define QT3DRENDER_RENDER_OPENGL_QGRAPHICSUTILS_P_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 for the convenience
12// of other Qt classes. 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 <Qt3DRender/qt3drender_global.h>
19#include <QMatrix2x2>
20#include <QMatrix3x3>
21#include <QMatrix4x4>
22#include <QGenericMatrix>
23#include <QVector2D>
24#include <QVarLengthArray>
25#include <QColor>
26#include <shadervariables_p.h>
27
28QT_BEGIN_NAMESPACE
29
30namespace Qt3DRender {
31
32namespace Render {
33
34namespace OpenGL {
35
36namespace {
37
38const int QMatrix2x2Type = qMetaTypeId<QMatrix2x2>();
39const int QMatrix2x3Type = qMetaTypeId<QMatrix2x3>();
40const int QMatrix2x4Type = qMetaTypeId<QMatrix2x4>();
41const int QMatrix3x2Type = qMetaTypeId<QMatrix3x2>();
42const int QMatrix3x3Type = qMetaTypeId<QMatrix3x3>();
43const int QMatrix3x4Type = qMetaTypeId<QMatrix3x4>();
44const int QMatrix4x2Type = qMetaTypeId<QMatrix4x2>();
45const int QMatrix4x3Type = qMetaTypeId<QMatrix4x3>();
46
47}
48
49class QGraphicsUtils
50{
51
52public:
53
54 template<typename T>
55 static const char *bytesFromVariant(const QVariant &v)
56 {
57 uint byteSize = sizeof(T);
58 // Max 16 float that we may want as doubles
59 // 64 should be best for most cases
60 static QVarLengthArray<char, 64> array(16 * byteSize);
61 memset(s: array.data(), c: 0, n: array.size());
62
63 switch (v.metaType().id()) {
64 // 1 byte
65 case QMetaType::Bool: {
66 T data = v.value<bool>();
67 memcpy(array.data(), &data, byteSize);
68 break;
69 }
70 case QMetaType::Char: {
71 T data = v.value<char>();
72 memcpy(array.data(), &data, byteSize);
73 break;
74 }
75
76 // 4 bytes
77 case QMetaType::Float: {
78 T data = v.value<float>();
79 memcpy(array.data(), &data, byteSize);
80 break;
81 }
82 case QMetaType::Int: {
83 T data = v.value<int>();
84 memcpy(array.data(), &data, byteSize);
85 break;
86
87 }
88 case QMetaType::UInt: {
89 qDebug() << "UINT";
90 T data = v.value<uint>();
91 memcpy(array.data(), &data, byteSize);
92 break;
93 }
94
95 // 8 bytes
96 case QMetaType::Double: {
97 T data = v.value<double>();
98 memcpy(array.data(), &data, byteSize);
99 break;
100 }
101
102 // 2 floats
103 case QMetaType::QPointF: {
104 QPointF vv = v.value<QPointF>();
105 T data = vv.x();
106 memcpy(array.data(), &data, byteSize);
107 data = vv.y();
108 memcpy(array.data() + byteSize, &data, byteSize);
109 break;
110 }
111 case QMetaType::QSizeF: {
112 QSizeF vv = v.value<QSizeF>();
113 T data = vv.width();
114 memcpy(array.data(), &data, byteSize);
115 data = vv.height();
116 memcpy(array.data() + byteSize, &data, byteSize);
117 break;
118 }
119
120 case QMetaType::QVector2D: {
121 QVector2D vv = v.value<QVector2D>();
122 T data = vv.x();
123 memcpy(array.data(), &data, byteSize);
124 data = vv.y();
125 memcpy(array.data() + byteSize, &data, byteSize);
126 break;
127 }
128
129 // 2 ints
130 case QMetaType::QPoint: {
131 QPointF vv = v.value<QPoint>();
132 T data = vv.x();
133 memcpy(array.data(), &data, byteSize);
134 data = vv.y();
135 memcpy(array.data() + byteSize, &data, byteSize);
136 break;
137 }
138
139 case QMetaType::QSize: {
140 QSize vv = v.value<QSize>();
141 T data = vv.width();
142 memcpy(array.data(), &data, byteSize);
143 data = vv.height();
144 memcpy(array.data() + byteSize, &data, byteSize);
145 break;
146 }
147
148 // 3 floats
149 case QMetaType::QVector3D: {
150 QVector3D vv = v.value<QVector3D>();
151 T data = vv.x();
152 memcpy(array.data(), &data, byteSize);
153 data = vv.y();
154 memcpy(array.data() + byteSize, &data, byteSize);
155 data = vv.z();
156 memcpy(array.data() + 2 * byteSize, &data, byteSize);
157 break;
158 }
159
160 // 4 floats
161 case QMetaType::QVector4D: {
162 QVector4D vv = v.value<QVector4D>();
163 T data = vv.x();
164 memcpy(array.data(), &data, byteSize);
165 data = vv.y();
166 memcpy(array.data() + byteSize, &data, byteSize);
167 data = vv.z();
168 memcpy(array.data() + 2 * byteSize, &data, byteSize);
169 data = vv.w();
170 memcpy(array.data() + 3 * byteSize, &data, byteSize);
171 break;
172 }
173
174 case QMetaType::QQuaternion: {
175
176 break;
177 }
178
179 case QMetaType::QRectF: {
180 QRectF vv = v.value<QRectF>();
181 T data = vv.x();
182 memcpy(array.data(), &data, byteSize);
183 data = vv.y();
184 memcpy(array.data() + byteSize, &data, byteSize);
185 data = vv.width();
186 memcpy(array.data() + 2 * byteSize, &data, byteSize);
187 data = vv.height();
188 memcpy(array.data() + 3 * byteSize, &data, byteSize);
189 break;
190 }
191
192 case QMetaType::QColor: {
193 QColor vv = v.value<QColor>();
194 T data = vv.redF();
195 memcpy(array.data(), &data, byteSize);
196 data = vv.greenF();
197 memcpy(array.data() + byteSize, &data, byteSize);
198 data = vv.blueF();
199 memcpy(array.data() + 2 * byteSize, &data, byteSize);
200 data = vv.alphaF();
201 memcpy(array.data() + 3 * byteSize, &data, byteSize);
202 break;
203 }
204
205 // 4 ints
206 case QMetaType::QRect: {
207 QRectF vv = v.value<QRect>();
208 T data = vv.x();
209 memcpy(array.data(), &data, byteSize);
210 data = vv.y();
211 memcpy(array.data() + byteSize, &data, byteSize);
212 data = vv.width();
213 memcpy(array.data() + 2 * byteSize, &data, byteSize);
214 data = vv.height();
215 memcpy(array.data() + 3 * byteSize, &data, byteSize);
216 break;
217 }
218
219 // 16 floats
220 case QMetaType::QMatrix4x4: {
221 QMatrix4x4 mat = v.value<QMatrix4x4>();
222 float *data = mat.data();
223 for (int i = 0; i < 16; i++) {
224 T d = data[i];
225 memcpy(array.data() + i * byteSize, &d, byteSize);
226 }
227 break;
228 }
229
230 default: {
231
232 float *data = nullptr;
233 if (v.userType() == QMatrix3x3Type) {
234 QMatrix3x3 mat = v.value<QMatrix3x3>();
235 data = mat.data();
236 for (int i = 0; i < 9; i++) {
237 T d = data[i];
238 memcpy(array.data() + i * byteSize, &d, byteSize);
239 }
240 }
241 else if (v.userType() == QMatrix2x2Type) {
242 QMatrix2x2 mat = v.value<QMatrix2x2>();
243 data = mat.data();
244 for (int i = 0; i < 4; i++) {
245 T d = data[i];
246 memcpy(array.data() + i * byteSize, &d, byteSize);
247 }
248 }
249 else if (v.userType() == QMatrix2x3Type) {
250 QMatrix2x3 mat = v.value<QMatrix2x3>();
251 data = mat.data();
252 for (int i = 0; i < 6; i++) {
253 T d = data[i];
254 memcpy(array.data() + i * byteSize, &d, byteSize);
255 }
256 }
257 else if (v.userType() == QMatrix3x2Type) {
258 QMatrix3x2 mat = v.value<QMatrix3x2>();
259 data = mat.data();
260 for (int i = 0; i < 6; i++) {
261 T d = data[i];
262 memcpy(array.data() + i * byteSize, &d, byteSize);
263 }
264 }
265 else if (v.userType() == QMatrix2x4Type) {
266 QMatrix2x4 mat = v.value<QMatrix2x4>();
267 data = mat.data();
268 for (int i = 0; i < 8; i++) {
269 T d = data[i];
270 memcpy(array.data() + i * byteSize, &d, byteSize);
271 }
272 }
273 else if (v.userType() == QMatrix4x2Type) {
274 QMatrix4x2 mat = v.value<QMatrix4x2>();
275 data = mat.data();
276 for (int i = 0; i < 8; i++) {
277 T d = data[i];
278 memcpy(array.data() + i * byteSize, &d, byteSize);
279 }
280 }
281 else if (v.userType() == QMatrix3x4Type) {
282 QMatrix3x4 mat = v.value<QMatrix3x4>();
283 data = mat.data();
284 for (int i = 0; i < 12; i++) {
285 T d = data[i];
286 memcpy(array.data() + i * byteSize, &d, byteSize);
287 }
288 }
289 else if (v.userType() == QMatrix4x3Type) {
290 QMatrix4x3 mat = v.value<QMatrix4x3>();
291 data = mat.data();
292 for (int i = 0; i < 12; i++) {
293 T d = data[i];
294 memcpy(array.data() + i * byteSize, &d, byteSize);
295 }
296 }
297 else
298 qWarning() << Q_FUNC_INFO << "QVariant type conversion not handled for " << v.metaType().id();
299 break;
300 }
301
302 }
303 return array.constData();
304 }
305
306
307 template<typename T>
308 static const T *valueArrayFromVariant(const QVariant &v, int count, int tupleSize)
309 {
310 uint byteSize = sizeof(T);
311 uint offset = byteSize * tupleSize;
312 static QVarLengthArray<char, 1024> uniformValuesArray(1024);
313 uniformValuesArray.resize(sz: count * offset);
314 char *data = uniformValuesArray.data();
315 memset(s: data, c: 0, n: uniformValuesArray.size());
316
317 QVariantList vList = v.toList();
318 // Handles list of QVariant: usually arrays of float
319 if (!vList.isEmpty()) {
320 for (int i = 0; i < vList.size() && uint(i) * offset < uint(uniformValuesArray.size()); i++) {
321 const char *subBuffer = QGraphicsUtils::bytesFromVariant<T>(vList.at(i));
322 memcpy(dest: data + i * offset, src: subBuffer, n: offset);
323 }
324 }
325 else {
326 memcpy(data, QGraphicsUtils::bytesFromVariant<T>(v), offset);
327 }
328 return reinterpret_cast<const T *>(uniformValuesArray.constData());
329 }
330
331 template<typename T>
332 static void fillDataArray(void *buffer, const T *data, const ShaderUniform &description, int tupleSize)
333 {
334 uint offset = description.m_offset / sizeof(T);
335 uint stride = description.m_arrayStride / sizeof(T);
336 T *bufferData = (T*)buffer;
337
338 for (int i = 0; i < description.m_size; ++i) {
339 for (int j = 0; j < tupleSize; j++) {
340 int idx = i * tupleSize + j;
341 bufferData[offset + j] = data[idx];
342 }
343 offset += stride;
344 }
345 }
346
347 template<typename T>
348 static void fillDataMatrixArray(void *buffer, const T *data, const ShaderUniform &description, int cols, int rows)
349 {
350 uint offset = description.m_offset / sizeof(T);
351 uint arrayStride = description.m_arrayStride / sizeof(T);
352 uint matrixStride = description.m_matrixStride / sizeof(T);
353 T *bufferData = (T*)buffer;
354
355 for (int i = 0; i < description.m_size; ++i) {
356 for (int col = 0; col < cols; ++col) {
357 for (int row = 0; row < rows; ++row) {
358 int idx = i * cols * rows + rows * col + row;
359 bufferData[offset + row] = data[idx];
360 }
361 offset += matrixStride;
362 }
363 offset += arrayStride;
364 }
365 }
366
367};
368
369} // namespace OpenGL
370
371} // namespace Render
372
373} // namespace Qt3DRender
374
375QT_END_NAMESPACE
376
377#endif // QT3DRENDER_RENDER_OPENGL_QGRAPHICSUTILS_P_H
378

source code of qt3d/src/plugins/renderers/opengl/graphicshelpers/qgraphicsutils_p.h