1 | // Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QT3DCORE_BUFFERVISITOR_P_H |
5 | #define QT3DCORE_BUFFERVISITOR_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists for the convenience |
12 | // of other Qt classes. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <Qt3DCore/qnodeid.h> |
19 | #include <Qt3DCore/qattribute.h> |
20 | #include <Qt3DCore/qbuffer.h> |
21 | #include <Qt3DCore/private/bufferutils_p.h> |
22 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | namespace Qt3DCore { |
26 | class QEntity; |
27 | |
28 | template <typename ValueType, Qt3DCore::QAttribute::VertexBaseType VertexBaseType, uint dataSize> |
29 | class Q_AUTOTEST_EXPORT BufferVisitor |
30 | { |
31 | public: |
32 | explicit BufferVisitor() = default; |
33 | virtual ~BufferVisitor() = default; |
34 | |
35 | virtual void visit(uint ndx, ValueType x) { |
36 | Q_UNUSED(ndx); Q_UNUSED(x); |
37 | } |
38 | virtual void visit(uint ndx, ValueType x, ValueType y) { |
39 | Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); |
40 | } |
41 | virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z) { |
42 | Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z); |
43 | } |
44 | virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z, ValueType w) { |
45 | Q_UNUSED(ndx); Q_UNUSED(x); Q_UNUSED(y); Q_UNUSED(z); Q_UNUSED(w); |
46 | } |
47 | |
48 | bool apply(QAttribute *attribute, |
49 | QAttribute *indexAttribute, |
50 | int drawVertexCount, |
51 | bool primitiveRestartEnabled, |
52 | int primitiveRestartIndex) |
53 | { |
54 | if (attribute->vertexBaseType() != VertexBaseType) |
55 | return false; |
56 | if (attribute->vertexSize() < dataSize) |
57 | return false; |
58 | |
59 | auto data = attribute->buffer()->data(); |
60 | auto vertexBuffer = BufferTypeInfo::castToType<VertexBaseType>(data, attribute->byteOffset()); |
61 | |
62 | if (indexAttribute) { |
63 | auto indexData = indexAttribute->buffer()->data(); |
64 | switch (indexAttribute->vertexBaseType()) { |
65 | case Qt3DCore::QAttribute::UnsignedShort: { |
66 | auto indexBuffer = BufferTypeInfo::castToType<Qt3DCore::QAttribute::UnsignedShort>(u: indexData, byteOffset: indexAttribute->byteOffset()); |
67 | traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount, |
68 | primitiveRestartEnabled, primitiveRestartIndex); |
69 | break; |
70 | } |
71 | case Qt3DCore::QAttribute::UnsignedInt: { |
72 | auto indexBuffer = BufferTypeInfo::castToType<Qt3DCore::QAttribute::UnsignedInt>(u: indexData, byteOffset: indexAttribute->byteOffset()); |
73 | traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount, |
74 | primitiveRestartEnabled, primitiveRestartIndex); |
75 | break; |
76 | } |
77 | case Qt3DCore::QAttribute::UnsignedByte: { |
78 | auto indexBuffer = BufferTypeInfo::castToType<Qt3DCore::QAttribute::UnsignedByte>(u: indexData, byteOffset: indexAttribute->byteOffset()); |
79 | traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount, |
80 | primitiveRestartEnabled, primitiveRestartIndex); |
81 | break; |
82 | } |
83 | default: Q_UNREACHABLE(); |
84 | } |
85 | } else { |
86 | switch (dataSize) { |
87 | case 1: traverseCoordinates1(vertexBuffer, attribute->byteStride(), drawVertexCount); break; |
88 | case 2: traverseCoordinates2(vertexBuffer, attribute->byteStride(), drawVertexCount); break; |
89 | case 3: traverseCoordinates3(vertexBuffer, attribute->byteStride(), drawVertexCount); break; |
90 | case 4: traverseCoordinates4(vertexBuffer, attribute->byteStride(), drawVertexCount); break; |
91 | default: Q_UNREACHABLE(); |
92 | } |
93 | } |
94 | |
95 | return true; |
96 | } |
97 | |
98 | protected: |
99 | template<typename VertexBufferType, typename IndexBufferType> |
100 | void traverseCoordinateIndexed(VertexBufferType *vertexBuffer, |
101 | IndexBufferType *indexBuffer, |
102 | int vertexByteStride, |
103 | int drawVertexCount, |
104 | bool primitiveRestartEnabled, |
105 | int primitiveRestartIndex) |
106 | { |
107 | switch (dataSize) { |
108 | case 1: traverseCoordinates1Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount, |
109 | primitiveRestartEnabled, primitiveRestartIndex); |
110 | break; |
111 | case 2: traverseCoordinates2Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount, |
112 | primitiveRestartEnabled, primitiveRestartIndex); |
113 | break; |
114 | case 3: traverseCoordinates3Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount, |
115 | primitiveRestartEnabled, primitiveRestartIndex); |
116 | break; |
117 | case 4: traverseCoordinates4Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount, |
118 | primitiveRestartEnabled, primitiveRestartIndex); |
119 | break; |
120 | default: Q_UNREACHABLE(); |
121 | } |
122 | } |
123 | |
124 | template <typename Coordinate> |
125 | void traverseCoordinates1(Coordinate *coordinates, |
126 | const uint byteStride, |
127 | const uint count) |
128 | { |
129 | const uint stride = byteStride / sizeof(Coordinate); |
130 | for (uint ndx = 0; ndx < count; ++ndx) { |
131 | visit(ndx, coordinates[0]); |
132 | coordinates += stride; |
133 | } |
134 | } |
135 | |
136 | template <typename Coordinate, typename IndexElem> |
137 | void traverseCoordinates1Indexed(Coordinate *coordinates, |
138 | const uint byteStride, |
139 | IndexElem *indices, |
140 | const uint count, |
141 | bool primitiveRestartEnabled, |
142 | int primitiveRestartIndex) |
143 | { |
144 | const uint stride = byteStride / sizeof(Coordinate); |
145 | if (primitiveRestartEnabled) { |
146 | for (uint i = 0; i < count; ++i) { |
147 | if (static_cast<int>(indices[i]) != primitiveRestartIndex) { |
148 | const uint n = stride * indices[i]; |
149 | visit(i, coordinates[n]); |
150 | } |
151 | } |
152 | } else { |
153 | for (uint i = 0; i < count; ++i) { |
154 | const uint n = stride * indices[i]; |
155 | visit(i, coordinates[n]); |
156 | } |
157 | } |
158 | } |
159 | |
160 | template <typename Coordinate> |
161 | void traverseCoordinates2(Coordinate *coordinates, |
162 | const uint byteStride, |
163 | const uint count) |
164 | { |
165 | const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2; |
166 | for (uint ndx = 0; ndx < count; ++ndx) { |
167 | visit(ndx, coordinates[0], coordinates[1]); |
168 | coordinates += stride; |
169 | } |
170 | } |
171 | |
172 | template <typename Coordinate, typename IndexElem> |
173 | void traverseCoordinates2Indexed(Coordinate *coordinates, |
174 | const uint byteStride, |
175 | IndexElem *indices, |
176 | const uint count, |
177 | bool primitiveRestartEnabled, |
178 | int primitiveRestartIndex) |
179 | { |
180 | const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2; |
181 | if (primitiveRestartEnabled) { |
182 | for (uint i = 0; i < count; ++i) { |
183 | if (static_cast<int>(indices[i]) != primitiveRestartIndex) { |
184 | const uint n = stride * indices[i]; |
185 | visit(i, coordinates[n], coordinates[n + 1]); |
186 | } |
187 | } |
188 | } else { |
189 | for (uint i = 0; i < count; ++i) { |
190 | const uint n = stride * indices[i]; |
191 | visit(i, coordinates[n], coordinates[n + 1]); |
192 | } |
193 | } |
194 | } |
195 | |
196 | template <typename Coordinate> |
197 | void traverseCoordinates3(Coordinate *coordinates, |
198 | const uint byteStride, |
199 | const uint count) |
200 | { |
201 | const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3; |
202 | for (uint ndx = 0; ndx < count; ++ndx) { |
203 | visit(ndx, coordinates[0], coordinates[1], coordinates[2]); |
204 | coordinates += stride; |
205 | } |
206 | } |
207 | |
208 | template <typename Coordinate, typename IndexElem> |
209 | void traverseCoordinates3Indexed(Coordinate *coordinates, |
210 | const uint byteStride, |
211 | IndexElem *indices, |
212 | const uint count, |
213 | bool primitiveRestartEnabled, |
214 | int primitiveRestartIndex) |
215 | { |
216 | const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3; |
217 | if (primitiveRestartEnabled) { |
218 | for (uint i = 0; i < count; ++i) { |
219 | if (static_cast<int>(indices[i]) != primitiveRestartIndex) { |
220 | const uint n = stride * indices[i]; |
221 | visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2]); |
222 | } |
223 | } |
224 | } else { |
225 | for (uint i = 0; i < count; ++i) { |
226 | const uint n = stride * indices[i]; |
227 | visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2]); |
228 | } |
229 | } |
230 | } |
231 | |
232 | template <typename Coordinate> |
233 | void traverseCoordinates4(Coordinate *coordinates, |
234 | const uint byteStride, |
235 | const uint count) |
236 | { |
237 | const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4; |
238 | for (uint ndx = 0; ndx < count; ++ndx) { |
239 | visit(ndx, coordinates[0], coordinates[1], coordinates[2], coordinates[3]); |
240 | coordinates += stride; |
241 | } |
242 | } |
243 | |
244 | template <typename Coordinate, typename IndexElem> |
245 | void traverseCoordinates4Indexed(Coordinate *coordinates, |
246 | const uint byteStride, |
247 | IndexElem *indices, |
248 | const uint count, |
249 | bool primitiveRestartEnabled, |
250 | int primitiveRestartIndex) |
251 | { |
252 | const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4; |
253 | if (primitiveRestartEnabled) { |
254 | for (uint i = 0; i < count; ++i) { |
255 | if (static_cast<int>(indices[i]) != primitiveRestartIndex) { |
256 | const uint n = stride * indices[i]; |
257 | visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2], coordinates[n + 3]); |
258 | } |
259 | } |
260 | } else { |
261 | for (uint i = 0; i < count; ++i) { |
262 | const uint n = stride * indices[i]; |
263 | visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2], coordinates[n + 3]); |
264 | } |
265 | } |
266 | } |
267 | }; |
268 | |
269 | typedef BufferVisitor<float, Qt3DCore::QAttribute::Float, 3> Buffer3fVisitor; |
270 | |
271 | } // namespace Qt3DCore |
272 | |
273 | QT_END_NAMESPACE |
274 | |
275 | |
276 | #endif // QT3DCORE_BUFFERVISITOR_P_H |
277 | |