/**************************************************************************** ** ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt3D module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPLv3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or later as published by the Free ** Software Foundation and appearing in the file LICENSE.GPL included in ** the packaging of this file. Please review the following information to ** ensure the GNU General Public License version 2.0 requirements will be ** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include class tst_QGraphicsUtils : public QObject { Q_OBJECT private slots: void fillScalarInDataArray(); void fillArray(); void fillScalarWithOffsets(); void fillMatrix4x4(); void fillMatrix3x4(); void fillMatrix4x3(); void fillMatrixArray(); }; void tst_QGraphicsUtils::fillScalarInDataArray() { Qt3DRender::Render::ShaderUniform description; description.m_size = 1; description.m_offset = 0; description.m_arrayStride = 10; QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(testVector, 1, 4); for (int i = 0; i < 4; i++) { if (i == 0) QVERIFY(vectorData[i] == testVector.x()); else if (i == 1) QVERIFY(vectorData[i] == testVector.y()); else if (i == 2) QVERIFY(vectorData[i] == testVector.z()); else if (i == 3) QVERIFY(vectorData[i] == testVector.w()); } QByteArray data(description.m_size * 4 * sizeof(GLfloat), 0); char *innerData = data.data(); // Checked that we are not overflowing Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 2); for (int i = 0; i < 4; ++i) { if (i < 2) QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); else QVERIFY(((GLfloat*)innerData)[i] == 0.0f); } // Check that all values are copied Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); for (int i = 0; i < 4; ++i) QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); // check that offsetting works description.m_offset = 16; data = QByteArray(description.m_size * 8 * sizeof(GLfloat), 0); innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); for (int i = 0; i < 8; ++i) { if (i < 4) QVERIFY(((GLfloat*)innerData)[i] == 0.0f); else QVERIFY(vectorData[i - 4] == ((GLfloat*)innerData)[i]); } } void tst_QGraphicsUtils::fillArray() { QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); QVector4D testVector2(3.0f, 5.0f, 0.0f, 7.0f); QVector4D testVector3(4.0f, 5.0f, 4.0f, 2.0f); QVariantList variantList = QVariantList() << testVector << testVector2 << testVector3; const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant(variantList), 3, 4); Qt3DRender::Render::ShaderUniform description; description.m_size = 3; description.m_offset = 16; description.m_arrayStride = 16; QByteArray data(description.m_size * (4 + description.m_arrayStride) * sizeof(GLfloat) + description.m_offset, 0); char *innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); int offset = description.m_offset / sizeof(GLfloat); int stride = description.m_arrayStride / sizeof(GLfloat); GLfloat *innerDataFloat = (GLfloat*)innerData; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 4; ++j) { int idx = i * 4 + j; QVERIFY(innerDataFloat[offset + j] == vectorData[idx]); } offset += stride; } } void tst_QGraphicsUtils::fillScalarWithOffsets() { // Simulates Uniform Block // uniform Block { // vec3 position; // Offset 0 - 12 bytes // vec3 direction; // Offset 16 - 12 bytes // vec4 color; // Offset 32 - 16 bytes // float intensity; // Offset 48 - bytes // } // total size 64 bytes QVector3D position(8.0f, 8.0f, 3.0f); QVector3D direction(3.0f, 5.0f, 2.0f); QVector4D color(4.0f, 5.0f, 4.0f, 1.0f); float intensity = 1.0f; Qt3DRender::Render::ShaderUniform posUniform; posUniform.m_size = 1; posUniform.m_arrayStride = 0; posUniform.m_matrixStride = 0; posUniform.m_offset = 0; Qt3DRender::Render::ShaderUniform dirUniform; dirUniform.m_size = 1; dirUniform.m_arrayStride = 0; dirUniform.m_matrixStride = 0; dirUniform.m_offset = 16; Qt3DRender::Render::ShaderUniform colUniform; colUniform.m_size = 1; colUniform.m_arrayStride = 0; colUniform.m_matrixStride = 0; colUniform.m_offset = 32; Qt3DRender::Render::ShaderUniform intUniform; intUniform.m_size = 1; intUniform.m_arrayStride = 0; intUniform.m_matrixStride = 0; intUniform.m_offset = 48; QVector data(16); void *innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(position, 1, 3), posUniform, 3); Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(direction, 1, 3), dirUniform, 3); Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(color, 1, 4), colUniform, 4); Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(intensity, 1, 1), intUniform, 1); GLfloat *floatData = (GLfloat*)innerData; // Check first 16 bytes - position QVERIFY(floatData[0] == position.x()); QVERIFY(floatData[1] == position.y()); QVERIFY(floatData[2] == position.z()); QVERIFY(floatData[3] == 0.0f); // Check 16 - 32 bytes - direction QVERIFY(floatData[4] == direction.x()); QVERIFY(floatData[5] == direction.y()); QVERIFY(floatData[6] == direction.z()); QVERIFY(floatData[7] == 0.0f); // Check 32 - 48 bytes - color QVERIFY(floatData[8] == color.x()); QVERIFY(floatData[9] == color.y()); QVERIFY(floatData[10] == color.z()); QVERIFY(floatData[11] == color.w()); // Check 48 - 64 bytes - intensity QVERIFY(floatData[12] == intensity); QVERIFY(floatData[13] == 0.0f); QVERIFY(floatData[14] == 0.0f); QVERIFY(floatData[15] == 0.0f); } void tst_QGraphicsUtils::fillMatrix4x4() { // row major 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); // column major const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(mat, 1, 16); Qt3DRender::Render::ShaderUniform description; description.m_size = 1; description.m_offset = 0; description.m_arrayStride = 0; description.m_matrixStride = 16; QByteArray data(description.m_size * 16 * sizeof(GLfloat), 0); char *innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); // Check for no offset/no stride for (int i = 0; i < 16; ++i) QVERIFY((((GLfloat *)innerData)[i]) == matData[i]); description.m_offset = 12; data = QByteArray((description.m_size * 16 + description.m_offset) * sizeof(GLfloat), 0); innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); // Check with 12 offset/no stride for (int i = 0; i < 16; ++i) QVERIFY((((GLfloat *)innerData)[3 + i]) == matData[i]); description.m_matrixStride = 16; data = QByteArray((description.m_size * 16 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); // Check with 10 offset/ 16 stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); for (int col = 0; col < 4; ++col) { for (int row = 0; row < 4; ++row) QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]); offset += matrixStride; } } void tst_QGraphicsUtils::fillMatrix3x4() { QMatrix3x4 mat; mat.fill(6.0f); const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); Qt3DRender::Render::ShaderUniform description; description.m_size = 1; description.m_offset = 16; description.m_arrayStride = 0; description.m_matrixStride = 12; QByteArray data((description.m_size * 12 + 3 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); char *innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 3, 4); // Check with 16 offset/ 12 stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); for (int col = 0; col < 3; ++col) { for (int row = 0; row < 4; ++row) QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]); offset += matrixStride; } } void tst_QGraphicsUtils::fillMatrix4x3() { QMatrix4x3 mat; mat.fill(6.0f); const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); Qt3DRender::Render::ShaderUniform description; description.m_size = 1; description.m_offset = 16; description.m_arrayStride = 0; description.m_matrixStride = 16; QByteArray data((description.m_size * 12 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); char *innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); // Check with 16 offset/ 16 stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); for (int col = 0; col < 4; ++col) { for (int row = 0; row < 3; ++row) QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 3 + row]); offset += matrixStride; } } void tst_QGraphicsUtils::fillMatrixArray() { QMatrix4x3 mat1; QMatrix4x3 mat2; QMatrix4x3 mat3; mat1.fill(6.0f); mat2.fill(2.0f); mat3.fill(7.0f); QVariantList matrices = QVariantList() << QVariant::fromValue(mat1) << QVariant::fromValue(mat2) << QVariant::fromValue(mat3); const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(matrices), 3, 12); Qt3DRender::Render::ShaderUniform description; description.m_size = 3; description.m_offset = 12; description.m_arrayStride = 4; description.m_matrixStride = 16; QByteArray data((description.m_size * (12 + 4 * description.m_matrixStride + description.m_arrayStride) + description.m_offset) * sizeof(GLfloat), 0); char *innerData = data.data(); Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); // Check with 12 offset/ 4 array stride / 16 matrix stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); int arrayStride = description.m_arrayStride / sizeof(GLfloat); for (int i = 0; i < 3; ++i) { for (int col = 0; col < 4; ++col) { for (int row = 0; row < 3; ++row) { int idx = i * 4 * 3 + col * 3 + row; QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[idx]); } offset += matrixStride; } offset += arrayStride; } } QTEST_APPLESS_MAIN(tst_QGraphicsUtils) #include "tst_qgraphicsutils.moc"