| 1 | // Copyright (C) 2019 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
| 3 | |
| 4 | #include "gridgeometry_p.h" |
| 5 | #include <QtQuick3DRuntimeRender/private/qssgrendergeometry_p.h> |
| 6 | |
| 7 | /*! |
| 8 | \qmltype GridGeometry |
| 9 | \inqmlmodule QtQuick3D.Helpers |
| 10 | \inherits Geometry |
| 11 | \brief A custom geometry provider for rendering grids. |
| 12 | |
| 13 | This helper implements grid geometry, which allows showing a grid in a scene. |
| 14 | |
| 15 | For example, the following snippet would display a grid with 19 cells in |
| 16 | both directions in a scene that has one light. Without further |
| 17 | transformations, the grid is facing the camera by default. |
| 18 | |
| 19 | \image gridgeometry.jpg |
| 20 | |
| 21 | \badcode |
| 22 | View3D { |
| 23 | anchors.fill: parent |
| 24 | camera: camera |
| 25 | |
| 26 | PerspectiveCamera { |
| 27 | id: camera |
| 28 | position: Qt.vector3d(0, 0, 600) |
| 29 | } |
| 30 | |
| 31 | DirectionalLight { |
| 32 | position: Qt.vector3d(-500, 500, -100) |
| 33 | color: Qt.rgba(0.4, 0.2, 0.6, 1.0) |
| 34 | ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0) |
| 35 | } |
| 36 | |
| 37 | Model { |
| 38 | scale: Qt.vector3d(100, 100, 100) |
| 39 | geometry: GridGeometry { |
| 40 | horizontalLines: 20 |
| 41 | verticalLines: 20 |
| 42 | } |
| 43 | materials: [ DefaultMaterial { } ] |
| 44 | } |
| 45 | } |
| 46 | \endcode |
| 47 | |
| 48 | \sa {Qt Quick 3D - Custom Geometry Example}, Model |
| 49 | */ |
| 50 | |
| 51 | /*! \qmlproperty int GridGeometry::horizontalLines |
| 52 | Specifies the number of horizontal lines in a grid. The default value is 1000. |
| 53 | */ |
| 54 | /*! \qmlproperty int GridGeometry::verticalLines |
| 55 | Specifies the number of vertical lines in a grid. The default value is 1000. |
| 56 | */ |
| 57 | /*! \qmlproperty real GridGeometry::horizontalStep |
| 58 | Specifies the spacing between horizontal lines. The default value is 0.1. |
| 59 | */ |
| 60 | /*! \qmlproperty real GridGeometry::verticalStep |
| 61 | Specifies the spacing between vertical lines. The default value is 0.1. |
| 62 | */ |
| 63 | |
| 64 | GridGeometry::GridGeometry() |
| 65 | : QQuick3DGeometry() |
| 66 | { |
| 67 | updateData(); |
| 68 | } |
| 69 | |
| 70 | GridGeometry::~GridGeometry() |
| 71 | { |
| 72 | |
| 73 | } |
| 74 | |
| 75 | int GridGeometry::horizontalLines() const |
| 76 | { |
| 77 | return m_horLines; |
| 78 | } |
| 79 | |
| 80 | int GridGeometry::verticalLines() const |
| 81 | { |
| 82 | return m_vertLines; |
| 83 | } |
| 84 | |
| 85 | float GridGeometry::horizontalStep() const |
| 86 | { |
| 87 | return m_horStep; |
| 88 | } |
| 89 | |
| 90 | float GridGeometry::verticalStep() const |
| 91 | { |
| 92 | return m_vertStep; |
| 93 | } |
| 94 | |
| 95 | void GridGeometry::setHorizontalLines(int count) |
| 96 | { |
| 97 | count = qMax(a: count, b: 1); |
| 98 | if (m_horLines == count) |
| 99 | return; |
| 100 | m_horLines = qMax(a: count, b: 1); |
| 101 | emit horizontalLinesChanged(); |
| 102 | updateData(); |
| 103 | update(); |
| 104 | } |
| 105 | |
| 106 | void GridGeometry::setVerticalLines(int count) |
| 107 | { |
| 108 | count = qMax(a: count, b: 1); |
| 109 | if (m_vertLines == count) |
| 110 | return; |
| 111 | m_vertLines = qMax(a: count, b: 1); |
| 112 | emit verticalLinesChanged(); |
| 113 | updateData(); |
| 114 | update(); |
| 115 | } |
| 116 | |
| 117 | void GridGeometry::setHorizontalStep(float step) |
| 118 | { |
| 119 | step = qMax(a: step, b: 0.0f); |
| 120 | if (qFuzzyCompare(p1: m_horStep, p2: step)) |
| 121 | return; |
| 122 | m_horStep = step; |
| 123 | emit horizontalStepChanged(); |
| 124 | updateData(); |
| 125 | update(); |
| 126 | } |
| 127 | |
| 128 | void GridGeometry::setVerticalStep(float step) |
| 129 | { |
| 130 | step = qMax(a: step, b: 0.0f); |
| 131 | if (qFuzzyCompare(p1: m_vertStep, p2: step)) |
| 132 | return; |
| 133 | m_vertStep = step; |
| 134 | emit verticalStepChanged(); |
| 135 | updateData(); |
| 136 | update(); |
| 137 | } |
| 138 | |
| 139 | static void fillVertexData(QByteArray &vertexData, int horLines, float horStep, |
| 140 | int vertLines, float vertStep) |
| 141 | { |
| 142 | const int size = (horLines + vertLines) * sizeof(float) * 8 * 2; |
| 143 | vertexData.resize(size); |
| 144 | float *dataPtr = reinterpret_cast<float *>(vertexData.data()); |
| 145 | |
| 146 | float y0 = -float(horLines - 1) * horStep * .5f; |
| 147 | float x0 = -float(vertLines - 1) * vertStep * .5f; |
| 148 | float y1 = -y0; |
| 149 | float x1 = -x0; |
| 150 | |
| 151 | for (int i = 0; i < horLines; ++i) { |
| 152 | // start position |
| 153 | dataPtr[0] = x0; |
| 154 | dataPtr[1] = y0 + i * horStep; |
| 155 | dataPtr[2] = .0f; |
| 156 | dataPtr[3] = 1.f; |
| 157 | |
| 158 | dataPtr[4] = 0; |
| 159 | dataPtr[5] = 0; |
| 160 | dataPtr[6] = 1.f; |
| 161 | dataPtr[7] = 0; |
| 162 | |
| 163 | dataPtr += 8; |
| 164 | |
| 165 | // end position |
| 166 | dataPtr[0] = x1; |
| 167 | dataPtr[1] = y0 + i * horStep; |
| 168 | dataPtr[2] = .0f; |
| 169 | dataPtr[3] = 1.f; |
| 170 | |
| 171 | dataPtr[4] = 0; |
| 172 | dataPtr[5] = 0; |
| 173 | dataPtr[6] = 1.f; |
| 174 | dataPtr[7] = 0; |
| 175 | |
| 176 | dataPtr += 8; |
| 177 | } |
| 178 | |
| 179 | for (int i = 0; i < vertLines; ++i) { |
| 180 | // start position |
| 181 | dataPtr[0] = x0 + i * vertStep; |
| 182 | dataPtr[1] = y0; |
| 183 | dataPtr[2] = .0f; |
| 184 | dataPtr[3] = 1.f; |
| 185 | |
| 186 | dataPtr[4] = 0; |
| 187 | dataPtr[5] = 0; |
| 188 | dataPtr[6] = 1.f; |
| 189 | dataPtr[7] = 0; |
| 190 | |
| 191 | dataPtr += 8; |
| 192 | |
| 193 | // end position |
| 194 | dataPtr[0] = x0 + i * vertStep; |
| 195 | dataPtr[1] = y1; |
| 196 | dataPtr[2] = .0f; |
| 197 | dataPtr[3] = 1.f; |
| 198 | |
| 199 | dataPtr[4] = 0; |
| 200 | dataPtr[5] = 0; |
| 201 | dataPtr[6] = 1.f; |
| 202 | dataPtr[7] = 0; |
| 203 | |
| 204 | dataPtr += 8; |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | void GridGeometry::updateData() |
| 209 | { |
| 210 | QByteArray vertexData; |
| 211 | fillVertexData(vertexData, horLines: m_horLines, horStep: m_horStep, vertLines: m_vertLines, vertStep: m_vertStep); |
| 212 | clear(); |
| 213 | addAttribute(semantic: QQuick3DGeometry::Attribute::PositionSemantic, offset: 0, |
| 214 | componentType: QQuick3DGeometry::Attribute::ComponentType::F32Type); |
| 215 | addAttribute(semantic: QQuick3DGeometry::Attribute::NormalSemantic, offset: 16, |
| 216 | componentType: QQuick3DGeometry::Attribute::ComponentType::F32Type); |
| 217 | setStride(32); |
| 218 | setVertexData(vertexData); |
| 219 | setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines); |
| 220 | setBounds(min: QVector3D(float(-m_vertLines / 2), float(-m_horLines / 2), 0.0f) * m_horStep, |
| 221 | max: QVector3D(float(m_vertLines / 2), float(m_horLines / 2), 0.0f) * m_vertStep); |
| 222 | } |
| 223 | |