| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the Qt3D module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | 
| 21 | ** packaging of this file. Please review the following information to | 
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | 
| 24 | ** | 
| 25 | ** GNU General Public License Usage | 
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | 
| 28 | ** Public license version 3 or any later version approved by the KDE Free | 
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | 
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | 
| 31 | ** included in the packaging of this file. Please review the following | 
| 32 | ** information to ensure the GNU General Public License requirements will | 
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | 
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | 
| 35 | ** | 
| 36 | ** $QT_END_LICENSE$ | 
| 37 | ** | 
| 38 | ****************************************************************************/ | 
| 39 |  | 
| 40 | #include "qcuboidgeometry.h" | 
| 41 | #include "qcuboidgeometry_p.h" | 
| 42 |  | 
| 43 | #include <Qt3DRender/qattribute.h> | 
| 44 | #include <Qt3DRender/qbuffer.h> | 
| 45 | #include <Qt3DRender/qbufferdatagenerator.h> | 
| 46 | #include <Qt3DRender/private/renderlogging_p.h> | 
| 47 |  | 
| 48 | #include <limits> | 
| 49 |  | 
| 50 |  | 
| 51 | QT_BEGIN_NAMESPACE | 
| 52 |  | 
| 53 | using namespace Qt3DRender; | 
| 54 |  | 
| 55 | namespace  Qt3DExtras { | 
| 56 |  | 
| 57 | namespace { | 
| 58 |  | 
| 59 | enum  { | 
| 60 |     , | 
| 61 |     , | 
| 62 |     , | 
| 63 |     , | 
| 64 |     , | 
| 65 |      | 
| 66 | }; | 
| 67 |  | 
| 68 | void (float w, float h, const QSize &resolution, | 
| 69 |                            PlaneNormal normal, float planeDistance, | 
| 70 |                            float *vertices) | 
| 71 | { | 
| 72 |     const float a0 = -w / 2.0f; | 
| 73 |     const float b0 = -h / 2.0f; | 
| 74 |     const float da = w / (resolution.width() - 1); | 
| 75 |     const float db = h / (resolution.height() - 1); | 
| 76 |     const float du = 1.0f / (resolution.width() - 1); | 
| 77 |     const float dv = 1.0f / (resolution.height() - 1); | 
| 78 |  | 
| 79 |     switch (normal) { | 
| 80 |     case NegativeX: | 
| 81 |         // Iterate over z | 
| 82 |         for (int j = resolution.height() - 1; j >= 0; --j) { | 
| 83 |             const float b = b0 + static_cast<float>(j) * db; | 
| 84 |             const float v = static_cast<float>(j) * dv; | 
| 85 |  | 
| 86 |             // Iterate over y | 
| 87 |             for (int i = 0; i < resolution.width(); ++i) { | 
| 88 |                 const float a = a0 + static_cast<float>(i) * da; | 
| 89 |                 const float u = static_cast<float>(i) * du; | 
| 90 |  | 
| 91 |                 // position | 
| 92 |                 *vertices++ = planeDistance; | 
| 93 |                 *vertices++ = a; | 
| 94 |                 *vertices++ = b; | 
| 95 |  | 
| 96 |                 // texture coordinates | 
| 97 |                 *vertices++ = v; | 
| 98 |                 *vertices++ = u; | 
| 99 |  | 
| 100 |                 // normal | 
| 101 |                 *vertices++ = -1.0f; | 
| 102 |                 *vertices++ = 0.0f; | 
| 103 |                 *vertices++ = 0.0f; | 
| 104 |  | 
| 105 |                 // tangent | 
| 106 |                 *vertices++ = 0.0f; | 
| 107 |                 *vertices++ = 0.0f; | 
| 108 |                 *vertices++ = 1.0f; | 
| 109 |                 *vertices++ = 1.0f; | 
| 110 |             } | 
| 111 |         } | 
| 112 |         break; | 
| 113 |  | 
| 114 |     case PositiveX: { | 
| 115 |         // Iterate over z | 
| 116 |         for (int j = 0; j < resolution.height(); ++j) { | 
| 117 |             const float b = b0 + static_cast<float>(j) * db; | 
| 118 |             const float v = static_cast<float>(j) * dv; | 
| 119 |  | 
| 120 |             // Iterate over y | 
| 121 |             for (int i = 0; i < resolution.width(); ++i) { | 
| 122 |                 const float a = a0 + static_cast<float>(i) * da; | 
| 123 |                 const float u = static_cast<float>(i) * du; | 
| 124 |  | 
| 125 |                 // position | 
| 126 |                 *vertices++ = planeDistance; | 
| 127 |                 *vertices++ = a; | 
| 128 |                 *vertices++ = b; | 
| 129 |  | 
| 130 |                 // texture coordinates | 
| 131 |                 *vertices++ = 1.0f - v; | 
| 132 |                 *vertices++ = u; | 
| 133 |  | 
| 134 |                 // normal | 
| 135 |                 *vertices++ = 1.0f; | 
| 136 |                 *vertices++ = 0.0f; | 
| 137 |                 *vertices++ = 0.0f; | 
| 138 |  | 
| 139 |                 // tangent | 
| 140 |                 *vertices++ = 0.0f; | 
| 141 |                 *vertices++ = 0.0f; | 
| 142 |                 *vertices++ = -1.0f; | 
| 143 |                 *vertices++ = 1.0f; | 
| 144 |             } | 
| 145 |         } | 
| 146 |         break; | 
| 147 |     } | 
| 148 |  | 
| 149 |     case NegativeY: | 
| 150 |         // Iterate over z | 
| 151 |         for (int j = 0; j < resolution.height(); ++j) { | 
| 152 |             const float b = b0 + static_cast<float>(j) * db; | 
| 153 |             const float v = static_cast<float>(j) * dv; | 
| 154 |  | 
| 155 |             // Iterate over x | 
| 156 |             // This iterates in the opposite sense to the other directions | 
| 157 |             // so that the winding order is correct | 
| 158 |             for (int i = 0; i < resolution.width(); ++i) { | 
| 159 |                 const float a = a0 + static_cast<float>(i) * da; | 
| 160 |                 const float u = static_cast<float>(i) * du; | 
| 161 |  | 
| 162 |                 // position | 
| 163 |                 *vertices++ = a; | 
| 164 |                 *vertices++ = planeDistance; | 
| 165 |                 *vertices++ = b; | 
| 166 |  | 
| 167 |                 // texture coordinates | 
| 168 |                 *vertices++ = u; | 
| 169 |                 *vertices++ = v; | 
| 170 |  | 
| 171 |                 // normal | 
| 172 |                 *vertices++ = 0.0f; | 
| 173 |                 *vertices++ = -1.0f; | 
| 174 |                 *vertices++ = 0.0f; | 
| 175 |  | 
| 176 |                 // tangent | 
| 177 |                 *vertices++ = 1.0f; | 
| 178 |                 *vertices++ = 0.0f; | 
| 179 |                 *vertices++ = 0.0f; | 
| 180 |                 *vertices++ = 1.0f; | 
| 181 |             } | 
| 182 |         } | 
| 183 |         break; | 
| 184 |  | 
| 185 |     case PositiveY: { | 
| 186 |         // Iterate over z | 
| 187 |         for (int j = resolution.height() - 1; j >= 0; --j) { | 
| 188 |             const float b = b0 + static_cast<float>(j) * db; | 
| 189 |             const float v = static_cast<float>(j) * dv; | 
| 190 |  | 
| 191 |             // Iterate over x | 
| 192 |             // This iterates in the opposite sense to the other directions | 
| 193 |             // so that the winding order is correct | 
| 194 |             for (int i = 0; i < resolution.width(); ++i) { | 
| 195 |                 const float a = a0 + static_cast<float>(i) * da; | 
| 196 |                 const float u = static_cast<float>(i) * du; | 
| 197 |  | 
| 198 |                 // position | 
| 199 |                 *vertices++ = a; | 
| 200 |                 *vertices++ = planeDistance; | 
| 201 |                 *vertices++ = b; | 
| 202 |  | 
| 203 |                 // texture coordinates | 
| 204 |                 *vertices++ = u; | 
| 205 |                 *vertices++ = 1.0f - v; | 
| 206 |  | 
| 207 |                 // normal | 
| 208 |                 *vertices++ = 0.0f; | 
| 209 |                 *vertices++ = 1.0f; | 
| 210 |                 *vertices++ = 0.0f; | 
| 211 |  | 
| 212 |                 // tangent | 
| 213 |                 *vertices++ = 1.0f; | 
| 214 |                 *vertices++ = 0.0f; | 
| 215 |                 *vertices++ = 0.0f; | 
| 216 |                 *vertices++ = 1.0f; | 
| 217 |             } | 
| 218 |         } | 
| 219 |         break; | 
| 220 |     } | 
| 221 |  | 
| 222 |     case NegativeZ: | 
| 223 |         // Iterate over y | 
| 224 |         for (int j = 0; j < resolution.height(); ++j) { | 
| 225 |             const float b = b0 + static_cast<float>(j) * db; | 
| 226 |             const float v = static_cast<float>(j) * dv; | 
| 227 |  | 
| 228 |             // Iterate over x | 
| 229 |             for (int i = resolution.width() - 1; i >= 0; --i) { | 
| 230 |                 const float a = a0 + static_cast<float>(i) * da; | 
| 231 |                 const float u = static_cast<float>(i) * du; | 
| 232 |  | 
| 233 |                 // position | 
| 234 |                 *vertices++ = a; | 
| 235 |                 *vertices++ = b; | 
| 236 |                 *vertices++ = planeDistance; | 
| 237 |  | 
| 238 |                 // texture coordinates | 
| 239 |                 *vertices++ = 1.0f - u; | 
| 240 |                 *vertices++ = v; | 
| 241 |  | 
| 242 |                 // normal | 
| 243 |                 *vertices++ = 0.0f; | 
| 244 |                 *vertices++ = 0.0f; | 
| 245 |                 *vertices++ = -1.0f; | 
| 246 |  | 
| 247 |                 // tangent | 
| 248 |                 *vertices++ = -1.0f; | 
| 249 |                 *vertices++ = 0.0f; | 
| 250 |                 *vertices++ = 0.0f; | 
| 251 |                 *vertices++ = 1.0f; | 
| 252 |             } | 
| 253 |         } | 
| 254 |         break; | 
| 255 |  | 
| 256 |     case PositiveZ: { | 
| 257 |         // Iterate over y | 
| 258 |         for (int j = 0; j < resolution.height(); ++j) { | 
| 259 |             const float b = b0 + static_cast<float>(j) * db; | 
| 260 |             const float v = static_cast<float>(j) * dv; | 
| 261 |  | 
| 262 |             // Iterate over x | 
| 263 |             for (int i = 0; i < resolution.width(); ++i) { | 
| 264 |                 const float a = a0 + static_cast<float>(i) * da; | 
| 265 |                 const float u = static_cast<float>(i) * du; | 
| 266 |  | 
| 267 |                 // position | 
| 268 |                 *vertices++ = a; | 
| 269 |                 *vertices++ = b; | 
| 270 |                 *vertices++ = planeDistance; | 
| 271 |  | 
| 272 |                 // texture coordinates | 
| 273 |                 *vertices++ = u; | 
| 274 |                 *vertices++ = v; | 
| 275 |  | 
| 276 |                 // normal | 
| 277 |                 *vertices++ = 0.0f; | 
| 278 |                 *vertices++ = 0.0f; | 
| 279 |                 *vertices++ = 1.0f; | 
| 280 |  | 
| 281 |                 // tangent | 
| 282 |                 *vertices++ = 1.0f; | 
| 283 |                 *vertices++ = 0.0f; | 
| 284 |                 *vertices++ = 0.0f; | 
| 285 |                 *vertices++ = 1.0f; | 
| 286 |             } | 
| 287 |         } | 
| 288 |         break; | 
| 289 |     } | 
| 290 |     } // switch (normal) | 
| 291 | } | 
| 292 |  | 
| 293 | void (const QSize &resolution, quint16 *indices, quint16 &baseVertex) | 
| 294 | { | 
| 295 |     // Populate indices taking care to get correct CCW winding on all faces | 
| 296 |     // Iterate over v direction (rows) | 
| 297 |     for (int j = 0; j < resolution.height() - 1; ++j) { | 
| 298 |         const int rowStartIndex = j * resolution.width() + baseVertex; | 
| 299 |         const int nextRowStartIndex = (j + 1) * resolution.width() + baseVertex; | 
| 300 |  | 
| 301 |         // Iterate over u direction (columns) | 
| 302 |         for (int i = 0; i < resolution.width() - 1; ++i) { | 
| 303 |             // Split quad into two triangles | 
| 304 |             *indices++ = rowStartIndex + i; | 
| 305 |             *indices++ = rowStartIndex + i + 1; | 
| 306 |             *indices++ = nextRowStartIndex + i; | 
| 307 |  | 
| 308 |             *indices++ = nextRowStartIndex + i; | 
| 309 |             *indices++ = rowStartIndex + i + 1; | 
| 310 |             *indices++ = nextRowStartIndex + i + 1; | 
| 311 |         } | 
| 312 |     } | 
| 313 |     baseVertex += resolution.width() * resolution.height(); | 
| 314 | } | 
| 315 |  | 
| 316 | QByteArray (float xExtent, | 
| 317 |                                   float yExtent, | 
| 318 |                                   float zExtent, | 
| 319 |                                   const QSize &yzResolution, | 
| 320 |                                   const QSize &xzResolution, | 
| 321 |                                   const QSize &xyResolution) | 
| 322 | { | 
| 323 |     Q_ASSERT(xExtent > 0.0f && yExtent > 0.0f && zExtent > 0.0); | 
| 324 |     Q_ASSERT(yzResolution.width() >= 2 && yzResolution.height() >=2); | 
| 325 |     Q_ASSERT(xzResolution.width() >= 2 && xzResolution.height() >=2); | 
| 326 |     Q_ASSERT(xyResolution.width() >= 2 && xyResolution.height() >=2); | 
| 327 |  | 
| 328 |     const int yzVerts = yzResolution.width() * yzResolution.height(); | 
| 329 |     const int xzVerts = xzResolution.width() * xzResolution.height(); | 
| 330 |     const int xyVerts = xyResolution.width() * xyResolution.height(); | 
| 331 |     const int nVerts = 2 * (yzVerts + xzVerts + xyVerts); | 
| 332 |  | 
| 333 |     const quint32 elementSize = 3 + 3 + 2 + 4; | 
| 334 |     const quint32 stride = elementSize * sizeof(float); | 
| 335 |     QByteArray vertexBytes; | 
| 336 |     vertexBytes.resize(size: stride * nVerts); | 
| 337 |     float* vertices = reinterpret_cast<float*>(vertexBytes.data()); | 
| 338 |  | 
| 339 |     createPlaneVertexData(w: yExtent, h: zExtent, resolution: yzResolution, normal: PositiveX, planeDistance: xExtent * 0.5f, vertices); | 
| 340 |     vertices += yzVerts * elementSize; | 
| 341 |     createPlaneVertexData(w: yExtent, h: zExtent, resolution: yzResolution, normal: NegativeX, planeDistance: -xExtent * 0.5f, vertices); | 
| 342 |     vertices += yzVerts * elementSize; | 
| 343 |     createPlaneVertexData(w: xExtent, h: zExtent, resolution: xzResolution, normal: PositiveY, planeDistance: yExtent * 0.5f, vertices); | 
| 344 |     vertices += xzVerts * elementSize; | 
| 345 |     createPlaneVertexData(w: xExtent, h: zExtent, resolution: xzResolution, normal: NegativeY, planeDistance: -yExtent * 0.5f, vertices); | 
| 346 |     vertices += xzVerts * elementSize; | 
| 347 |     createPlaneVertexData(w: xExtent, h: yExtent, resolution: xyResolution, normal: PositiveZ, planeDistance: zExtent * 0.5f, vertices); | 
| 348 |     vertices += xyVerts * elementSize; | 
| 349 |     createPlaneVertexData(w: xExtent, h: yExtent, resolution: xyResolution, normal: NegativeZ, planeDistance: -zExtent * 0.5f, vertices); | 
| 350 |  | 
| 351 |     return vertexBytes; | 
| 352 | } | 
| 353 |  | 
| 354 | QByteArray (const QSize &yzResolution, | 
| 355 |                                  const QSize &xzResolution, | 
| 356 |                                  const QSize &xyResolution) | 
| 357 | { | 
| 358 |     Q_ASSERT(yzResolution.width() >= 2 && yzResolution.height() >= 2); | 
| 359 |     Q_ASSERT(xzResolution.width() >= 2 && xzResolution.height() >= 2); | 
| 360 |     Q_ASSERT(xyResolution.width() >= 2 && xyResolution.height() >= 2); | 
| 361 |  | 
| 362 |     const int yzIndices = 2 * 3 * (yzResolution.width() - 1) * (yzResolution.height() - 1); | 
| 363 |     const int xzIndices = 2 * 3 * (xzResolution.width() - 1) * (xzResolution.height() - 1); | 
| 364 |     const int xyIndices = 2 * 3 * (xyResolution.width() - 1) * (xyResolution.height() - 1); | 
| 365 |     const int indexCount = 2 * (yzIndices + xzIndices + xyIndices); | 
| 366 |  | 
| 367 |     QByteArray indexData; | 
| 368 |     indexData.resize(size: indexCount * sizeof(quint16)); | 
| 369 |     quint16 *indices = reinterpret_cast<quint16 *>(indexData.data()); | 
| 370 |     quint16 baseIndex = 0; | 
| 371 |  | 
| 372 |     createPlaneIndexData(resolution: yzResolution, indices, baseVertex&: baseIndex); | 
| 373 |     indices += yzIndices; | 
| 374 |     createPlaneIndexData(resolution: yzResolution, indices, baseVertex&: baseIndex); | 
| 375 |     indices += yzIndices; | 
| 376 |     createPlaneIndexData(resolution: xzResolution, indices, baseVertex&: baseIndex); | 
| 377 |     indices += xzIndices; | 
| 378 |     createPlaneIndexData(resolution: xzResolution, indices, baseVertex&: baseIndex); | 
| 379 |     indices += xzIndices; | 
| 380 |     createPlaneIndexData(resolution: xyResolution, indices, baseVertex&: baseIndex); | 
| 381 |     indices += xyIndices; | 
| 382 |     createPlaneIndexData(resolution: xyResolution, indices, baseVertex&: baseIndex); | 
| 383 |  | 
| 384 |     return indexData; | 
| 385 | } | 
| 386 |  | 
| 387 | } // anonymous | 
| 388 |  | 
| 389 | class  : public QBufferDataGenerator | 
| 390 | { | 
| 391 | public: | 
| 392 |     explicit (float xExtent, | 
| 393 |                                        float yExtent, | 
| 394 |                                        float zExtent, | 
| 395 |                                        const QSize &yzResolution, | 
| 396 |                                        const QSize &xzResolution, | 
| 397 |                                        const QSize &xyResolution) | 
| 398 |         : m_xExtent(xExtent) | 
| 399 |         , m_yExtent(yExtent) | 
| 400 |         , m_zExtent(zExtent) | 
| 401 |         , m_yzFaceResolution(yzResolution) | 
| 402 |         , m_xzFaceResolution(xzResolution) | 
| 403 |         , m_xyFaceResolution(xyResolution) | 
| 404 |     {} | 
| 405 |  | 
| 406 |     () {} | 
| 407 |  | 
| 408 |     QByteArray () final | 
| 409 |     { | 
| 410 |         return createCuboidVertexData(xExtent: m_xExtent, yExtent: m_yExtent, zExtent: m_zExtent, | 
| 411 |                                       yzResolution: m_yzFaceResolution, xzResolution: m_xzFaceResolution, xyResolution: m_xyFaceResolution); | 
| 412 |     } | 
| 413 |  | 
| 414 |     bool (const QBufferDataGenerator &other) const final | 
| 415 |     { | 
| 416 |         const CuboidVertexBufferFunctor *otherFunctor = functor_cast<CuboidVertexBufferFunctor>(other: &other); | 
| 417 |         if (otherFunctor != nullptr) | 
| 418 |             return (otherFunctor->m_xExtent == m_xExtent && | 
| 419 |                     otherFunctor->m_yExtent == m_yExtent && | 
| 420 |                     otherFunctor->m_zExtent == m_zExtent && | 
| 421 |                     otherFunctor->m_yzFaceResolution == m_yzFaceResolution && | 
| 422 |                     otherFunctor->m_xzFaceResolution == m_xzFaceResolution && | 
| 423 |                     otherFunctor->m_xyFaceResolution == m_xyFaceResolution); | 
| 424 |         return false; | 
| 425 |     } | 
| 426 |  | 
| 427 |     QT3D_FUNCTOR(CuboidVertexBufferFunctor) | 
| 428 |  | 
| 429 | private: | 
| 430 |     float ; | 
| 431 |     float ; | 
| 432 |     float ; | 
| 433 |     QSize ; | 
| 434 |     QSize ; | 
| 435 |     QSize ; | 
| 436 | }; | 
| 437 |  | 
| 438 | class  : public QBufferDataGenerator | 
| 439 | { | 
| 440 | public: | 
| 441 |     explicit (const QSize &yzResolution, | 
| 442 |                                       const QSize &xzResolution, | 
| 443 |                                       const QSize &xyResolution) | 
| 444 |         : m_yzFaceResolution(yzResolution) | 
| 445 |         , m_xzFaceResolution(xzResolution) | 
| 446 |         , m_xyFaceResolution(xyResolution) | 
| 447 |     {} | 
| 448 |  | 
| 449 |     () {} | 
| 450 |  | 
| 451 |     QByteArray () final | 
| 452 |     { | 
| 453 |         return createCuboidIndexData(yzResolution: m_yzFaceResolution, xzResolution: m_xzFaceResolution, xyResolution: m_xyFaceResolution); | 
| 454 |     } | 
| 455 |  | 
| 456 |     bool (const QBufferDataGenerator &other) const final | 
| 457 |     { | 
| 458 |         const CuboidIndexBufferFunctor *otherFunctor = functor_cast<CuboidIndexBufferFunctor>(other: &other); | 
| 459 |         if (otherFunctor != nullptr) | 
| 460 |             return (otherFunctor->m_yzFaceResolution == m_yzFaceResolution && | 
| 461 |                     otherFunctor->m_xzFaceResolution == m_xzFaceResolution && | 
| 462 |                     otherFunctor->m_xyFaceResolution == m_xyFaceResolution); | 
| 463 |         return false; | 
| 464 |     } | 
| 465 |  | 
| 466 |     QT3D_FUNCTOR(CuboidIndexBufferFunctor) | 
| 467 |  | 
| 468 | private: | 
| 469 |     QSize ; | 
| 470 |     QSize ; | 
| 471 |     QSize ; | 
| 472 | }; | 
| 473 |  | 
| 474 | QCuboidGeometryPrivate::() | 
| 475 |     : QGeometryPrivate() | 
| 476 |     , m_xExtent(1.0f) | 
| 477 |     , m_yExtent(1.0f) | 
| 478 |     , m_zExtent(1.0f) | 
| 479 |     , m_yzFaceResolution(2, 2) | 
| 480 |     , m_xzFaceResolution(2, 2) | 
| 481 |     , m_xyFaceResolution(2, 2) | 
| 482 |     , m_positionAttribute(nullptr) | 
| 483 |     , m_normalAttribute(nullptr) | 
| 484 |     , m_texCoordAttribute(nullptr) | 
| 485 |     , m_tangentAttribute(nullptr) | 
| 486 |     , m_indexAttribute(nullptr) | 
| 487 |     , m_vertexBuffer(nullptr) | 
| 488 |     , m_indexBuffer(nullptr) | 
| 489 | { | 
| 490 | } | 
| 491 |  | 
| 492 | void QCuboidGeometryPrivate::() | 
| 493 | { | 
| 494 |     Q_Q(QCuboidGeometry); | 
| 495 |     m_positionAttribute = new Qt3DRender::QAttribute(q); | 
| 496 |     m_normalAttribute = new Qt3DRender::QAttribute(q); | 
| 497 |     m_texCoordAttribute = new Qt3DRender::QAttribute(q); | 
| 498 |     m_tangentAttribute = new Qt3DRender::QAttribute(q); | 
| 499 |     m_indexAttribute = new Qt3DRender::QAttribute(q); | 
| 500 |     m_vertexBuffer = new Qt3DRender::QBuffer(q); | 
| 501 |     m_indexBuffer = new Qt3DRender::QBuffer(q); | 
| 502 |  | 
| 503 |     // vec3 pos vec2 tex vec3 normal vec4 tangent | 
| 504 |     const quint32 stride = (3 + 2 + 3 + 4) * sizeof(float); | 
| 505 |     const int yzIndices = 2 * 3 * (m_yzFaceResolution.width() - 1) * (m_yzFaceResolution.height() - 1); | 
| 506 |     const int xzIndices = 2 * 3 * (m_xzFaceResolution.width() - 1) * (m_xzFaceResolution.height() - 1); | 
| 507 |     const int xyIndices = 2 * 3 * (m_xyFaceResolution.width() - 1) * (m_xyFaceResolution.height() - 1); | 
| 508 |     const int yzVerts = m_yzFaceResolution.width() * m_yzFaceResolution.height(); | 
| 509 |     const int xzVerts = m_xzFaceResolution.width() * m_xzFaceResolution.height(); | 
| 510 |     const int xyVerts = m_xyFaceResolution.width() * m_xyFaceResolution.height(); | 
| 511 |  | 
| 512 |     const int nVerts = 2 * (yzVerts + xzVerts + xyVerts); | 
| 513 |     const int indexCount = 2 * (yzIndices + xzIndices + xyIndices); | 
| 514 |  | 
| 515 |     m_positionAttribute->setName(QAttribute::defaultPositionAttributeName()); | 
| 516 |     m_positionAttribute->setVertexBaseType(QAttribute::Float); | 
| 517 |     m_positionAttribute->setVertexSize(3); | 
| 518 |     m_positionAttribute->setAttributeType(QAttribute::VertexAttribute); | 
| 519 |     m_positionAttribute->setBuffer(m_vertexBuffer); | 
| 520 |     m_positionAttribute->setByteStride(stride); | 
| 521 |     m_positionAttribute->setCount(nVerts); | 
| 522 |  | 
| 523 |     m_texCoordAttribute->setName(QAttribute::defaultTextureCoordinateAttributeName()); | 
| 524 |     m_texCoordAttribute->setVertexBaseType(QAttribute::Float); | 
| 525 |     m_texCoordAttribute->setVertexSize(2); | 
| 526 |     m_texCoordAttribute->setAttributeType(QAttribute::VertexAttribute); | 
| 527 |     m_texCoordAttribute->setBuffer(m_vertexBuffer); | 
| 528 |     m_texCoordAttribute->setByteStride(stride); | 
| 529 |     m_texCoordAttribute->setByteOffset(3 * sizeof(float)); | 
| 530 |     m_texCoordAttribute->setCount(nVerts); | 
| 531 |  | 
| 532 |     m_normalAttribute->setName(QAttribute::defaultNormalAttributeName()); | 
| 533 |     m_normalAttribute->setVertexBaseType(QAttribute::Float); | 
| 534 |     m_normalAttribute->setVertexSize(3); | 
| 535 |     m_normalAttribute->setAttributeType(QAttribute::VertexAttribute); | 
| 536 |     m_normalAttribute->setBuffer(m_vertexBuffer); | 
| 537 |     m_normalAttribute->setByteStride(stride); | 
| 538 |     m_normalAttribute->setByteOffset(5 * sizeof(float)); | 
| 539 |     m_normalAttribute->setCount(nVerts); | 
| 540 |  | 
| 541 |     m_tangentAttribute->setName(QAttribute::defaultTangentAttributeName()); | 
| 542 |     m_tangentAttribute->setVertexBaseType(QAttribute::Float); | 
| 543 |     m_tangentAttribute->setVertexSize(4); | 
| 544 |     m_tangentAttribute->setAttributeType(QAttribute::VertexAttribute); | 
| 545 |     m_tangentAttribute->setBuffer(m_vertexBuffer); | 
| 546 |     m_tangentAttribute->setByteStride(stride); | 
| 547 |     m_tangentAttribute->setByteOffset(8 * sizeof(float)); | 
| 548 |     m_tangentAttribute->setCount(nVerts); | 
| 549 |  | 
| 550 |     m_indexAttribute->setAttributeType(QAttribute::IndexAttribute); | 
| 551 |     m_indexAttribute->setVertexBaseType(QAttribute::UnsignedShort); | 
| 552 |     m_indexAttribute->setBuffer(m_indexBuffer); | 
| 553 |  | 
| 554 |     m_indexAttribute->setCount(indexCount); | 
| 555 |  | 
| 556 |     m_vertexBuffer->setDataGenerator(QSharedPointer<CuboidVertexBufferFunctor>::create(arguments&: m_xExtent, arguments&: m_yExtent, arguments&: m_zExtent, | 
| 557 |                                                                                        arguments&: m_yzFaceResolution, arguments&: m_xzFaceResolution, arguments&: m_xyFaceResolution)); | 
| 558 |     m_indexBuffer->setDataGenerator(QSharedPointer<CuboidIndexBufferFunctor>::create(arguments&: m_yzFaceResolution, arguments&: m_xzFaceResolution, arguments&: m_xyFaceResolution)); | 
| 559 |  | 
| 560 |     q->addAttribute(attribute: m_positionAttribute); | 
| 561 |     q->addAttribute(attribute: m_texCoordAttribute); | 
| 562 |     q->addAttribute(attribute: m_normalAttribute); | 
| 563 |     q->addAttribute(attribute: m_tangentAttribute); | 
| 564 |     q->addAttribute(attribute: m_indexAttribute); | 
| 565 | } | 
| 566 |  | 
| 567 | /*! | 
| 568 |  * \qmltype CuboidGeometry | 
| 569 |  * \instantiates Qt3DExtras::QCuboidGeometry | 
| 570 |  * \inqmlmodule Qt3D.Extras | 
| 571 |  * \brief CuboidGeometry allows creation of a cuboid in 3D space. | 
| 572 |  * | 
| 573 |  * The CuboidGeometry type is most commonly used internally by the CuboidMesh type | 
| 574 |  * but can also be used in custom GeometryRenderer types. | 
| 575 |  */ | 
| 576 |  | 
| 577 | /*! | 
| 578 |  * \qmlproperty real CuboidGeometry::xExtent | 
| 579 |  * | 
| 580 |  * Holds the x extent of the geometry. | 
| 581 |  */ | 
| 582 |  | 
| 583 | /*! | 
| 584 |  * \qmlproperty real CuboidGeometry::yExtent | 
| 585 |  * | 
| 586 |  * Holds the y extent of the geometry. | 
| 587 |  */ | 
| 588 |  | 
| 589 | /*! | 
| 590 |  * \qmlproperty real CuboidGeometry::zExtent | 
| 591 |  * | 
| 592 |  * Holds the z extent of the geometry. | 
| 593 |  */ | 
| 594 |  | 
| 595 | /*! | 
| 596 |  * \qmlproperty size CuboidGeometry::yzMeshResolution | 
| 597 |  * | 
| 598 |  * Holds the y-z resolution. | 
| 599 |  * The width and height values of this property specify the number of vertices generated for | 
| 600 |  * the y-z faces of the mesh. | 
| 601 |  */ | 
| 602 |  | 
| 603 | /*! | 
| 604 |  * \qmlproperty size CuboidGeometry::xzMeshResolution | 
| 605 |  * | 
| 606 |  * Holds the x-z resolution. | 
| 607 |  * The width and height values of this property specify the number of vertices generated for | 
| 608 |  * the x-z faces of the mesh. | 
| 609 |  */ | 
| 610 |  | 
| 611 | /*! | 
| 612 |  * \qmlproperty size CuboidGeometry::xyMeshResolution | 
| 613 |  * | 
| 614 |  * Holds the x-y resolution. | 
| 615 |  * The width and height values of this property specify the number of vertices generated for | 
| 616 |  * the x-y faces of the mesh. | 
| 617 |  */ | 
| 618 |  | 
| 619 | /*! | 
| 620 |  * \qmlproperty Attribute CuboidGeometry::positionAttribute | 
| 621 |  * | 
| 622 |  * Holds the geometry position attribute. | 
| 623 |  */ | 
| 624 |  | 
| 625 | /*! | 
| 626 |  * \qmlproperty Attribute CuboidGeometry::normalAttribute | 
| 627 |  * | 
| 628 |  * Holds the geometry normal attribute. | 
| 629 |  */ | 
| 630 |  | 
| 631 | /*! | 
| 632 |  * \qmlproperty Attribute CuboidGeometry::texCoordAttribute | 
| 633 |  * | 
| 634 |  * Holds the geometry texture coordinate attribute. | 
| 635 |  */ | 
| 636 |  | 
| 637 | /*! | 
| 638 |  * \qmlproperty Attribute CuboidGeometry::tangentAttribute | 
| 639 |  * | 
| 640 |  * Holds the geometry tangent attribute. | 
| 641 |  */ | 
| 642 |  | 
| 643 | /*! | 
| 644 |  * \qmlproperty Attribute CuboidGeometry::indexAttribute | 
| 645 |  * | 
| 646 |  * Holds the geometry index attribute. | 
| 647 |  */ | 
| 648 |  | 
| 649 | /*! | 
| 650 |  * \class Qt3DExtras::QCuboidGeometry | 
| 651 |    \ingroup qt3d-extras-geometries | 
| 652 |  * \inheaderfile Qt3DExtras/QCuboidGeometry | 
| 653 |  * \inmodule Qt3DExtras | 
| 654 |  * \brief The QCuboidGeometry class allows creation of a cuboid in 3D space. | 
| 655 |  * \since 5.7 | 
| 656 |  * \ingroup geometries | 
| 657 |  * \inherits Qt3DRender::QGeometry | 
| 658 |  * | 
| 659 |  * The QCuboidGeometry class is most commonly used internally by the QCuboidMesh | 
| 660 |  * but can also be used in custom Qt3DRender::QGeometryRenderer subclasses. | 
| 661 |  */ | 
| 662 |  | 
| 663 | /*! | 
| 664 |  * Constructs a new QCuboidGeometry with \a parent. | 
| 665 |  */ | 
| 666 | QCuboidGeometry::(QNode *parent) | 
| 667 |     : QGeometry(*new QCuboidGeometryPrivate(), parent) | 
| 668 | { | 
| 669 |     Q_D(QCuboidGeometry); | 
| 670 |     d->init(); | 
| 671 | } | 
| 672 |  | 
| 673 | /*! | 
| 674 |  * \internal | 
| 675 |  */ | 
| 676 | QCuboidGeometry::(QCuboidGeometryPrivate &dd, QNode *parent) | 
| 677 |     : QGeometry(dd, parent) | 
| 678 | { | 
| 679 |     Q_D(QCuboidGeometry); | 
| 680 |     d->init(); | 
| 681 | } | 
| 682 |  | 
| 683 | /*! | 
| 684 |  * \internal | 
| 685 |  */ | 
| 686 | QCuboidGeometry::() | 
| 687 | { | 
| 688 | } | 
| 689 |  | 
| 690 | /*! | 
| 691 |  * Updates indices based on mesh resolutions. | 
| 692 |  */ | 
| 693 | void QCuboidGeometry::() | 
| 694 | { | 
| 695 |     Q_D(QCuboidGeometry); | 
| 696 |     const int yzIndices = 2 * 3 * (d->m_yzFaceResolution.width() - 1) * (d->m_yzFaceResolution.height() - 1); | 
| 697 |     const int xzIndices = 2 * 3 * (d->m_xzFaceResolution.width() - 1) * (d->m_xzFaceResolution.height() - 1); | 
| 698 |     const int xyIndices = 2 * 3 * (d->m_xyFaceResolution.width() - 1) * (d->m_xyFaceResolution.height() - 1); | 
| 699 |     const int indexCount = 2 * (yzIndices + xzIndices + xyIndices); | 
| 700 |  | 
| 701 |     d->m_indexAttribute->setCount(indexCount); | 
| 702 |     d->m_indexBuffer->setDataGenerator(QSharedPointer<CuboidIndexBufferFunctor>::create(arguments&: d->m_yzFaceResolution, arguments&: d->m_xzFaceResolution, arguments&: d->m_xyFaceResolution)); | 
| 703 |  | 
| 704 | } | 
| 705 |  | 
| 706 | /*! | 
| 707 |  * Updates vertices based on mesh resolutions. | 
| 708 |  */ | 
| 709 | void QCuboidGeometry::() | 
| 710 | { | 
| 711 |     Q_D(QCuboidGeometry); | 
| 712 |     const int yzVerts = d->m_yzFaceResolution.width() * d->m_yzFaceResolution.height(); | 
| 713 |     const int xzVerts = d->m_xzFaceResolution.width() * d->m_xzFaceResolution.height(); | 
| 714 |     const int xyVerts = d->m_xyFaceResolution.width() * d->m_xyFaceResolution.height(); | 
| 715 |     const int nVerts = 2 * (yzVerts + xzVerts + xyVerts); | 
| 716 |  | 
| 717 |     d->m_positionAttribute->setCount(nVerts); | 
| 718 |     d->m_normalAttribute->setCount(nVerts); | 
| 719 |     d->m_texCoordAttribute->setCount(nVerts); | 
| 720 |     d->m_tangentAttribute->setCount(nVerts); | 
| 721 |  | 
| 722 |     d->m_vertexBuffer->setDataGenerator(QSharedPointer<CuboidVertexBufferFunctor>::create(arguments&: d->m_xExtent, arguments&: d->m_yExtent, arguments&: d->m_zExtent, | 
| 723 |                                                                                           arguments&: d->m_yzFaceResolution, arguments&: d->m_xzFaceResolution, arguments&: d->m_xyFaceResolution)); | 
| 724 | } | 
| 725 |  | 
| 726 | void QCuboidGeometry::(float xExtent) | 
| 727 | { | 
| 728 |     Q_D(QCuboidGeometry); | 
| 729 |     if (d->m_xExtent != xExtent) { | 
| 730 |         d->m_xExtent = xExtent; | 
| 731 |         updateVertices(); | 
| 732 |         emit xExtentChanged(xExtent); | 
| 733 |     } | 
| 734 | } | 
| 735 |  | 
| 736 | void QCuboidGeometry::(float yExtent) | 
| 737 | { | 
| 738 |     Q_D(QCuboidGeometry); | 
| 739 |     if (d->m_yExtent != yExtent) { | 
| 740 |         d->m_yExtent = yExtent; | 
| 741 |         updateVertices(); | 
| 742 |         emit yExtentChanged(yExtent); | 
| 743 |     } | 
| 744 | } | 
| 745 |  | 
| 746 | void QCuboidGeometry::(float zExtent) | 
| 747 | { | 
| 748 |     Q_D(QCuboidGeometry); | 
| 749 |     if (d->m_zExtent != zExtent) { | 
| 750 |         d->m_zExtent = zExtent; | 
| 751 |         updateVertices(); | 
| 752 |         emit zExtentChanged(zExtent); | 
| 753 |     } | 
| 754 | } | 
| 755 |  | 
| 756 | void QCuboidGeometry::(const QSize &resolution) | 
| 757 | { | 
| 758 |     Q_D(QCuboidGeometry); | 
| 759 |     if (d->m_yzFaceResolution != resolution) { | 
| 760 |         d->m_yzFaceResolution = resolution; | 
| 761 |         updateVertices(); | 
| 762 |         updateIndices(); | 
| 763 |         emit yzMeshResolutionChanged(yzMeshResolution: resolution); | 
| 764 |     } | 
| 765 | } | 
| 766 |  | 
| 767 | void QCuboidGeometry::(const QSize &resolution) | 
| 768 | { | 
| 769 |     Q_D(QCuboidGeometry); | 
| 770 |     if (d->m_xzFaceResolution != resolution) { | 
| 771 |         d->m_xzFaceResolution = resolution; | 
| 772 |         updateVertices(); | 
| 773 |         updateIndices(); | 
| 774 |         emit xzMeshResolutionChanged(xzMeshResolution: resolution); | 
| 775 |     } | 
| 776 | } | 
| 777 |  | 
| 778 | void QCuboidGeometry::(const QSize &resolution) | 
| 779 | { | 
| 780 |     Q_D(QCuboidGeometry); | 
| 781 |     if (d->m_xyFaceResolution != resolution) { | 
| 782 |         d->m_xyFaceResolution = resolution; | 
| 783 |         updateVertices(); | 
| 784 |         updateIndices(); | 
| 785 |         emit xyMeshResolutionChanged(xyMeshResolution: resolution); | 
| 786 |     } | 
| 787 | } | 
| 788 |  | 
| 789 | /*! | 
| 790 |  * \property QCuboidGeometry::xExtent | 
| 791 |  * | 
| 792 |  * Holds the x extent of the geometry. | 
| 793 |  */ | 
| 794 | float QCuboidGeometry::() const | 
| 795 | { | 
| 796 |     Q_D(const QCuboidGeometry); | 
| 797 |     return d->m_xExtent; | 
| 798 | } | 
| 799 |  | 
| 800 | /*! | 
| 801 |  * \property QCuboidGeometry::yExtent | 
| 802 |  * | 
| 803 |  * Holds the y extent of the geometry. | 
| 804 |  */ | 
| 805 | float QCuboidGeometry::() const | 
| 806 | { | 
| 807 |     Q_D(const QCuboidGeometry); | 
| 808 |     return d->m_yExtent; | 
| 809 | } | 
| 810 |  | 
| 811 | /*! | 
| 812 |  * \property QCuboidGeometry::zExtent | 
| 813 |  * | 
| 814 |  * Holds the z extent of the geometry. | 
| 815 |  */ | 
| 816 | float QCuboidGeometry::() const | 
| 817 | { | 
| 818 |     Q_D(const QCuboidGeometry); | 
| 819 |     return d->m_zExtent; | 
| 820 | } | 
| 821 |  | 
| 822 | /*! | 
| 823 |  * \property QCuboidGeometry::yzMeshResolution | 
| 824 |  * | 
| 825 |  * Holds the y-z resolution. | 
| 826 |  * The width and height values of this property specify the number of vertices generated for | 
| 827 |  * the y-z faces of the mesh. | 
| 828 |  */ | 
| 829 | QSize QCuboidGeometry::() const | 
| 830 | { | 
| 831 |     Q_D(const QCuboidGeometry); | 
| 832 |     return d->m_yzFaceResolution; | 
| 833 | } | 
| 834 |  | 
| 835 | /*! | 
| 836 |  * \property QCuboidGeometry::xzMeshResolution | 
| 837 |  * | 
| 838 |  * Holds the x-z resolution. | 
| 839 |  * The width and height values of this property specify the number of vertices generated for | 
| 840 |  * the x-z faces of the mesh. | 
| 841 |  */ | 
| 842 | QSize QCuboidGeometry::() const | 
| 843 | { | 
| 844 |     Q_D(const QCuboidGeometry); | 
| 845 |     return d->m_xyFaceResolution; | 
| 846 | } | 
| 847 |  | 
| 848 | /*! | 
| 849 |  * \property QCuboidGeometry::xyMeshResolution | 
| 850 |  * | 
| 851 |  * Holds the x-y resolution. | 
| 852 |  * The width and height values of this property specify the number of vertices generated for | 
| 853 |  * the x-y faces of the mesh. | 
| 854 |  */ | 
| 855 | QSize QCuboidGeometry::() const | 
| 856 | { | 
| 857 |     Q_D(const QCuboidGeometry); | 
| 858 |     return d->m_xzFaceResolution; | 
| 859 | } | 
| 860 |  | 
| 861 | /*! | 
| 862 |  * \property QCuboidGeometry::positionAttribute | 
| 863 |  * | 
| 864 |  * Holds the geometry position attribute. | 
| 865 |  */ | 
| 866 | QAttribute *QCuboidGeometry::() const | 
| 867 | { | 
| 868 |     Q_D(const QCuboidGeometry); | 
| 869 |     return d->m_positionAttribute; | 
| 870 | } | 
| 871 |  | 
| 872 | /*! | 
| 873 |  * \property QCuboidGeometry::normalAttribute | 
| 874 |  * | 
| 875 |  * Holds the geometry normal attribute. | 
| 876 |  */ | 
| 877 | QAttribute *QCuboidGeometry::() const | 
| 878 | { | 
| 879 |     Q_D(const QCuboidGeometry); | 
| 880 |     return d->m_normalAttribute; | 
| 881 | } | 
| 882 |  | 
| 883 | /*! | 
| 884 |  * \property QCuboidGeometry::texCoordAttribute | 
| 885 |  * | 
| 886 |  * Holds the geometry texture coordinate attribute. | 
| 887 |  */ | 
| 888 | QAttribute *QCuboidGeometry::() const | 
| 889 | { | 
| 890 |     Q_D(const QCuboidGeometry); | 
| 891 |     return d->m_texCoordAttribute; | 
| 892 | } | 
| 893 |  | 
| 894 | /*! | 
| 895 |  * \property QCuboidGeometry::tangentAttribute | 
| 896 |  * | 
| 897 |  * Holds the geometry tangent attribute. | 
| 898 |  */ | 
| 899 | QAttribute *QCuboidGeometry::() const | 
| 900 | { | 
| 901 |     Q_D(const QCuboidGeometry); | 
| 902 |     return d->m_tangentAttribute; | 
| 903 | } | 
| 904 |  | 
| 905 | /*! | 
| 906 |  * \property QCuboidGeometry::indexAttribute | 
| 907 |  * | 
| 908 |  * Holds the geometry index attribute. | 
| 909 |  */ | 
| 910 | QAttribute *QCuboidGeometry::() const | 
| 911 | { | 
| 912 |     Q_D(const QCuboidGeometry); | 
| 913 |     return d->m_indexAttribute; | 
| 914 | } | 
| 915 |  | 
| 916 | } //  Qt3DExtras | 
| 917 |  | 
| 918 | QT_END_NAMESPACE | 
| 919 |  |