6#if QT_CONFIG(concurrent)
7#include <QtConcurrentRun>
13
14
15
16
17
18
19
20
21
22
25
26
27
30
31
32
35
36
37
40
41
42
45
46
47
50
51
52
55
56
57
58
61
62
63
64
65
66
67
68
69
70
76#if QT_CONFIG(concurrent)
77 connect(&m_geometryDataWatcher, &QFutureWatcher<GeometryData>::finished,
this, &CuboidGeometry::requestFinished);
79 scheduleGeometryUpdate();
82CuboidGeometry::~CuboidGeometry()
87float CuboidGeometry::xExtent()
const
92void CuboidGeometry::setXExtent(
float newXExtent)
94 if (qFuzzyCompare(m_xExtent, newXExtent))
96 m_xExtent = newXExtent;
97 emit xExtentChanged();
98 scheduleGeometryUpdate();
101float CuboidGeometry::yExtent()
const
106void CuboidGeometry::setYExtent(
float newYExtent)
108 if (qFuzzyCompare(m_yExtent, newYExtent))
110 m_yExtent = newYExtent;
111 emit yExtentChanged();
112 scheduleGeometryUpdate();
115float CuboidGeometry::zExtent()
const
120void CuboidGeometry::setZExtent(
float newZExtent)
122 if (qFuzzyCompare(m_zExtent, newZExtent))
124 m_zExtent = newZExtent;
125 emit zExtentChanged();
126 scheduleGeometryUpdate();
129QSize CuboidGeometry::yzMeshResolution()
const
131 return m_yzMeshResolution;
134void CuboidGeometry::setYzMeshResolution(
const QSize &newYzMeshResolution)
136 if (m_yzMeshResolution == newYzMeshResolution)
138 m_yzMeshResolution = newYzMeshResolution;
139 emit yzMeshResolutionChanged();
140 scheduleGeometryUpdate();
143QSize CuboidGeometry::xzMeshResolution()
const
145 return m_xzMeshResolution;
148void CuboidGeometry::setXzMeshResolution(
const QSize &newXzMeshResolution)
150 if (m_xzMeshResolution == newXzMeshResolution)
152 m_xzMeshResolution = newXzMeshResolution;
153 emit xzMeshResolutionChanged();
154 scheduleGeometryUpdate();
157QSize CuboidGeometry::xyMeshResolution()
const
159 return m_xyMeshResolution;
162void CuboidGeometry::setXyMeshResolution(
const QSize &newXyMeshResolution)
164 if (m_xyMeshResolution == newXyMeshResolution)
166 m_xyMeshResolution = newXyMeshResolution;
167 emit xyMeshResolutionChanged();
168 scheduleGeometryUpdate();
171bool CuboidGeometry::asynchronous()
const
173 return m_asynchronous;
176void CuboidGeometry::setAsynchronous(
bool newAsynchronous)
178 if (m_asynchronous == newAsynchronous)
180 m_asynchronous = newAsynchronous;
181 emit asynchronousChanged();
184CuboidGeometry::Status CuboidGeometry::status()
const
189void CuboidGeometry::doUpdateGeometry()
192 m_geometryUpdateRequested =
false;
194#if QT_CONFIG(concurrent)
195 if (m_geometryDataFuture.isRunning()) {
196 m_pendingAsyncUpdate =
true;
204 if (m_xExtent <= 0 || m_yExtent <= 0 || m_yExtent <= 0) {
210#if QT_CONFIG(concurrent)
211 if (m_asynchronous) {
212 m_geometryDataFuture = QtConcurrent::run(generateCuboidGeometryAsync,
219 m_geometryDataWatcher.setFuture(m_geometryDataFuture);
220 m_status = Status::Loading;
221 Q_EMIT statusChanged();
227 updateGeometry(generateCuboidGeometry(m_xExtent,
232 m_xyMeshResolution));
236void CuboidGeometry::requestFinished()
238#if QT_CONFIG(concurrent)
239 const auto output = m_geometryDataFuture.takeResult();
240 updateGeometry(output);
244void CuboidGeometry::scheduleGeometryUpdate()
246 if (!m_geometryUpdateRequested) {
247 QMetaObject::invokeMethod(
this,
"doUpdateGeometry", Qt::QueuedConnection);
248 m_geometryUpdateRequested =
true;
252void CuboidGeometry::updateGeometry(
const GeometryData &geometryData)
254 setStride(
sizeof(
float) * 8);
255 setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles);
256 addAttribute(QQuick3DGeometry::Attribute::PositionSemantic,
258 QQuick3DGeometry::Attribute::F32Type);
259 addAttribute(QQuick3DGeometry::Attribute::TexCoord0Semantic,
261 QQuick3DGeometry::Attribute::F32Type);
262 addAttribute(QQuick3DGeometry::Attribute::NormalSemantic,
264 QQuick3DGeometry::Attribute::F32Type);
265 addAttribute(QQuick3DGeometry::Attribute::IndexSemantic,
267 QQuick3DGeometry::Attribute::U16Type);
269 setBounds(geometryData.boundsMin, geometryData.boundsMax);
270 setVertexData(geometryData.vertexData);
271 setIndexData(geometryData.indexData);
275 if (m_pendingAsyncUpdate) {
276 m_pendingAsyncUpdate =
false;
277 scheduleGeometryUpdate();
279 m_status = Status::Ready;
280 Q_EMIT statusChanged();
285CuboidGeometry::GeometryData CuboidGeometry::generateCuboidGeometry(
float xExtent,
float yExtent,
float zExtent, QSize yzMeshResolution, QSize xzMeshResolution, QSize xyMeshResolution)
287 GeometryData geometryData;
289 const float halfXExtent = xExtent / 2.0f;
290 const float halfYExtent = yExtent / 2.0f;
291 const float halfZExtent = zExtent / 2.0f;
292 geometryData.boundsMin = QVector3D(-halfXExtent, -halfYExtent, -halfZExtent);
293 geometryData.boundsMax = QVector3D(halfXExtent, halfYExtent, halfZExtent);
296 int numVertices = (yzMeshResolution.width() + 1) * (yzMeshResolution.height() + 1) * 2 +
297 (xzMeshResolution.width() + 1) * (xzMeshResolution.height() + 1) * 2 +
298 (xyMeshResolution.width() + 1) * (xyMeshResolution.height() + 1) * 2;
300 int numIndices = yzMeshResolution.width() * yzMeshResolution.height() * 6 * 2 +
301 xzMeshResolution.width() * xzMeshResolution.height() * 6 * 2 +
302 xyMeshResolution.width() * xyMeshResolution.height() * 6 * 2;
304 const int vertexStride =
sizeof(
float) * (3 + 2 + 3);
305 const int indexStride =
sizeof(uint16_t);
308 geometryData.vertexData.resize(numVertices * vertexStride);
309 geometryData.indexData.resize(numIndices * indexStride);
312 float* vertexPtr =
reinterpret_cast<
float*>(geometryData.vertexData.data());
313 uint16_t* indexPtr =
reinterpret_cast<uint16_t*>(geometryData.indexData.data());
316 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) {
317 const int quadsX = resolution.width();
318 const int quadsY = resolution.height();
319 const float halfWidth = width / 2.0f;
320 const float halfHeight = height / 2.0f;
321 quint16 vertexCount = 0;
324 for (
int y = 0; y <= quadsY; ++y) {
325 for (
int x = 0; x <= quadsX; ++x) {
327 float u =
static_cast<
float>(x) / quadsX;
328 float v =
static_cast<
float>(y) / quadsY;
331 QVector3D position = origin + right * (u * width - halfWidth) + up * (v * height - halfHeight);
334 *vertexPtr++ = position.x();
335 *vertexPtr++ = position.y();
336 *vertexPtr++ = position.z();
343 *vertexPtr++ = normal.x();
344 *vertexPtr++ = normal.y();
345 *vertexPtr++ = normal.z();
352 for (
int y = 0; y < quadsY; ++y) {
353 for (
int x = 0; x < quadsX; ++x) {
354 uint16_t a = indexOffset +
static_cast<uint16_t>(y * (quadsX + 1) + x);
355 uint16_t b =
static_cast<uint16_t>(a + quadsX + 1);
356 uint16_t c =
static_cast<uint16_t>(b + 1);
357 uint16_t d =
static_cast<uint16_t>(a + 1);
380 indexOffset += vertexCount;
385 uint16_t indexOffset = 0;
386 generatePlane(vertexPtr, indexPtr, indexOffset, zExtent, yExtent, QVector3D(halfXExtent, 0, 0), QVector3D(0, 0, -1), QVector3D(0, 1, 0), QVector3D(1, 0, 0), yzMeshResolution);
387 generatePlane(vertexPtr, indexPtr, indexOffset, zExtent, yExtent, QVector3D(-halfXExtent, 0, 0), QVector3D(0, 0, 1), QVector3D(0, 1, 0), QVector3D(-1, 0, 0), yzMeshResolution);
391 generatePlane(vertexPtr, indexPtr, indexOffset, xExtent, zExtent, QVector3D(0, halfYExtent, 0), QVector3D(-1, 0, 0), QVector3D(0, 0, 1), QVector3D(0, 1, 0), xzMeshResolution);
392 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, yExtent, QVector3D(0, 0, halfZExtent), QVector3D(1, 0, 0), QVector3D(0, 1, 0), QVector3D(0, 0, 1), xyMeshResolution);
396 generatePlane(vertexPtr, indexPtr, indexOffset, xExtent, yExtent, QVector3D(0, 0, -halfZExtent), QVector3D(-1, 0, 0), QVector3D(0, 1, 0), QVector3D(0, 0, -1), xyMeshResolution);
402#if QT_CONFIG(concurrent)
403void CuboidGeometry::generateCuboidGeometryAsync(QPromise<CuboidGeometry::GeometryData> &promise,
407 QSize yzMeshResolution,
408 QSize xzMeshResolution,
409 QSize xyMeshResolution)
411 auto output = generateCuboidGeometry(xExtent, yExtent, zExtent, yzMeshResolution, xzMeshResolution, xyMeshResolution);
412 promise.addResult(output);
\qmltype Object3D \inqmlmodule QtQuick3D \nativetype QQuick3DObject \inherits QtObject
Combined button and popup list for selecting options.