8#if QT_CONFIG(concurrent)
9#include <QtConcurrentRun>
15
16
17
18
19
20
21
22
23
24
27
28
29
32
33
34
37
38
39
42
43
44
47
48
49
52
53
54
57
58
59
60
63
64
65
66
67
68
69
70
71
72
75CuboidGeometry::CuboidGeometry(QQuick3DObject *parent)
76 : QQuick3DGeometry(parent)
78#if QT_CONFIG(concurrent)
79 connect(&m_geometryDataWatcher, &QFutureWatcher<GeometryData>::finished,
this, &CuboidGeometry::requestFinished);
81 scheduleGeometryUpdate();
84CuboidGeometry::~CuboidGeometry()
89float CuboidGeometry::xExtent()
const
94void CuboidGeometry::setXExtent(
float newXExtent)
96 if (qFuzzyCompare(m_xExtent, newXExtent))
98 m_xExtent = newXExtent;
99 emit xExtentChanged();
100 scheduleGeometryUpdate();
103float CuboidGeometry::yExtent()
const
108void CuboidGeometry::setYExtent(
float newYExtent)
110 if (qFuzzyCompare(m_yExtent, newYExtent))
112 m_yExtent = newYExtent;
113 emit yExtentChanged();
114 scheduleGeometryUpdate();
117float CuboidGeometry::zExtent()
const
122void CuboidGeometry::setZExtent(
float newZExtent)
124 if (qFuzzyCompare(m_zExtent, newZExtent))
126 m_zExtent = newZExtent;
127 emit zExtentChanged();
128 scheduleGeometryUpdate();
131QSize CuboidGeometry::yzMeshResolution()
const
133 return m_yzMeshResolution;
136void CuboidGeometry::setYzMeshResolution(
const QSize &newYzMeshResolution)
138 if (m_yzMeshResolution == newYzMeshResolution)
140 m_yzMeshResolution = newYzMeshResolution;
141 emit yzMeshResolutionChanged();
142 scheduleGeometryUpdate();
145QSize CuboidGeometry::xzMeshResolution()
const
147 return m_xzMeshResolution;
150void CuboidGeometry::setXzMeshResolution(
const QSize &newXzMeshResolution)
152 if (m_xzMeshResolution == newXzMeshResolution)
154 m_xzMeshResolution = newXzMeshResolution;
155 emit xzMeshResolutionChanged();
156 scheduleGeometryUpdate();
159QSize CuboidGeometry::xyMeshResolution()
const
161 return m_xyMeshResolution;
164void CuboidGeometry::setXyMeshResolution(
const QSize &newXyMeshResolution)
166 if (m_xyMeshResolution == newXyMeshResolution)
168 m_xyMeshResolution = newXyMeshResolution;
169 emit xyMeshResolutionChanged();
170 scheduleGeometryUpdate();
173bool CuboidGeometry::asynchronous()
const
175 return m_asynchronous;
178void CuboidGeometry::setAsynchronous(
bool newAsynchronous)
180 if (m_asynchronous == newAsynchronous)
182 m_asynchronous = newAsynchronous;
183 emit asynchronousChanged();
186CuboidGeometry::Status CuboidGeometry::status()
const
191void CuboidGeometry::doUpdateGeometry()
194 m_geometryUpdateRequested =
false;
196#if QT_CONFIG(concurrent)
197 if (m_geometryDataFuture.isRunning()) {
198 m_pendingAsyncUpdate =
true;
206 if (m_xExtent <= 0 || m_yExtent <= 0 || m_yExtent <= 0) {
212#if QT_CONFIG(concurrent)
213 if (m_asynchronous) {
214 m_geometryDataFuture = QtConcurrent::run(generateCuboidGeometryAsync,
221 m_geometryDataWatcher.setFuture(m_geometryDataFuture);
222 m_status = Status::Loading;
223 Q_EMIT statusChanged();
229 updateGeometry(generateCuboidGeometry(m_xExtent,
234 m_xyMeshResolution));
238void CuboidGeometry::requestFinished()
240#if QT_CONFIG(concurrent)
241 const auto output = m_geometryDataFuture.takeResult();
242 updateGeometry(output);
246void CuboidGeometry::scheduleGeometryUpdate()
248 if (!m_geometryUpdateRequested) {
249 QMetaObject::invokeMethod(
this,
"doUpdateGeometry", Qt::QueuedConnection);
250 m_geometryUpdateRequested =
true;
254void CuboidGeometry::updateGeometry(
const GeometryData &geometryData)
256 setStride(
sizeof(
float) * 8);
257 setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles);
258 addAttribute(QQuick3DGeometry::Attribute::PositionSemantic,
260 QQuick3DGeometry::Attribute::F32Type);
261 addAttribute(QQuick3DGeometry::Attribute::TexCoord0Semantic,
263 QQuick3DGeometry::Attribute::F32Type);
264 addAttribute(QQuick3DGeometry::Attribute::NormalSemantic,
266 QQuick3DGeometry::Attribute::F32Type);
267 addAttribute(QQuick3DGeometry::Attribute::IndexSemantic,
269 QQuick3DGeometry::Attribute::U16Type);
271 setBounds(geometryData.boundsMin, geometryData.boundsMax);
272 setVertexData(geometryData.vertexData);
273 setIndexData(geometryData.indexData);
277 if (m_pendingAsyncUpdate) {
278 m_pendingAsyncUpdate =
false;
279 scheduleGeometryUpdate();
281 m_status = Status::Ready;
282 Q_EMIT statusChanged();
285 emit geometryChanged();
288CuboidGeometry::GeometryData CuboidGeometry::generateCuboidGeometry(
float xExtent,
float yExtent,
float zExtent, QSize yzMeshResolution, QSize xzMeshResolution, QSize xyMeshResolution)
290 GeometryData geometryData;
292 const float halfXExtent = xExtent / 2.0f;
293 const float halfYExtent = yExtent / 2.0f;
294 const float halfZExtent = zExtent / 2.0f;
295 geometryData.boundsMin = QVector3D(-halfXExtent, -halfYExtent, -halfZExtent);
296 geometryData.boundsMax = QVector3D(halfXExtent, halfYExtent, halfZExtent);
299 int numVertices = (yzMeshResolution.width() + 1) * (yzMeshResolution.height() + 1) * 2 +
300 (xzMeshResolution.width() + 1) * (xzMeshResolution.height() + 1) * 2 +
301 (xyMeshResolution.width() + 1) * (xyMeshResolution.height() + 1) * 2;
303 int numIndices = yzMeshResolution.width() * yzMeshResolution.height() * 6 * 2 +
304 xzMeshResolution.width() * xzMeshResolution.height() * 6 * 2 +
305 xyMeshResolution.width() * xyMeshResolution.height() * 6 * 2;
307 const int vertexStride =
sizeof(
float) * (3 + 2 + 3);
308 const int indexStride =
sizeof(uint16_t);
311 geometryData.vertexData.resize(numVertices * vertexStride);
312 geometryData.indexData.resize(numIndices * indexStride);
315 float* vertexPtr =
reinterpret_cast<
float*>(geometryData.vertexData.data());
316 uint16_t* indexPtr =
reinterpret_cast<uint16_t*>(geometryData.indexData.data());
319 auto generatePlane = [](
float* &vertexPtr, uint16_t* &indexPtr, uint16_t &indexOffset,
float width,
float height,
const QVector3D& origin,
const QVector3D& right,
const QVector3D& up,
const QVector3D& normal, QSize resolution,
bool flipWinding =
false) {
320 const int quadsX = resolution.width();
321 const int quadsY = resolution.height();
322 const float halfWidth = width / 2.0f;
323 const float halfHeight = height / 2.0f;
324 quint16 vertexCount = 0;
327 for (
int y = 0; y <= quadsY; ++y) {
328 for (
int x = 0; x <= quadsX; ++x) {
330 float u =
static_cast<
float>(x) / quadsX;
331 float v =
static_cast<
float>(y) / quadsY;
334 QVector3D position = origin + right * (u * width - halfWidth) + up * (v * height - halfHeight);
337 *vertexPtr++ = position.x();
338 *vertexPtr++ = position.y();
339 *vertexPtr++ = position.z();
346 *vertexPtr++ = normal.x();
347 *vertexPtr++ = normal.y();
348 *vertexPtr++ = normal.z();
355 for (
int y = 0; y < quadsY; ++y) {
356 for (
int x = 0; x < quadsX; ++x) {
357 uint16_t a = indexOffset +
static_cast<uint16_t>(y * (quadsX + 1) + x);
358 uint16_t b =
static_cast<uint16_t>(a + quadsX + 1);
359 uint16_t c =
static_cast<uint16_t>(b + 1);
360 uint16_t d =
static_cast<uint16_t>(a + 1);
383 indexOffset += vertexCount;
388 uint16_t indexOffset = 0;
389 generatePlane(vertexPtr, indexPtr, indexOffset, zExtent, yExtent, QVector3D(halfXExtent, 0, 0), QVector3D(0, 0, -1), QVector3D(0, 1, 0), QVector3D(1, 0, 0), yzMeshResolution);
390 generatePlane(vertexPtr, indexPtr, indexOffset, zExtent, yExtent, QVector3D(-halfXExtent, 0, 0), QVector3D(0, 0, 1), QVector3D(0, 1, 0), QVector3D(-1, 0, 0), yzMeshResolution);
394 generatePlane(vertexPtr, indexPtr, indexOffset, xExtent, zExtent, QVector3D(0, halfYExtent, 0), QVector3D(-1, 0, 0), QVector3D(0, 0, 1), QVector3D(0, 1, 0), xzMeshResolution);
395 generatePlane(vertexPtr, indexPtr, indexOffset, xExtent, zExtent, QVector3D(0, -halfYExtent, 0), QVector3D(1, 0, 0), QVector3D(0, 0, 1), QVector3D(0, -1, 0), xzMeshResolution);
398 generatePlane(vertexPtr, indexPtr, indexOffset, xExtent, yExtent, QVector3D(0, 0, halfZExtent), QVector3D(1, 0, 0), QVector3D(0, 1, 0), QVector3D(0, 0, 1), xyMeshResolution);
399 generatePlane(vertexPtr, indexPtr, indexOffset, xExtent, yExtent, QVector3D(0, 0, -halfZExtent), QVector3D(-1, 0, 0), QVector3D(0, 1, 0), QVector3D(0, 0, -1), xyMeshResolution);
405#if QT_CONFIG(concurrent)
406void CuboidGeometry::generateCuboidGeometryAsync(QPromise<CuboidGeometry::GeometryData> &promise,
410 QSize yzMeshResolution,
411 QSize xzMeshResolution,
412 QSize xyMeshResolution)
414 auto output = generateCuboidGeometry(xExtent, yExtent, zExtent, yzMeshResolution, xzMeshResolution, xyMeshResolution);
415 promise.addResult(output);
Combined button and popup list for selecting options.