| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2019 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:BSD$ |
| 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 | ** BSD License Usage |
| 18 | ** Alternatively, you may use this file under the terms of the BSD license |
| 19 | ** as follows: |
| 20 | ** |
| 21 | ** "Redistribution and use in source and binary forms, with or without |
| 22 | ** modification, are permitted provided that the following conditions are |
| 23 | ** met: |
| 24 | ** * Redistributions of source code must retain the above copyright |
| 25 | ** notice, this list of conditions and the following disclaimer. |
| 26 | ** * Redistributions in binary form must reproduce the above copyright |
| 27 | ** notice, this list of conditions and the following disclaimer in |
| 28 | ** the documentation and/or other materials provided with the |
| 29 | ** distribution. |
| 30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
| 31 | ** contributors may be used to endorse or promote products derived |
| 32 | ** from this software without specific prior written permission. |
| 33 | ** |
| 34 | ** |
| 35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
| 46 | ** |
| 47 | ** $QT_END_LICENSE$ |
| 48 | ** |
| 49 | ****************************************************************************/ |
| 50 | |
| 51 | #include <QGuiApplication> |
| 52 | |
| 53 | #include <Qt3DCore/QEntity> |
| 54 | #include <Qt3DRender/QCamera> |
| 55 | #include <Qt3DRender/QCameraLens> |
| 56 | #include <Qt3DCore/QTransform> |
| 57 | #include <Qt3DCore/QAspectEngine> |
| 58 | |
| 59 | #include <Qt3DInput/QInputAspect> |
| 60 | |
| 61 | #include <Qt3DRender/QRenderStateSet> |
| 62 | #include <Qt3DRender/QRenderAspect> |
| 63 | #include <Qt3DExtras/QForwardRenderer> |
| 64 | #include <Qt3DExtras/QPerVertexColorMaterial> |
| 65 | |
| 66 | #include <Qt3DRender/QGeometryRenderer> |
| 67 | #include <Qt3DRender/QGeometry> |
| 68 | #include <Qt3DRender/QAttribute> |
| 69 | #include <Qt3DRender/QBuffer> |
| 70 | |
| 71 | #include <QPropertyAnimation> |
| 72 | #include <Qt3DExtras/qt3dwindow.h> |
| 73 | #include <Qt3DExtras/qorbitcameracontroller.h> |
| 74 | #include <Qt3DRender/QParameter> |
| 75 | #include <Qt3DRender/QEffect> |
| 76 | #include <Qt3DRender/QTechnique> |
| 77 | #include <Qt3DRender/QAbstractTexture> |
| 78 | #include <Qt3DRender/QShaderProgram> |
| 79 | #include <Qt3DRender/QRenderPass> |
| 80 | #include <Qt3DRender/QBlendEquation> |
| 81 | #include <Qt3DRender/QBlendEquationArguments> |
| 82 | #include <Qt3DRender/QFilterKey> |
| 83 | #include <Qt3DRender/QGraphicsApiFilter> |
| 84 | #include <Qt3DRender/QRenderSurfaceSelector> |
| 85 | #include <Qt3DRender/QViewport> |
| 86 | #include <Qt3DRender/QCameraSelector> |
| 87 | #include <Qt3DRender/QNoDraw> |
| 88 | #include <QColor> |
| 89 | #include <QVector2D> |
| 90 | #include <QUrl> |
| 91 | #include <QTimer> |
| 92 | #include <Qt3DRender/QMaterial> |
| 93 | #include <Qt3DRender/QFilterKey> |
| 94 | #include <Qt3DRender/QTechnique> |
| 95 | #include <Qt3DRender/QMaterial> |
| 96 | #include <Qt3DRender/QTexture> |
| 97 | #include <qmath.h> |
| 98 | |
| 99 | static const constexpr auto vertex_shader = R"_(#version 450 |
| 100 | |
| 101 | /** |
| 102 | * Unicode comment: Ѧ𝙱ƇᗞΣ |
| 103 | */ |
| 104 | |
| 105 | layout(location = 0) in vec3 vertexPosition; |
| 106 | layout(location = 1) in vec3 vertexColor; |
| 107 | layout(location = 0) out vec3 color; |
| 108 | |
| 109 | layout(std140, binding = 0) uniform qt3d_render_view_uniforms { |
| 110 | mat4 viewMatrix; |
| 111 | mat4 projectionMatrix; |
| 112 | mat4 viewProjectionMatrix; |
| 113 | mat4 inverseViewMatrix; |
| 114 | mat4 inverseProjectionMatrix; |
| 115 | mat4 inverseViewProjectionMatrix; |
| 116 | mat4 viewportMatrix; |
| 117 | mat4 inverseViewportMatrix; |
| 118 | vec4 textureTransformMatrix; |
| 119 | vec3 eyePosition; |
| 120 | float aspectRatio; |
| 121 | float gamma; |
| 122 | float exposure; |
| 123 | float time; |
| 124 | }; |
| 125 | layout(std140, binding = 1) uniform qt3d_command_uniforms { |
| 126 | mat4 modelMatrix; |
| 127 | mat4 inverseModelMatrix; |
| 128 | mat4 modelViewMatrix; |
| 129 | mat3 modelNormalMatrix; |
| 130 | mat4 inverseModelViewMatrix; |
| 131 | mat4 mvp; |
| 132 | mat4 inverseModelViewProjectionMatrix; |
| 133 | }; |
| 134 | void main() |
| 135 | { |
| 136 | color = vertexColor; |
| 137 | gl_Position = mvp * vec4(vertexPosition, 1.0); |
| 138 | } |
| 139 | )_" ; |
| 140 | |
| 141 | static const constexpr auto fragment_shader = R"_(#version 450 |
| 142 | |
| 143 | /** |
| 144 | * Unicode comment: Ѧ𝙱ƇᗞΣ |
| 145 | */ |
| 146 | |
| 147 | layout(location = 0) out vec4 fragColor; |
| 148 | layout(location = 0) in vec3 color; |
| 149 | |
| 150 | layout(std140, binding = 0) uniform qt3d_render_view_uniforms { |
| 151 | mat4 viewMatrix; |
| 152 | mat4 projectionMatrix; |
| 153 | mat4 viewProjectionMatrix; |
| 154 | mat4 inverseViewMatrix; |
| 155 | mat4 inverseProjectionMatrix; |
| 156 | mat4 inverseViewProjectionMatrix; |
| 157 | mat4 viewportMatrix; |
| 158 | mat4 inverseViewportMatrix; |
| 159 | vec4 textureTransformMatrix; |
| 160 | vec3 eyePosition; |
| 161 | float aspectRatio; |
| 162 | float gamma; |
| 163 | float exposure; |
| 164 | float time; |
| 165 | }; |
| 166 | layout(std140, binding = 1) uniform qt3d_command_uniforms { |
| 167 | mat4 modelMatrix; |
| 168 | mat4 inverseModelMatrix; |
| 169 | mat4 modelViewMatrix; |
| 170 | mat3 modelNormalMatrix; |
| 171 | mat4 inverseModelViewMatrix; |
| 172 | mat4 mvp; |
| 173 | mat4 inverseModelViewProjectionMatrix; |
| 174 | }; |
| 175 | layout(std140, binding = 2) uniform custom_ubo { |
| 176 | vec3 colorFactor; |
| 177 | }; |
| 178 | |
| 179 | layout(binding = 3) uniform sampler2D myTexture; |
| 180 | void main() |
| 181 | { |
| 182 | vec2 texCoord = color.xz; |
| 183 | vec2 rhiTexCoord = textureTransformMatrix.xy * texCoord+ textureTransformMatrix.zw; |
| 184 | fragColor = vec4(color * colorFactor, 1.0); |
| 185 | |
| 186 | fragColor *= texture(myTexture, rhiTexCoord); |
| 187 | } |
| 188 | |
| 189 | )_" ; |
| 190 | |
| 191 | class Material : public Qt3DRender::QMaterial |
| 192 | { |
| 193 | public: |
| 194 | explicit Material(Qt3DCore::QNode *parent = nullptr) |
| 195 | : QMaterial(parent) |
| 196 | , m_effect(new Qt3DRender::QEffect(this)) |
| 197 | { |
| 198 | setEffect(m_effect); |
| 199 | |
| 200 | m_testParam = new Qt3DRender::QParameter(QStringLiteral("example" ), float(0.5)); |
| 201 | |
| 202 | m_effect->addParameter(parameter: m_testParam); |
| 203 | |
| 204 | m_filter = new Qt3DRender::QFilterKey(this); |
| 205 | m_filter->setName(QStringLiteral("renderingStyle" )); |
| 206 | m_filter->setValue(QStringLiteral("forward" )); |
| 207 | |
| 208 | m_technique = new Qt3DRender::QTechnique(m_effect); |
| 209 | m_technique->addFilterKey(filterKey: m_filter); |
| 210 | |
| 211 | m_effect->addTechnique(t: m_technique); |
| 212 | |
| 213 | m_program = new Qt3DRender::QShaderProgram(m_effect); |
| 214 | m_program->setVertexShaderCode(vertex_shader); |
| 215 | m_program->setFragmentShaderCode(fragment_shader); |
| 216 | |
| 217 | m_renderPass = new Qt3DRender::QRenderPass(m_effect); |
| 218 | |
| 219 | m_renderPass->setShaderProgram(m_program); |
| 220 | |
| 221 | m_technique->addRenderPass(pass: m_renderPass); |
| 222 | |
| 223 | m_technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::RHI); |
| 224 | } |
| 225 | private: |
| 226 | Qt3DRender::QEffect *m_effect{}; |
| 227 | Qt3DRender::QParameter *m_testParam{}; |
| 228 | Qt3DRender::QFilterKey *m_filter{}; |
| 229 | Qt3DRender::QTechnique *m_technique{}; |
| 230 | Qt3DRender::QShaderProgram *m_program{}; |
| 231 | Qt3DRender::QRenderPass *m_renderPass{}; |
| 232 | }; |
| 233 | |
| 234 | int main(int argc, char* argv[]) |
| 235 | { |
| 236 | qputenv(varName: "QT3D_RENDERER" , value: "rhi" ); |
| 237 | QGuiApplication app(argc, argv); |
| 238 | |
| 239 | auto api = Qt3DRender::API::OpenGL; |
| 240 | if (argc >= 2) { |
| 241 | |
| 242 | #ifdef Q_OS_WIN |
| 243 | if (argv[1] == QByteArrayLiteral("--d3d11" )) api = Qt3DRender::API::DirectX; |
| 244 | #endif |
| 245 | |
| 246 | #if QT_CONFIG(vulkan) |
| 247 | if (argv[1] == QByteArrayLiteral("--vulkan" )) api = Qt3DRender::API::Vulkan; |
| 248 | #endif |
| 249 | |
| 250 | #if defined(Q_OS_MACOS) || defined(Q_OS_IOS) |
| 251 | if (argv[1] == QByteArrayLiteral("--metal" )) api = Qt3DRender::API::Metal; |
| 252 | #endif |
| 253 | } |
| 254 | |
| 255 | Qt3DExtras::Qt3DWindow view{nullptr, api}; |
| 256 | |
| 257 | // Root entity |
| 258 | Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); |
| 259 | |
| 260 | // Camera |
| 261 | Qt3DRender::QCamera *topViewCamera = new Qt3DRender::QCamera(rootEntity); |
| 262 | topViewCamera->setPosition(QVector3D(0, 40, 0)); |
| 263 | topViewCamera->setViewCenter(QVector3D(0, 0, 0)); |
| 264 | topViewCamera->setUpVector(QVector3D(0, 0, 1)); |
| 265 | topViewCamera->lens()->setPerspectiveProjection(fieldOfView: 45.0f, aspect: 16.0f/9.0f, nearPlane: 0.1f, farPlane: 1000.0f); |
| 266 | |
| 267 | Qt3DRender::QCamera *cameraEntity = view.camera(); |
| 268 | cameraEntity->lens()->setPerspectiveProjection(fieldOfView: 45.0f, aspect: 16.0f/9.0f, nearPlane: 0.1f, farPlane: 1000.0f); |
| 269 | cameraEntity->setPosition(QVector3D(0, 0, 40.0f)); |
| 270 | cameraEntity->setUpVector(QVector3D(0, 1, 0)); |
| 271 | cameraEntity->setViewCenter(QVector3D(0, 0, 0)); |
| 272 | |
| 273 | { |
| 274 | // Custom FG |
| 275 | auto *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector(); |
| 276 | surfaceSelector->setSurface(&view); |
| 277 | |
| 278 | // RV 1 |
| 279 | auto *clearBuffer = new Qt3DRender::QClearBuffers(surfaceSelector); |
| 280 | clearBuffer->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer); |
| 281 | clearBuffer->setClearColor(QColor::fromRgbF(r: 0.1, g: 0.5, b: 0.0, a: 1.0)); |
| 282 | auto *noDraw = new Qt3DRender::QNoDraw(clearBuffer); |
| 283 | |
| 284 | // RV 2 |
| 285 | auto *cameraSelector1 = new Qt3DRender::QCameraSelector(surfaceSelector); |
| 286 | cameraSelector1->setCamera(view.camera()); |
| 287 | auto *viewport1 = new Qt3DRender::QViewport(cameraSelector1); |
| 288 | viewport1->setNormalizedRect(QRectF(0.0f, 0.0f, 0.5f, 0.5f)); |
| 289 | |
| 290 | // RV3 |
| 291 | auto *cameraSelector2 = new Qt3DRender::QCameraSelector(surfaceSelector); |
| 292 | cameraSelector2->setCamera(topViewCamera); |
| 293 | auto *viewport2 = new Qt3DRender::QViewport(cameraSelector2); |
| 294 | viewport2->setNormalizedRect(QRectF(0.5f, 0.5f, 0.5f, 0.5f)); |
| 295 | |
| 296 | view.setActiveFrameGraph(surfaceSelector); |
| 297 | } |
| 298 | |
| 299 | QTimer *cameraAnimationTimer = new QTimer(&view); |
| 300 | QObject::connect(sender: cameraAnimationTimer, signal: &QTimer::timeout, |
| 301 | slot: [cameraEntity] { |
| 302 | static int angle = 0; |
| 303 | const float radius = 40.0f; |
| 304 | const float anglef = qDegreesToRadians(degrees: float(angle)); |
| 305 | cameraEntity->setPosition(QVector3D(qSin(v: anglef), 0.0f, qCos(v: anglef)) * radius); |
| 306 | angle += 1; |
| 307 | }); |
| 308 | cameraAnimationTimer->start(msec: 16); |
| 309 | |
| 310 | // For camera controls |
| 311 | Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(rootEntity); |
| 312 | camController->setCamera(cameraEntity); |
| 313 | |
| 314 | // Material |
| 315 | Qt3DRender::QMaterial *material = new Material(rootEntity); |
| 316 | Qt3DRender::QParameter *parameter = new Qt3DRender::QParameter(QStringLiteral("colorFactor" ), QColor(Qt::white)); |
| 317 | material->addParameter(parameter); |
| 318 | |
| 319 | Qt3DRender::QTextureLoader *textureLoader = new Qt3DRender::QTextureLoader{}; |
| 320 | textureLoader->setSource(QUrl{QStringLiteral("qrc:///qtlogo.png" )}); |
| 321 | Qt3DRender::QParameter *texture = new Qt3DRender::QParameter(QStringLiteral("myTexture" ), textureLoader); |
| 322 | material->addParameter(parameter: texture); |
| 323 | |
| 324 | QTimer *parameterAnimationTimer = new QTimer(&view); |
| 325 | QObject::connect(sender: parameterAnimationTimer, signal: &QTimer::timeout, |
| 326 | slot: [parameter] { |
| 327 | static int angle = 0; |
| 328 | const float anglef = qDegreesToRadians(degrees: float(angle)); |
| 329 | parameter->setValue(QColor::fromRgbF(r: fabs(x: qCos(v: anglef)), g: fabs(x: qSin(v: anglef)), b: 1.0f)); |
| 330 | angle += 10; |
| 331 | }); |
| 332 | parameterAnimationTimer->start(msec: 16); |
| 333 | |
| 334 | // Torus |
| 335 | Qt3DCore::QEntity *customMeshEntity = new Qt3DCore::QEntity(rootEntity); |
| 336 | |
| 337 | // Transform |
| 338 | Qt3DCore::QTransform *transform = new Qt3DCore::QTransform; |
| 339 | transform->setScale(8.0f); |
| 340 | |
| 341 | // Custom Mesh (TetraHedron) |
| 342 | Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer; |
| 343 | Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer); |
| 344 | |
| 345 | Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry); |
| 346 | Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(customGeometry); |
| 347 | |
| 348 | // 5 vertices of 3 vertices + 3 colors |
| 349 | QByteArray vertexBufferData; |
| 350 | vertexBufferData.resize(size: 5 * (3 + 3) * sizeof(float)); |
| 351 | |
| 352 | // Vertices |
| 353 | QVector3D v0(-1.0f, 0.0f, -1.0f); |
| 354 | QVector3D v1(1.0f, 0.0f, -1.0f); |
| 355 | QVector3D v2(-1.0f, 0.0f, 1.0f); |
| 356 | QVector3D v3(1.0f, 0.0f, 1.0f); |
| 357 | QVector3D v4(0.0f, 2.0f, 0.0f); |
| 358 | |
| 359 | QVector3D red(1.0f, 0.0f, 0.0f); |
| 360 | QVector3D green(0.0f, 1.0f, 0.0f); |
| 361 | QVector3D blue(0.0f, 0.0f, 1.0f); |
| 362 | QVector3D white(1.0f, 1.0f, 1.0f); |
| 363 | QVector3D grey(0.5f, 0.5f, 0.5f); |
| 364 | |
| 365 | const QVector<QVector3D> vertices = QVector<QVector3D>() |
| 366 | << v0 << red |
| 367 | << v1 << green |
| 368 | << v2 << blue |
| 369 | << v3 << grey |
| 370 | << v4 << white; |
| 371 | |
| 372 | memcpy(dest: vertexBufferData.data(), src: vertices.constData(), n: vertices.size() * sizeof(QVector3D)); |
| 373 | vertexDataBuffer->setData(vertexBufferData); |
| 374 | |
| 375 | QByteArray indexBufferData; |
| 376 | // 6 triangle faces |
| 377 | indexBufferData.resize(size: 6 * 3 * sizeof(ushort)); |
| 378 | ushort *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data()); |
| 379 | |
| 380 | rawIndexArray[0] = 0; |
| 381 | rawIndexArray[1] = 1; |
| 382 | rawIndexArray[2] = 2; |
| 383 | |
| 384 | rawIndexArray[3] = 2; |
| 385 | rawIndexArray[4] = 1; |
| 386 | rawIndexArray[5] = 3; |
| 387 | |
| 388 | rawIndexArray[6] = 2; |
| 389 | rawIndexArray[7] = 3; |
| 390 | rawIndexArray[8] = 4; |
| 391 | |
| 392 | rawIndexArray[9] = 3; |
| 393 | rawIndexArray[10] = 1; |
| 394 | rawIndexArray[11] = 4; |
| 395 | |
| 396 | rawIndexArray[12] = 1; |
| 397 | rawIndexArray[13] = 0; |
| 398 | rawIndexArray[14] = 4; |
| 399 | |
| 400 | rawIndexArray[15] = 0; |
| 401 | rawIndexArray[16] = 2; |
| 402 | rawIndexArray[17] = 4; |
| 403 | |
| 404 | indexDataBuffer->setData(indexBufferData); |
| 405 | |
| 406 | // Attributes |
| 407 | Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute(); |
| 408 | positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); |
| 409 | positionAttribute->setBuffer(vertexDataBuffer); |
| 410 | positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); |
| 411 | positionAttribute->setVertexSize(3); |
| 412 | positionAttribute->setByteOffset(0); |
| 413 | positionAttribute->setByteStride(6 * sizeof(float)); |
| 414 | positionAttribute->setCount(5); |
| 415 | positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); |
| 416 | |
| 417 | Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute(); |
| 418 | colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); |
| 419 | colorAttribute->setBuffer(vertexDataBuffer); |
| 420 | colorAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float); |
| 421 | colorAttribute->setVertexSize(3); |
| 422 | colorAttribute->setByteOffset(3 * sizeof(float)); |
| 423 | colorAttribute->setByteStride(6 * sizeof(float)); |
| 424 | colorAttribute->setCount(5); |
| 425 | colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName()); |
| 426 | |
| 427 | Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute(); |
| 428 | indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); |
| 429 | indexAttribute->setBuffer(indexDataBuffer); |
| 430 | indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort); |
| 431 | indexAttribute->setVertexSize(1); |
| 432 | indexAttribute->setByteOffset(0); |
| 433 | indexAttribute->setByteStride(0); |
| 434 | indexAttribute->setCount(18); |
| 435 | |
| 436 | customGeometry->addAttribute(attribute: positionAttribute); |
| 437 | customGeometry->addAttribute(attribute: colorAttribute); |
| 438 | customGeometry->addAttribute(attribute: indexAttribute); |
| 439 | |
| 440 | customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); |
| 441 | customMeshRenderer->setGeometry(customGeometry); |
| 442 | |
| 443 | customMeshEntity->addComponent(comp: customMeshRenderer); |
| 444 | customMeshEntity->addComponent(comp: transform); |
| 445 | customMeshEntity->addComponent(comp: material); |
| 446 | |
| 447 | view.setRootEntity(rootEntity); |
| 448 | view.show(); |
| 449 | |
| 450 | return app.exec(); |
| 451 | } |
| 452 | |