// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "customgeometry.h" #include #include #include //struct Vertex { // QVector3D position; //// qint32 joints[4]; //// float weights[4]; // float pad; //}; //static const int s_vertexSize = sizeof(Vertex); //Q_STATIC_ASSERT(s_vertexSize == 16); CustomGeometry::CustomGeometry(QQuick3DObject *parent) : QQuick3DGeometry(parent) { addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0, QQuick3DGeometry::Attribute::ComponentType::F32Type); addAttribute(QQuick3DGeometry::Attribute::IndexSemantic, 0, QQuick3DGeometry::Attribute::ComponentType::U32Type); addAttribute(QQuick3DGeometry::Attribute::ColorSemantic, 3 * sizeof(float), QQuick3DGeometry::Attribute::ComponentType::F32Type); // addAttribute(QQuick3DGeometry::Attribute::JointSemantic, offsetof(Vertex, joints[0]), // QQuick3DGeometry::Attribute::ComponentType::I32Type); // addAttribute(QQuick3DGeometry::Attribute::WeightSemantic, offsetof(Vertex, weights[0]), // QQuick3DGeometry::Attribute::ComponentType::F32Type); } QList CustomGeometry::positions() const { return m_positions; } QList CustomGeometry::joints() const { return m_joints; } QList CustomGeometry::weights() const { return m_weights; } QList CustomGeometry::indexes() const { return m_indexes; } void CustomGeometry::setPositions(const QList &positions) { if (positions == m_positions) return; m_positions = positions; emit positionsChanged(); m_vertexDirty = true; } void CustomGeometry::setJoints(const QList &joints) { if (joints == m_joints) return; m_joints = joints; emit jointsChanged(); m_vertexDirty = true; } void CustomGeometry::setWeights(const QList &weights) { if (weights == m_weights) return; m_weights = weights; emit weightsChanged(); m_vertexDirty = true; } void CustomGeometry::setIndexes(const QList &indexes) { if (indexes == m_indexes) return; m_indexes = indexes; emit indexesChanged(); m_indexDirty = true; } #if 0 QVector3D cubeVertices[8] = { QVector3D(-1, -1, -1), QVector3D(1, -1, -1), QVector3D(1, 1, -1), QVector3D(-1, 1, -1), QVector3D(-1, -1, 1), QVector3D(1, -1, 1), QVector3D(1, 1, 1), QVector3D(-1, 1, 1) }; int cubeIndices[6 * 6] = { 0, 1, 3, 3, 1, 2, 1, 5, 2, 2, 5, 6, 5, 4, 6, 6, 4, 7, 4, 0, 7, 7, 0, 3, 3, 2, 7, 7, 2, 6, 4, 5, 0, 0, 5, 1 }; constexpr int vertsPerCube = 8; constexpr int trianglesPerCube = 6*2; #else QVector3D cubeVertices[6] = { QVector3D(0, -1, 0), QVector3D(-1, 0, -1), QVector3D(-1, 0, 1), QVector3D(1, 0, 1), QVector3D(1, 0, -1), QVector3D(0, 1, 0) }; constexpr int vertsPerCube = 6; constexpr int trianglesPerCube = 8; int cubeIndices[trianglesPerCube*3] = { 0,4,1, 0,3,4, 0,2,3, 0,1,2, 5,1,4, 5,4,3, 5,3,2, 5,2,1 }; #endif constexpr int numCubes = 1; constexpr int floatsPerVert = 8; constexpr qsizetype vertexBufferSizeInBytes = numCubes * vertsPerCube * floatsPerVert * sizeof(float); constexpr qsizetype indexBufferSizeInBytes = numCubes * sizeof(cubeIndices); QSSGRenderGraphObject *CustomGeometry::updateSpatialNode(QSSGRenderGraphObject *node) { #if 1 if (m_vertexDirty) { QByteArray iBuffer; iBuffer.resize(indexBufferSizeInBytes); QByteArray vBuffer; vBuffer.resize(vertexBufferSizeInBytes); vBuffer.fill(0); int *iData = reinterpret_cast(iBuffer.data()); float *vData = reinterpret_cast(vBuffer.data()); QRandomGenerator *rgen = QRandomGenerator::global(); for (int c = 0; c < numCubes; ++c) { auto rand = [rgen]() {return rgen->bounded(10000)/50.0 - 100; }; QColor cubeColor(rgen->bounded(255), rgen->bounded(255), rgen->bounded(255)); QVector3D offs = numCubes == 1 ? QVector3D{} : QVector3D(2*rand(), rand(), 2*rand()); float scale = numCubes == 1 ? 1.0 : rgen->bounded(100)/100.0; scale = scale * 10; //scale = scale/3.0; //............. for (int i = 0; i < vertsPerCube; ++i) { int idx = i * floatsPerVert + c * vertsPerCube * floatsPerVert; QVector3D vertex = cubeVertices[i] * scale * -1 + offs; // our polygons' faces are oriented wrong //qDebug() << "cube" << c << "vert" << i << vertex; vData[idx] = vertex.x(); vData[idx+1] = vertex.y(); vData[idx+2] = vertex.z(); vData[idx+3] = cubeColor.redF(); vData[idx+4] = cubeColor.greenF(); vData[idx+5] = cubeColor.blueF(); vData[idx+6] = 1.0; } //qDebug() << "iData" << indexBufferSizeInBytes << iBuffer.size(); constexpr int idxPerCube = trianglesPerCube * 3; for (int i = 0; i < trianglesPerCube*3; ++i) { //qDebug() << "trying:" << QString::number(i) << i + c*idxpercube << "of" << indexBufferSizeInBytes/sizeof(float); iData[i + c * idxPerCube] = cubeIndices[i] + c * vertsPerCube; } } setStride(floatsPerVert * sizeof(float)); setVertexData(vBuffer); setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles); setIndexData(iBuffer); m_vertexDirty = false; } #else if (m_vertexDirty) { m_vertexDirty = false; const int numVertexes = m_positions.size(); m_vertexBuffer.resize(numVertexes * s_vertexSize); Vertex *vert = reinterpret_cast(m_vertexBuffer.data()); for (int i = 0; i < numVertexes; ++i) { Vertex &v = vert[i]; v.position = m_positions[i]; } setStride(s_vertexSize); setVertexData(m_vertexBuffer); setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles); } if (m_indexDirty) { m_indexDirty = false; m_indexBuffer = QByteArray(reinterpret_cast(m_indexes.data()), m_indexes.size() * sizeof(quint32)); setIndexData(m_indexBuffer); } #endif node = QQuick3DGeometry::updateSpatialNode(node); return node; }