1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <qgraphicsutils_p.h>
31
32class tst_QGraphicsUtils : public QObject
33{
34 Q_OBJECT
35private slots:
36 void fillScalarInDataArray();
37 void fillArray();
38 void fillScalarWithOffsets();
39 void fillMatrix4x4();
40 void fillMatrix3x4();
41 void fillMatrix4x3();
42 void fillMatrixArray();
43};
44
45void tst_QGraphicsUtils::fillScalarInDataArray()
46{
47 Qt3DRender::Render::OpenGL::ShaderUniform description;
48
49 description.m_size = 1;
50 description.m_offset = 0;
51 description.m_arrayStride = 10;
52
53 QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f);
54 const GLfloat *vectorData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: testVector, count: 1, tupleSize: 4);
55
56 for (int i = 0; i < 4; i++) {
57 if (i == 0)
58 QVERIFY(vectorData[i] == testVector.x());
59 else if (i == 1)
60 QVERIFY(vectorData[i] == testVector.y());
61 else if (i == 2)
62 QVERIFY(vectorData[i] == testVector.z());
63 else if (i == 3)
64 QVERIFY(vectorData[i] == testVector.w());
65 }
66
67 QByteArray data(description.m_size * 4 * sizeof(GLfloat), 0);
68 char *innerData = data.data();
69
70 // Checked that we are not overflowing
71 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData, data: vectorData, description, tupleSize: 2);
72 for (int i = 0; i < 4; ++i) {
73 if (i < 2)
74 QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]);
75 else
76 QVERIFY(((GLfloat*)innerData)[i] == 0.0f);
77 }
78
79 // Check that all values are copied
80 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData, data: vectorData, description, tupleSize: 4);
81 for (int i = 0; i < 4; ++i)
82 QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]);
83
84 // check that offsetting works
85 description.m_offset = 16;
86 data = QByteArray(description.m_size * 8 * sizeof(GLfloat), 0);
87 innerData = data.data();
88
89 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData, data: vectorData, description, tupleSize: 4);
90 for (int i = 0; i < 8; ++i) {
91 if (i < 4)
92 QVERIFY(((GLfloat*)innerData)[i] == 0.0f);
93 else
94 QVERIFY(vectorData[i - 4] == ((GLfloat*)innerData)[i]);
95 }
96}
97
98void tst_QGraphicsUtils::fillArray()
99{
100 QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f);
101 QVector4D testVector2(3.0f, 5.0f, 0.0f, 7.0f);
102 QVector4D testVector3(4.0f, 5.0f, 4.0f, 2.0f);
103
104 QVariantList variantList = QVariantList() << testVector << testVector2 << testVector3;
105 const GLfloat *vectorData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: QVariant(variantList), count: 3, tupleSize: 4);
106
107 Qt3DRender::Render::OpenGL::ShaderUniform description;
108
109 description.m_size = 3;
110 description.m_offset = 16;
111 description.m_arrayStride = 16;
112
113 QByteArray data(description.m_size * (4 + description.m_arrayStride) * sizeof(GLfloat) + description.m_offset, 0);
114 char *innerData = data.data();
115 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData, data: vectorData, description, tupleSize: 4);
116
117 int offset = description.m_offset / sizeof(GLfloat);
118 int stride = description.m_arrayStride / sizeof(GLfloat);
119
120 GLfloat *innerDataFloat = (GLfloat*)innerData;
121
122 for (int i = 0; i < 3; ++i) {
123 for (int j = 0; j < 4; ++j) {
124 int idx = i * 4 + j;
125 QVERIFY(innerDataFloat[offset + j] == vectorData[idx]);
126 }
127 offset += stride;
128 }
129}
130
131void tst_QGraphicsUtils::fillScalarWithOffsets()
132{
133 // Simulates Uniform Block
134
135 // uniform Block {
136 // vec3 position; // Offset 0 - 12 bytes
137 // vec3 direction; // Offset 16 - 12 bytes
138 // vec4 color; // Offset 32 - 16 bytes
139 // float intensity; // Offset 48 - bytes
140 // } // total size 64 bytes
141
142 QVector3D position(8.0f, 8.0f, 3.0f);
143 QVector3D direction(3.0f, 5.0f, 2.0f);
144 QVector4D color(4.0f, 5.0f, 4.0f, 1.0f);
145 float intensity = 1.0f;
146
147 Qt3DRender::Render::OpenGL::ShaderUniform posUniform;
148 posUniform.m_size = 1;
149 posUniform.m_arrayStride = 0;
150 posUniform.m_matrixStride = 0;
151 posUniform.m_offset = 0;
152
153 Qt3DRender::Render::OpenGL::ShaderUniform dirUniform;
154 dirUniform.m_size = 1;
155 dirUniform.m_arrayStride = 0;
156 dirUniform.m_matrixStride = 0;
157 dirUniform.m_offset = 16;
158
159 Qt3DRender::Render::OpenGL::ShaderUniform colUniform;
160 colUniform.m_size = 1;
161 colUniform.m_arrayStride = 0;
162 colUniform.m_matrixStride = 0;
163 colUniform.m_offset = 32;
164
165 Qt3DRender::Render::OpenGL::ShaderUniform intUniform;
166 intUniform.m_size = 1;
167 intUniform.m_arrayStride = 0;
168 intUniform.m_matrixStride = 0;
169 intUniform.m_offset = 48;
170
171 QVector<GLfloat> data(16);
172 void *innerData = data.data();
173
174 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData,
175 data: Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: position, count: 1, tupleSize: 3),
176 description: posUniform, tupleSize: 3);
177 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData,
178 data: Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: direction, count: 1, tupleSize: 3),
179 description: dirUniform, tupleSize: 3);
180 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData,
181 data: Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: color, count: 1, tupleSize: 4),
182 description: colUniform, tupleSize: 4);
183 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(buffer: innerData,
184 data: Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: intensity, count: 1, tupleSize: 1),
185 description: intUniform, tupleSize: 1);
186
187 GLfloat *floatData = (GLfloat*)innerData;
188
189 // Check first 16 bytes - position
190 QVERIFY(floatData[0] == position.x());
191 QVERIFY(floatData[1] == position.y());
192 QVERIFY(floatData[2] == position.z());
193 QVERIFY(floatData[3] == 0.0f);
194 // Check 16 - 32 bytes - direction
195 QVERIFY(floatData[4] == direction.x());
196 QVERIFY(floatData[5] == direction.y());
197 QVERIFY(floatData[6] == direction.z());
198 QVERIFY(floatData[7] == 0.0f);
199 // Check 32 - 48 bytes - color
200 QVERIFY(floatData[8] == color.x());
201 QVERIFY(floatData[9] == color.y());
202 QVERIFY(floatData[10] == color.z());
203 QVERIFY(floatData[11] == color.w());
204 // Check 48 - 64 bytes - intensity
205 QVERIFY(floatData[12] == intensity);
206 QVERIFY(floatData[13] == 0.0f);
207 QVERIFY(floatData[14] == 0.0f);
208 QVERIFY(floatData[15] == 0.0f);
209}
210
211void tst_QGraphicsUtils::fillMatrix4x4()
212{
213 // row major
214 QMatrix4x4 mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f);
215
216 // column major
217 const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: mat, count: 1, tupleSize: 16);
218
219 Qt3DRender::Render::OpenGL::ShaderUniform description;
220
221 description.m_size = 1;
222 description.m_offset = 0;
223 description.m_arrayStride = 0;
224 description.m_matrixStride = 16;
225
226
227 QByteArray data(description.m_size * 16 * sizeof(GLfloat), 0);
228 char *innerData = data.data();
229 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(buffer: innerData, data: matData, description, cols: 4, rows: 4);
230 // Check for no offset/no stride
231 for (int i = 0; i < 16; ++i)
232 QVERIFY((((GLfloat *)innerData)[i]) == matData[i]);
233
234 description.m_offset = 12;
235 data = QByteArray((description.m_size * 16 + description.m_offset) * sizeof(GLfloat), 0);
236 innerData = data.data();
237 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(buffer: innerData, data: matData, description, cols: 4, rows: 4);
238 // Check with 12 offset/no stride
239 for (int i = 0; i < 16; ++i)
240 QVERIFY((((GLfloat *)innerData)[3 + i]) == matData[i]);
241
242 description.m_matrixStride = 16;
243 data = QByteArray((description.m_size * 16 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0);
244 innerData = data.data();
245 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(buffer: innerData, data: matData, description, cols: 4, rows: 4);
246 // Check with 10 offset/ 16 stride
247 int offset = description.m_offset / sizeof(GLfloat);
248 int matrixStride = description.m_matrixStride / sizeof(GLfloat);
249
250 for (int col = 0; col < 4; ++col) {
251 for (int row = 0; row < 4; ++row)
252 QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]);
253 offset += matrixStride;
254 }
255}
256
257void tst_QGraphicsUtils::fillMatrix3x4()
258{
259 QMatrix3x4 mat;
260
261 mat.fill(value: 6.0f);
262 const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: QVariant::fromValue(value: mat), count: 1, tupleSize: 12);
263
264 Qt3DRender::Render::OpenGL::ShaderUniform description;
265
266 description.m_size = 1;
267 description.m_offset = 16;
268 description.m_arrayStride = 0;
269 description.m_matrixStride = 12;
270
271 QByteArray data((description.m_size * 12 + 3 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0);
272 char *innerData = data.data();
273 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(buffer: innerData, data: matData, description, cols: 3, rows: 4);
274 // Check with 16 offset/ 12 stride
275 int offset = description.m_offset / sizeof(GLfloat);
276 int matrixStride = description.m_matrixStride / sizeof(GLfloat);
277
278 for (int col = 0; col < 3; ++col) {
279 for (int row = 0; row < 4; ++row)
280 QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]);
281 offset += matrixStride;
282 }
283}
284
285void tst_QGraphicsUtils::fillMatrix4x3()
286{
287 QMatrix4x3 mat;
288
289 mat.fill(value: 6.0f);
290 const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: QVariant::fromValue(value: mat), count: 1, tupleSize: 12);
291
292 Qt3DRender::Render::OpenGL::ShaderUniform description;
293
294 description.m_size = 1;
295 description.m_offset = 16;
296 description.m_arrayStride = 0;
297 description.m_matrixStride = 16;
298
299 QByteArray data((description.m_size * 12 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0);
300 char *innerData = data.data();
301 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(buffer: innerData, data: matData, description, cols: 4, rows: 3);
302 // Check with 16 offset/ 16 stride
303 int offset = description.m_offset / sizeof(GLfloat);
304 int matrixStride = description.m_matrixStride / sizeof(GLfloat);
305
306 for (int col = 0; col < 4; ++col) {
307 for (int row = 0; row < 3; ++row)
308 QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 3 + row]);
309 offset += matrixStride;
310 }
311}
312
313void tst_QGraphicsUtils::fillMatrixArray()
314{
315 QMatrix4x3 mat1;
316 QMatrix4x3 mat2;
317 QMatrix4x3 mat3;
318 mat1.fill(value: 6.0f);
319 mat2.fill(value: 2.0f);
320 mat3.fill(value: 7.0f);
321
322 QVariantList matrices = QVariantList() << QVariant::fromValue(value: mat1) << QVariant::fromValue(value: mat2) << QVariant::fromValue(value: mat3);
323
324 const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant<GLfloat>(v: QVariant::fromValue(value: matrices), count: 3, tupleSize: 12);
325
326 Qt3DRender::Render::OpenGL::ShaderUniform description;
327
328 description.m_size = 3;
329 description.m_offset = 12;
330 description.m_arrayStride = 4;
331 description.m_matrixStride = 16;
332
333 QByteArray data((description.m_size * (12 + 4 * description.m_matrixStride + description.m_arrayStride) + description.m_offset) * sizeof(GLfloat), 0);
334 char *innerData = data.data();
335 Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(buffer: innerData, data: matData, description, cols: 4, rows: 3);
336 // Check with 12 offset/ 4 array stride / 16 matrix stride
337 int offset = description.m_offset / sizeof(GLfloat);
338 int matrixStride = description.m_matrixStride / sizeof(GLfloat);
339 int arrayStride = description.m_arrayStride / sizeof(GLfloat);
340
341 for (int i = 0; i < 3; ++i) {
342 for (int col = 0; col < 4; ++col) {
343 for (int row = 0; row < 3; ++row) {
344 int idx = i * 4 * 3 + col * 3 + row;
345 QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[idx]);
346 }
347 offset += matrixStride;
348 }
349 offset += arrayStride;
350 }
351}
352
353QTEST_APPLESS_MAIN(tst_QGraphicsUtils)
354
355#include "tst_qgraphicsutils.moc"
356

source code of qt3d/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp