7#if QT_CONFIG(concurrent)
8#include <QtConcurrentRun>
14
15
16
17
18
19
20
21
22
23
26
27
28
31
32
33
37
38
39
42
43
44
45
46
47
48
49
50
51
54
55
56
57
58
59
60
63
64
65
68
69
70
71
74
75
76
77
78
79
80
81
82
83
85PlaneGeometry::PlaneGeometry(QQuick3DObject *parent)
86 : QQuick3DGeometry(parent)
88#if QT_CONFIG(concurrent)
89 connect(&m_geometryDataWatcher, &QFutureWatcher<GeometryData>::finished,
this, &PlaneGeometry::requestFinished);
91 scheduleGeometryUpdate();
94PlaneGeometry::~PlaneGeometry()
99float PlaneGeometry::width()
const
104void PlaneGeometry::setWidth(
float newWidth)
106 if (qFuzzyCompare(m_width, newWidth))
110 scheduleGeometryUpdate();
113float PlaneGeometry::height()
const
118void PlaneGeometry::setHeight(
float newHeight)
120 if (qFuzzyCompare(m_height, newHeight))
122 m_height = newHeight;
123 emit heightChanged();
124 scheduleGeometryUpdate();
127QSize PlaneGeometry::meshResolution()
const
129 return m_meshResolution;
132void PlaneGeometry::setMeshResolution(
const QSize &newMeshResolution)
134 if (m_meshResolution == newMeshResolution)
136 m_meshResolution = newMeshResolution;
137 emit meshResolutionChanged();
138 scheduleGeometryUpdate();
141PlaneGeometry::Plane PlaneGeometry::plane()
const
146void PlaneGeometry::setPlane(Plane newPlane)
148 if (m_plane == newPlane)
152 scheduleGeometryUpdate();
155bool PlaneGeometry::reversed()
const
160void PlaneGeometry::setReversed(
bool newReversed)
162 if (m_reversed == newReversed)
164 m_reversed = newReversed;
165 emit reversedChanged();
166 scheduleGeometryUpdate();
169bool PlaneGeometry::mirrored()
const
174void PlaneGeometry::setMirrored(
bool newMirrored)
176 if (m_mirrored == newMirrored)
178 m_mirrored = newMirrored;
179 emit mirroredChanged();
180 scheduleGeometryUpdate();
183bool PlaneGeometry::asynchronous()
const
185 return m_asynchronous;
188void PlaneGeometry::setAsynchronous(
bool newAsynchronous)
190 if (m_asynchronous == newAsynchronous)
192 m_asynchronous = newAsynchronous;
193 emit asynchronousChanged();
196PlaneGeometry::Status PlaneGeometry::status()
const
201void PlaneGeometry::doUpdateGeometry()
204 m_geometryUpdateRequested =
false;
206#if QT_CONFIG(concurrent)
207 if (m_geometryDataFuture.isRunning()) {
208 m_pendingAsyncUpdate =
true;
214 if (m_width <= 0 || m_height <= 0 || m_meshResolution.width() <= 0 || m_meshResolution.height() <= 0) {
220#if QT_CONFIG(concurrent)
221 if (m_asynchronous) {
222 m_geometryDataFuture = QtConcurrent::run(generatePlaneGeometryAsync,
229 m_geometryDataWatcher.setFuture(m_geometryDataFuture);
230 m_status = Status::Loading;
231 Q_EMIT statusChanged();
237 updateGeometry(generatePlaneGeometry(m_width, m_height, m_meshResolution, m_plane, m_reversed, m_mirrored));
241void PlaneGeometry::requestFinished()
243#if QT_CONFIG(concurrent)
244 const auto output = m_geometryDataFuture.takeResult();
245 updateGeometry(output);
249void PlaneGeometry::scheduleGeometryUpdate()
251 if (!m_geometryUpdateRequested) {
252 QMetaObject::invokeMethod(
this,
"doUpdateGeometry", Qt::QueuedConnection);
253 m_geometryUpdateRequested =
true;
257void PlaneGeometry::updateGeometry(
const GeometryData &geometryData)
259 setStride(
sizeof(
float) * 8);
260 setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles);
261 addAttribute(QQuick3DGeometry::Attribute::PositionSemantic,
263 QQuick3DGeometry::Attribute::F32Type);
264 addAttribute(QQuick3DGeometry::Attribute::TexCoord0Semantic,
266 QQuick3DGeometry::Attribute::F32Type);
267 addAttribute(QQuick3DGeometry::Attribute::NormalSemantic,
269 QQuick3DGeometry::Attribute::F32Type);
270 addAttribute(QQuick3DGeometry::Attribute::IndexSemantic,
272 QQuick3DGeometry::Attribute::U16Type);
274 setBounds(geometryData.boundsMin, geometryData.boundsMax);
275 setVertexData(geometryData.vertexData);
276 setIndexData(geometryData.indexData);
280 if (m_pendingAsyncUpdate) {
281 m_pendingAsyncUpdate =
false;
282 scheduleGeometryUpdate();
284 m_status = Status::Ready;
285 Q_EMIT statusChanged();
290PlaneGeometry::GeometryData PlaneGeometry::generatePlaneGeometry(
float width,
float height, QSize meshResolution, Plane plane,
bool reversed,
bool mirrored)
292 GeometryData geometryData;
294 int quadsX = meshResolution.width();
295 int quadsY = meshResolution.height();
297 const int numVertices = (quadsX + 1) * (quadsY + 1);
298 const int numIndices = quadsX * quadsY * 6;
300 const int vertexStride =
sizeof(
float) * (3 + 2 + 3);
301 const int indexStride =
sizeof(uint16_t);
303 geometryData.vertexData.resize(numVertices * vertexStride);
304 geometryData.indexData.resize(numIndices * indexStride);
306 QVector3D boundsMin(std::numeric_limits<
float>::max(),
307 std::numeric_limits<
float>::max(),
308 std::numeric_limits<
float>::max());
310 QVector3D boundsMax(std::numeric_limits<
float>::lowest(),
311 std::numeric_limits<
float>::lowest(),
312 std::numeric_limits<
float>::lowest());
314 float* vertexPtr =
reinterpret_cast<
float*>(geometryData.vertexData.data());
315 uint16_t* indexPtr =
reinterpret_cast<uint16_t*>(geometryData.indexData.data());
320 normal = QVector3D(0, 0, 1);
323 normal = QVector3D(0, 1, 0);
326 normal = QVector3D(1, 0, 0);
334 for (
int y = 0; y <= quadsY; ++y) {
335 for (
int x = 0; x <= quadsX; ++x) {
337 float u =
static_cast<
float>(x) / quadsX;
338 float v =
static_cast<
float>(y) / quadsY;
341 float posX = width * (u - 0.5f);
342 float posY = height * (v - 0.5f);
354 position = QVector3D(posX, posY, 0.0f);
357 position = QVector3D(posX, 0.0f, -posY);
360 position = QVector3D(0.0f, posY, -posX);
365 *vertexPtr++ = position.x();
366 *vertexPtr++ = position.y();
367 *vertexPtr++ = position.z();
374 *vertexPtr++ = normal.x();
375 *vertexPtr++ = normal.y();
376 *vertexPtr++ = normal.z();
379 boundsMin.setX(std::min(boundsMin.x(), position.x()));
380 boundsMin.setY(std::min(boundsMin.y(), position.y()));
381 boundsMin.setZ(std::min(boundsMin.z(), position.z()));
383 boundsMax.setX(std::max(boundsMax.x(), position.x()));
384 boundsMax.setY(std::max(boundsMax.y(), position.y()));
385 boundsMax.setZ(std::max(boundsMax.z(), position.z()));
390 for (
int y = 0; y < quadsY; ++y) {
391 for (
int x = 0; x < quadsX; ++x) {
392 uint16_t a =
static_cast<uint16_t>(y * (quadsX + 1) + x);
393 uint16_t b =
static_cast<uint16_t>(a + quadsX + 1);
394 uint16_t c =
static_cast<uint16_t>(b + 1);
395 uint16_t d =
static_cast<uint16_t>(a + 1);
420 geometryData.boundsMax = boundsMax;
421 geometryData.boundsMin = boundsMin;
426#if QT_CONFIG(concurrent)
427void PlaneGeometry::generatePlaneGeometryAsync(QPromise<PlaneGeometry::GeometryData> &promise,
430 QSize meshResolution,
435 auto output = generatePlaneGeometry(width, height, meshResolution, plane, reversed, mirrored);
436 promise.addResult(output);