1/****************************************************************************
2**
3** Copyright (C) 2016 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
75namespace {
76
77struct IndirectElementDrawBuffer{ // Element Indirect
78 uint count;
79 uint instancesCount;
80 uint firstIndex;
81 uint baseVertex;
82 uint baseInstance;
83};
84
85struct IndirectArrayDrawBuffer{ // Array Indirect
86 uint count;
87 uint instancesCount;
88 uint first;
89 uint baseInstance;
90};
91
92} // anonymous
93
94int main(int argc, char* argv[])
95{
96 QGuiApplication app(argc, argv);
97 Qt3DExtras::Qt3DWindow view;
98 view.defaultFrameGraph()->setClearColor(QColor::fromRgbF(r: 0.0, g: 0.5, b: 1.0, a: 1.0));
99
100 // Root entity
101 Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
102
103 // Camera
104 Qt3DRender::QCamera *cameraEntity = view.camera();
105
106 cameraEntity->lens()->setPerspectiveProjection(fieldOfView: 45.0f, aspect: 16.0f/9.0f, nearPlane: 0.1f, farPlane: 1000.0f);
107 cameraEntity->setPosition(QVector3D(0, 0, 40.0f));
108 cameraEntity->setUpVector(QVector3D(0, 1, 0));
109 cameraEntity->setViewCenter(QVector3D(0, 0, 0));
110
111 // For camera controls
112 Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
113 camController->setCamera(cameraEntity);
114
115 // Material
116 Qt3DRender::QMaterial *material = new Qt3DExtras::QPerVertexColorMaterial(rootEntity);
117
118 // vec3 for position
119 // vec3 for colors
120 // vec3 for normals
121
122 /* 2
123 /|\
124 / | \
125 / /3\ \
126 0/___\ 1
127 */
128 // Vertices
129 QVector3D v0(-1.0f, 0.0f, -1.0f);
130 QVector3D v1(1.0f, 0.0f, -1.0f);
131 QVector3D v2(0.0f, 1.0f, 0.0f);
132 QVector3D v3(0.0f, 0.0f, 1.0f);
133
134 // Faces Normals
135 QVector3D n023 = QVector3D::normal(v1: v0, v2, v3);
136 QVector3D n012 = QVector3D::normal(v1: v0, v2: v1, v3: v2);
137 QVector3D n310 = QVector3D::normal(v1: v3, v2: v1, v3: v0);
138 QVector3D n132 = QVector3D::normal(v1, v2: v3, v3: v2);
139
140 // Vector Normals
141 QVector3D n0 = QVector3D(n023 + n012 + n310).normalized();
142 QVector3D n1 = QVector3D(n132 + n012 + n310).normalized();
143 QVector3D n2 = QVector3D(n132 + n012 + n023).normalized();
144 QVector3D n3 = QVector3D(n132 + n310 + n023).normalized();
145
146 // Colors
147 QVector3D red(1.0f, 0.0f, 0.0f);
148 QVector3D green(0.0f, 1.0f, 0.0f);
149 QVector3D blue(0.0f, 0.0f, 1.0f);
150 QVector3D white(1.0f, 1.0f, 1.0f);
151
152 const QVector<QVector3D> vertices = QVector<QVector3D>()
153 << v0 << n0 << red
154 << v1 << n1 << blue
155 << v2 << n2 << green
156 << v3 << n3 << white;
157
158 // DrawElementIndirect
159 {
160 Qt3DCore::QEntity *customDrawElementIndirectEntity = new Qt3DCore::QEntity(rootEntity);
161
162 // Transform
163 Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
164 transform->setScale(8.0f);
165 transform->setTranslation(QVector3D(-10.0f, 0.0, 0.0f));
166
167 // Custom Mesh (TetraHedron)
168 Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
169 Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
170
171 Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
172 Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
173 Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(customGeometry);
174
175 // 4 distinct vertices
176 QByteArray vertexBufferData;
177 vertexBufferData.resize(size: 4 * (3 + 3 + 3) * sizeof(float));
178
179 float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
180 int idx = 0;
181
182 for (const QVector3D &v : vertices) {
183 rawVertexArray[idx++] = v.x();
184 rawVertexArray[idx++] = v.y();
185 rawVertexArray[idx++] = v.z();
186 }
187
188 // Indices (12)
189 QByteArray indexBufferData;
190 indexBufferData.resize(size: 4 * 3 * sizeof(ushort));
191 ushort *rawIndexArray = reinterpret_cast<ushort *>(indexBufferData.data());
192
193 // Front
194 rawIndexArray[0] = 0;
195 rawIndexArray[1] = 1;
196 rawIndexArray[2] = 2;
197 // Bottom
198 rawIndexArray[3] = 3;
199 rawIndexArray[4] = 1;
200 rawIndexArray[5] = 0;
201 // Left
202 rawIndexArray[6] = 0;
203 rawIndexArray[7] = 2;
204 rawIndexArray[8] = 3;
205 // Right
206 rawIndexArray[9] = 1;
207 rawIndexArray[10] = 3;
208 rawIndexArray[11] = 2;
209
210
211 QByteArray indirectBufferData;
212 indirectBufferData.resize(size: sizeof(IndirectElementDrawBuffer));
213 IndirectElementDrawBuffer *indirectStruct = reinterpret_cast<IndirectElementDrawBuffer *>(indirectBufferData.data());
214 indirectStruct->count = 12U;
215 indirectStruct->firstIndex = 0U;
216 indirectStruct->baseInstance = 0U;
217 indirectStruct->baseVertex = 0U;
218 indirectStruct->instancesCount = 1U;
219
220 vertexDataBuffer->setData(vertexBufferData);
221 indexDataBuffer->setData(indexBufferData);
222 indirectDrawDataBuffer->setData(indirectBufferData);
223
224 // Attributes
225 Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
226 positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
227 positionAttribute->setBuffer(vertexDataBuffer);
228 positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
229 positionAttribute->setVertexSize(3);
230 positionAttribute->setByteOffset(0);
231 positionAttribute->setByteStride(9 * sizeof(float));
232 positionAttribute->setCount(4);
233 positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
234
235 Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute();
236 normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
237 normalAttribute->setBuffer(vertexDataBuffer);
238 normalAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
239 normalAttribute->setVertexSize(3);
240 normalAttribute->setByteOffset(3 * sizeof(float));
241 normalAttribute->setByteStride(9 * sizeof(float));
242 normalAttribute->setCount(4);
243 normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName());
244
245 Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute();
246 colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
247 colorAttribute->setBuffer(vertexDataBuffer);
248 colorAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
249 colorAttribute->setVertexSize(3);
250 colorAttribute->setByteOffset(6 * sizeof(float));
251 colorAttribute->setByteStride(9 * sizeof(float));
252 colorAttribute->setCount(4);
253 colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName());
254
255 Qt3DRender::QAttribute *indexAttribute = new Qt3DRender::QAttribute();
256 indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute);
257 indexAttribute->setBuffer(indexDataBuffer);
258 indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedShort);
259 indexAttribute->setVertexSize(1);
260 indexAttribute->setByteOffset(0);
261 indexAttribute->setByteStride(0);
262 indexAttribute->setCount(12);
263
264 Qt3DRender::QAttribute *indirectAttribute = new Qt3DRender::QAttribute();
265 indirectAttribute->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
266 indirectAttribute->setBuffer(indirectDrawDataBuffer);
267 indirectAttribute->setByteOffset(0);
268 indirectAttribute->setByteStride(0);
269 indirectAttribute->setCount(1);
270
271 customGeometry->addAttribute(attribute: positionAttribute);
272 customGeometry->addAttribute(attribute: normalAttribute);
273 customGeometry->addAttribute(attribute: colorAttribute);
274 customGeometry->addAttribute(attribute: indexAttribute);
275 customGeometry->addAttribute(attribute: indirectAttribute);
276
277 customMeshRenderer->setInstanceCount(1);
278 customMeshRenderer->setIndexOffset(0);
279 customMeshRenderer->setFirstInstance(0);
280 customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
281 customMeshRenderer->setGeometry(customGeometry);
282 // 4 faces of 3 points
283 customMeshRenderer->setVertexCount(12);
284
285 customDrawElementIndirectEntity->addComponent(comp: customMeshRenderer);
286 customDrawElementIndirectEntity->addComponent(comp: transform);
287 customDrawElementIndirectEntity->addComponent(comp: material);
288 }
289
290 // DrawArrayIndirect
291 {
292 Qt3DCore::QEntity *customDrawArrayIndirectEntity = new Qt3DCore::QEntity(rootEntity);
293
294 // Transform
295 Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
296 transform->setScale(8.0f);
297 transform->setTranslation(QVector3D(10.0f, 0.0, 0.0f));
298
299 // Custom Mesh (TetraHedron)
300 Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
301 Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
302
303 Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(customGeometry);
304 Qt3DRender::QBuffer *indirectDrawDataBuffer = new Qt3DRender::QBuffer(customGeometry);
305
306
307 QVector<QVector3D> orderedPositionVertices;
308 // 12 vertices with position, normal, color
309 orderedPositionVertices.reserve(asize: 12 * (1 + 1 + 1));
310
311 orderedPositionVertices << v0 << n0 << red;
312 orderedPositionVertices << v1 << n1 << red;
313 orderedPositionVertices << v2 << n2 << red;
314
315 orderedPositionVertices << v3 << n3 << green;
316 orderedPositionVertices << v1 << n1 << green;
317 orderedPositionVertices << v0 << n0 << green;
318
319 orderedPositionVertices << v0 << n0 << blue;
320 orderedPositionVertices << v2 << n2 << blue;
321 orderedPositionVertices << v3 << n3 << blue;
322
323 orderedPositionVertices << v1 << n1 << white;
324 orderedPositionVertices << v3 << n3 << white;
325 orderedPositionVertices << v2 << n2 << white;
326
327 QByteArray vertexBufferData;
328 vertexBufferData.resize(size: orderedPositionVertices.size() * sizeof(QVector3D));
329 memcpy(dest: vertexBufferData.data(), src: orderedPositionVertices.data(), n: orderedPositionVertices.size() * sizeof(QVector3D));
330
331 QByteArray indirectBufferData;
332 indirectBufferData.resize(size: sizeof(IndirectArrayDrawBuffer));
333 IndirectArrayDrawBuffer *indirectStruct = reinterpret_cast<IndirectArrayDrawBuffer *>(indirectBufferData.data());
334 indirectStruct->count = 12U;
335 indirectStruct->baseInstance = 0U;
336 indirectStruct->instancesCount = 1U;
337 indirectStruct->first = 0U;
338
339 vertexDataBuffer->setData(vertexBufferData);
340 indirectDrawDataBuffer->setData(indirectBufferData);
341
342 // Attributes
343 Qt3DRender::QAttribute *positionAttribute = new Qt3DRender::QAttribute();
344 positionAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
345 positionAttribute->setBuffer(vertexDataBuffer);
346 positionAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
347 positionAttribute->setVertexSize(3);
348 positionAttribute->setByteOffset(0);
349 positionAttribute->setByteStride(9 * sizeof(float));
350 positionAttribute->setCount(12);
351 positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName());
352
353 Qt3DRender::QAttribute *normalAttribute = new Qt3DRender::QAttribute();
354 normalAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
355 normalAttribute->setBuffer(vertexDataBuffer);
356 normalAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
357 normalAttribute->setVertexSize(3);
358 normalAttribute->setByteOffset(3 * sizeof(float));
359 normalAttribute->setByteStride(9 * sizeof(float));
360 normalAttribute->setCount(12);
361 normalAttribute->setName(Qt3DRender::QAttribute::defaultNormalAttributeName());
362
363 Qt3DRender::QAttribute *colorAttribute = new Qt3DRender::QAttribute();
364 colorAttribute->setAttributeType(Qt3DRender::QAttribute::VertexAttribute);
365 colorAttribute->setBuffer(vertexDataBuffer);
366 colorAttribute->setVertexBaseType(Qt3DRender::QAttribute::Float);
367 colorAttribute->setVertexSize(3);
368 colorAttribute->setByteOffset(6 * sizeof(float));
369 colorAttribute->setByteStride(9 * sizeof(float));
370 colorAttribute->setCount(12);
371 colorAttribute->setName(Qt3DRender::QAttribute::defaultColorAttributeName());
372
373 Qt3DRender::QAttribute *indirectAttribute = new Qt3DRender::QAttribute();
374 indirectAttribute->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute);
375 indirectAttribute->setBuffer(indirectDrawDataBuffer);
376 indirectAttribute->setByteOffset(0);
377 indirectAttribute->setByteStride(0);
378 indirectAttribute->setCount(1);
379
380 customGeometry->addAttribute(attribute: positionAttribute);
381 customGeometry->addAttribute(attribute: normalAttribute);
382 customGeometry->addAttribute(attribute: colorAttribute);
383 customGeometry->addAttribute(attribute: indirectAttribute);
384
385 customMeshRenderer->setInstanceCount(1);
386 customMeshRenderer->setIndexOffset(0);
387 customMeshRenderer->setFirstInstance(0);
388 customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
389 customMeshRenderer->setGeometry(customGeometry);
390 // 4 faces of 3 points
391 customMeshRenderer->setVertexCount(12);
392
393 customDrawArrayIndirectEntity->addComponent(comp: customMeshRenderer);
394 customDrawArrayIndirectEntity->addComponent(comp: transform);
395 customDrawArrayIndirectEntity->addComponent(comp: material);
396 }
397
398 view.setRootEntity(rootEntity);
399 view.show();
400
401 return app.exec();
402}
403

source code of qt3d/tests/manual/custom-mesh-cpp-indirect/main.cpp