1/****************************************************************************
2**
3** Copyright (C) 2017 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#ifndef QT3DRENDER_RENDER_BUFFERVISITOR_P_H
41#define QT3DRENDER_RENDER_BUFFERVISITOR_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists for the convenience
48// of other Qt classes. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <Qt3DCore/qnodeid.h>
55#include <Qt3DRender/QAttribute>
56#include <Qt3DRender/private/trianglesvisitor_p.h>
57#include <Qt3DRender/private/attribute_p.h>
58#include <Qt3DRender/private/buffer_p.h>
59#include <Qt3DRender/private/bufferutils_p.h>
60#include <Qt3DRender/private/geometryrenderer_p.h>
61#include <Qt3DRender/private/geometry_p.h>
62#include <Qt3DRender/private/managers_p.h>
63#include <Qt3DRender/private/nodemanagers_p.h>
64
65QT_BEGIN_NAMESPACE
66
67namespace Qt3DCore {
68class QEntity;
69}
70
71namespace Qt3DRender {
72namespace Render {
73
74
75template <typename ValueType, QAttribute::VertexBaseType VertexBaseType, uint dataSize>
76class Q_AUTOTEST_EXPORT BufferVisitor
77{
78public:
79 explicit BufferVisitor(NodeManagers *manager)
80 : m_manager(manager)
81 {
82 }
83 virtual ~BufferVisitor() { }
84
85 virtual void visit(uint ndx, ValueType x) {
86 Q_UNUSED(ndx); Q_UNUSED(x);
87 }
88 virtual void visit(uint ndx, ValueType x, ValueType y) {
89 Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y);
90 }
91 virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z) {
92 Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z);
93 }
94 virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z, ValueType w) {
95 Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z); Q_UNUSED(w);
96 }
97
98 template<typename VertexBufferType, typename IndexBufferType>
99 void traverseCoordinateIndexed(VertexBufferType *vertexBuffer,
100 IndexBufferType *indexBuffer,
101 int vertexByteStride,
102 int drawVertexCount,
103 bool primitiveRestartEnabled,
104 int primitiveRestartIndex)
105 {
106 switch (dataSize) {
107 case 1: traverseCoordinates1Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
108 primitiveRestartEnabled, primitiveRestartIndex);
109 break;
110 case 2: traverseCoordinates2Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
111 primitiveRestartEnabled, primitiveRestartIndex);
112 break;
113 case 3: traverseCoordinates3Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
114 primitiveRestartEnabled, primitiveRestartIndex);
115 break;
116 case 4: traverseCoordinates4Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
117 primitiveRestartEnabled, primitiveRestartIndex);
118 break;
119 default: Q_UNREACHABLE();
120 }
121 }
122
123 bool apply(Qt3DRender::Render::Attribute *attribute,
124 Qt3DRender::Render::Attribute *indexAttribute,
125 int drawVertexCount,
126 bool primitiveRestartEnabled,
127 int primitiveRestartIndex)
128 {
129 if (attribute->vertexBaseType() != VertexBaseType)
130 return false;
131 if (attribute->vertexSize() < dataSize)
132 return false;
133
134 auto data = m_manager->lookupResource<Buffer, BufferManager>(id: attribute->bufferId())->data();
135 auto vertexBuffer = BufferTypeInfo::castToType<VertexBaseType>(data, attribute->byteOffset());
136
137 if (indexAttribute) {
138 auto indexData = m_manager->lookupResource<Buffer, BufferManager>(id: indexAttribute->bufferId())->data();
139 switch (indexAttribute->vertexBaseType()) {
140 case QAttribute::UnsignedShort: {
141 auto indexBuffer = BufferTypeInfo::castToType<QAttribute::UnsignedShort>(u: indexData, byteOffset: indexAttribute->byteOffset());
142 traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount,
143 primitiveRestartEnabled, primitiveRestartIndex);
144 break;
145 }
146 case QAttribute::UnsignedInt: {
147 auto indexBuffer = BufferTypeInfo::castToType<QAttribute::UnsignedInt>(u: indexData, byteOffset: indexAttribute->byteOffset());
148 traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount,
149 primitiveRestartEnabled, primitiveRestartIndex);
150 break;
151 }
152 case QAttribute::UnsignedByte: {
153 auto indexBuffer = BufferTypeInfo::castToType<QAttribute::UnsignedByte>(u: indexData, byteOffset: indexAttribute->byteOffset());
154 traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount,
155 primitiveRestartEnabled, primitiveRestartIndex);
156 break;
157 }
158 default: Q_UNREACHABLE();
159 }
160 } else {
161 switch (dataSize) {
162 case 1: traverseCoordinates1(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
163 case 2: traverseCoordinates2(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
164 case 3: traverseCoordinates3(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
165 case 4: traverseCoordinates4(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
166 default: Q_UNREACHABLE();
167 }
168 }
169
170 return true;
171 }
172
173protected:
174
175 template <typename Coordinate>
176 void traverseCoordinates1(Coordinate *coordinates,
177 const uint byteStride,
178 const uint count)
179 {
180 const uint stride = byteStride / sizeof(Coordinate);
181 for (uint ndx = 0; ndx < count; ++ndx) {
182 visit(ndx, coordinates[0]);
183 coordinates += stride;
184 }
185 }
186
187 template <typename Coordinate, typename IndexElem>
188 void traverseCoordinates1Indexed(Coordinate *coordinates,
189 const uint byteStride,
190 IndexElem *indices,
191 const uint count,
192 bool primitiveRestartEnabled,
193 int primitiveRestartIndex)
194 {
195 const uint stride = byteStride / sizeof(Coordinate);
196 for (uint i = 0; i < count; ++i) {
197 if (!primitiveRestartEnabled || (int) indices[i] != primitiveRestartIndex) {
198 const uint n = stride * indices[i];
199 visit(i, coordinates[n]);
200 }
201 }
202 }
203
204 template <typename Coordinate>
205 void traverseCoordinates2(Coordinate *coordinates,
206 const uint byteStride,
207 const uint count)
208 {
209 const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2;
210 for (uint ndx = 0; ndx < count; ++ndx) {
211 visit(ndx, coordinates[0], coordinates[1]);
212 coordinates += stride;
213 }
214 }
215
216
217 template <typename Coordinate, typename IndexElem>
218 void traverseCoordinates2Indexed(Coordinate *coordinates,
219 const uint byteStride,
220 IndexElem *indices,
221 const uint count,
222 bool primitiveRestartEnabled,
223 int primitiveRestartIndex)
224 {
225 const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2;
226 for (uint i = 0; i < count; ++i) {
227 if (!primitiveRestartEnabled || (int) indices[i] != primitiveRestartIndex) {
228 const uint n = stride * indices[i];
229 visit(i, coordinates[n], coordinates[n + 1]);
230 }
231 }
232 }
233
234 template <typename Coordinate>
235 void traverseCoordinates3(Coordinate *coordinates,
236 const uint byteStride,
237 const uint count)
238 {
239 const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3;
240 for (uint ndx = 0; ndx < count; ++ndx) {
241 visit(ndx, coordinates[0], coordinates[1], coordinates[2]);
242 coordinates += stride;
243 }
244 }
245
246 template <typename Coordinate, typename IndexElem>
247 void traverseCoordinates3Indexed(Coordinate *coordinates,
248 const uint byteStride,
249 IndexElem *indices,
250 const uint count,
251 bool primitiveRestartEnabled,
252 int primitiveRestartIndex)
253 {
254 const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3;
255 for (uint i = 0; i < count; ++i) {
256 if (!primitiveRestartEnabled || (int) indices[i] != primitiveRestartIndex) {
257 const uint n = stride * indices[i];
258 visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2]);
259 }
260 }
261 }
262
263 template <typename Coordinate>
264 void traverseCoordinates4(Coordinate *coordinates,
265 const uint byteStride,
266 const uint count)
267 {
268 const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4;
269 for (uint ndx = 0; ndx < count; ++ndx) {
270 visit(ndx, coordinates[0], coordinates[1], coordinates[2], coordinates[3]);
271 coordinates += stride;
272 }
273 }
274
275 template <typename Coordinate, typename IndexElem>
276 void traverseCoordinates4Indexed(Coordinate *coordinates,
277 const uint byteStride,
278 IndexElem *indices,
279 const uint count,
280 bool primitiveRestartEnabled,
281 int primitiveRestartIndex)
282 {
283 const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4;
284 for (uint i = 0; i < count; ++i) {
285 if (!primitiveRestartEnabled || (int) indices[i] != primitiveRestartIndex) {
286 const uint n = stride * indices[i];
287 visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2], coordinates[n + 3]);
288 }
289 }
290 }
291
292 NodeManagers *m_manager;
293};
294
295typedef BufferVisitor<float, QAttribute::Float, 3> Buffer3fVisitor;
296
297} // namespace Render
298
299} // namespace Qt3DRender
300
301QT_END_NAMESPACE
302
303
304#endif // QT3DRENDER_RENDER_BUFFERVISITOR_P_H
305

source code of qt3d/src/render/backend/buffervisitor_p.h