// Copyright (C) 2019 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "gridgeometry_p.h" #include /*! \qmltype GridGeometry \inqmlmodule QtQuick3D.Helpers \inherits Geometry \brief A custom geometry provider for rendering grids. This helper implements grid geometry, which allows showing a grid in a scene. For example, the following snippet would display a grid with 19 cells in both directions in a scene that has one light. Without further transformations, the grid is facing the camera by default. \image gridgeometry.jpg \badcode View3D { anchors.fill: parent camera: camera PerspectiveCamera { id: camera position: Qt.vector3d(0, 0, 600) } DirectionalLight { position: Qt.vector3d(-500, 500, -100) color: Qt.rgba(0.4, 0.2, 0.6, 1.0) ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0) } Model { scale: Qt.vector3d(100, 100, 100) geometry: GridGeometry { horizontalLines: 20 verticalLines: 20 } materials: [ DefaultMaterial { } ] } } \endcode \sa {Qt Quick 3D - Custom Geometry Example}, Model */ /*! \qmlproperty int GridGeometry::horizontalLines Specifies the number of horizontal lines in a grid. The default value is 1000. */ /*! \qmlproperty int GridGeometry::verticalLines Specifies the number of vertical lines in a grid. The default value is 1000. */ /*! \qmlproperty real GridGeometry::horizontalStep Specifies the spacing between horizontal lines. The default value is 0.1. */ /*! \qmlproperty real GridGeometry::verticalStep Specifies the spacing between vertical lines. The default value is 0.1. */ GridGeometry::GridGeometry() : QQuick3DGeometry() { updateData(); } GridGeometry::~GridGeometry() { } int GridGeometry::horizontalLines() const { return m_horLines; } int GridGeometry::verticalLines() const { return m_vertLines; } float GridGeometry::horizontalStep() const { return m_horStep; } float GridGeometry::verticalStep() const { return m_vertStep; } void GridGeometry::setHorizontalLines(int count) { count = qMax(count, 1); if (m_horLines == count) return; m_horLines = qMax(count, 1); emit horizontalLinesChanged(); updateData(); update(); } void GridGeometry::setVerticalLines(int count) { count = qMax(count, 1); if (m_vertLines == count) return; m_vertLines = qMax(count, 1); emit verticalLinesChanged(); updateData(); update(); } void GridGeometry::setHorizontalStep(float step) { step = qMax(step, 0.0f); if (qFuzzyCompare(m_horStep, step)) return; m_horStep = step; emit horizontalStepChanged(); updateData(); update(); } void GridGeometry::setVerticalStep(float step) { step = qMax(step, 0.0f); if (qFuzzyCompare(m_vertStep, step)) return; m_vertStep = step; emit verticalStepChanged(); updateData(); update(); } static void fillVertexData(QByteArray &vertexData, int horLines, float horStep, int vertLines, float vertStep) { const int size = (horLines + vertLines) * sizeof(float) * 8 * 2; vertexData.resize(size); float *dataPtr = reinterpret_cast(vertexData.data()); float y0 = -float(horLines - 1) * horStep * .5f; float x0 = -float(vertLines - 1) * vertStep * .5f; float y1 = -y0; float x1 = -x0; for (int i = 0; i < horLines; ++i) { // start position dataPtr[0] = x0; dataPtr[1] = y0 + i * horStep; dataPtr[2] = .0f; dataPtr[3] = 1.f; dataPtr[4] = 0; dataPtr[5] = 0; dataPtr[6] = 1.f; dataPtr[7] = 0; dataPtr += 8; // end position dataPtr[0] = x1; dataPtr[1] = y0 + i * horStep; dataPtr[2] = .0f; dataPtr[3] = 1.f; dataPtr[4] = 0; dataPtr[5] = 0; dataPtr[6] = 1.f; dataPtr[7] = 0; dataPtr += 8; } for (int i = 0; i < vertLines; ++i) { // start position dataPtr[0] = x0 + i * vertStep; dataPtr[1] = y0; dataPtr[2] = .0f; dataPtr[3] = 1.f; dataPtr[4] = 0; dataPtr[5] = 0; dataPtr[6] = 1.f; dataPtr[7] = 0; dataPtr += 8; // end position dataPtr[0] = x0 + i * vertStep; dataPtr[1] = y1; dataPtr[2] = .0f; dataPtr[3] = 1.f; dataPtr[4] = 0; dataPtr[5] = 0; dataPtr[6] = 1.f; dataPtr[7] = 0; dataPtr += 8; } } void GridGeometry::updateData() { QByteArray vertexData; fillVertexData(vertexData, m_horLines, m_horStep, m_vertLines, m_vertStep); clear(); addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0, QQuick3DGeometry::Attribute::ComponentType::F32Type); addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16, QQuick3DGeometry::Attribute::ComponentType::F32Type); setStride(32); setVertexData(vertexData); setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines); setBounds(QVector3D(float(-m_vertLines / 2), float(-m_horLines / 2), 0.0f) * m_horStep, QVector3D(float(m_vertLines / 2), float(m_horLines / 2), 0.0f) * m_vertStep); }