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 | |