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#include "segmentsvisitor_p.h"
5#include <Qt3DCore/qentity.h>
6#include <Qt3DRender/qgeometryrenderer.h>
7#include <Qt3DRender/private/managers_p.h>
8#include <Qt3DRender/private/nodemanagers_p.h>
9#include <Qt3DRender/private/buffermanager_p.h>
10#include <Qt3DRender/private/geometryrenderer_p.h>
11#include <Qt3DRender/private/geometryrenderermanager_p.h>
12#include <Qt3DRender/private/geometry_p.h>
13#include <Qt3DRender/private/attribute_p.h>
14#include <Qt3DRender/private/buffer_p.h>
15#include <Qt3DRender/private/trianglesvisitor_p.h>
16#include <Qt3DRender/private/visitorutils_p.h>
17
18QT_BEGIN_NAMESPACE
19
20namespace Qt3DRender {
21
22namespace Render {
23
24namespace {
25
26bool isSegmentBased(Qt3DRender::QGeometryRenderer::PrimitiveType type) noexcept
27{
28 switch (type) {
29 case Qt3DRender::QGeometryRenderer::Lines:
30 case Qt3DRender::QGeometryRenderer::LineStrip:
31 case Qt3DRender::QGeometryRenderer::LineLoop:
32 case Qt3DRender::QGeometryRenderer::LinesAdjacency:
33 case Qt3DRender::QGeometryRenderer::LineStripAdjacency:
34 return true;
35 default:
36 return false;
37 }
38}
39
40// indices, vertices are already offset
41template<typename Index, typename Vertex>
42void traverseSegmentsIndexed(Index *indices,
43 Vertex *vertices,
44 const BufferInfo &indexInfo,
45 const BufferInfo &vertexInfo,
46 SegmentsVisitor *visitor)
47{
48 uint i = 0;
49 const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
50 const uint maxVerticesDataSize = qMin(a: vertexInfo.dataSize, b: 3U);
51
52 uint ndx[2];
53 Vector3D abc[2];
54 while (i < indexInfo.count) {
55 for (uint u = 0; u < 2; ++u) {
56 ndx[u] = indices[i + u];
57 const uint idx = ndx[u] * verticesStride;
58 for (uint j = 0; j < maxVerticesDataSize; ++j) {
59 abc[u][j] = vertices[idx + j];
60 }
61 }
62 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
63 i += 2;
64 }
65}
66
67// vertices are already offset
68template<typename Vertex>
69void traverseSegments(Vertex *vertices,
70 const BufferInfo &vertexInfo,
71 SegmentsVisitor *visitor)
72{
73 uint i = 0;
74
75 const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
76 const uint maxVerticesDataSize = qMin(a: vertexInfo.dataSize, b: 3U);
77
78 uint ndx[2];
79 Vector3D abc[2];
80 while (i < vertexInfo.count) {
81 for (uint u = 0; u < 2; ++u) {
82 ndx[u] = (i + u);
83 const uint idx = ndx[u] * verticesStride;
84 for (uint j = 0; j < maxVerticesDataSize; ++j)
85 abc[u][j] = vertices[idx + j];
86 }
87 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
88 i += 2;
89 }
90}
91
92// indices, vertices are already offset
93template<typename Index, typename Vertex>
94void traverseSegmentStripIndexed(Index *indices,
95 Vertex *vertices,
96 const BufferInfo &indexInfo,
97 const BufferInfo &vertexInfo,
98 SegmentsVisitor *visitor,
99 bool loop)
100{
101 uint i = 0;
102 uint stripStartIndex = 0;
103
104 const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
105 const uint maxVerticesDataSize = qMin(a: vertexInfo.dataSize, b: 3U);
106
107 uint ndx[2];
108 Vector3D abc[2];
109 while (i < indexInfo.count) {
110 if (indexInfo.restartEnabled && indexInfo.restartIndexValue == static_cast<int>(indices[i])) {
111 ++i;
112 continue;
113 }
114 stripStartIndex = i;
115 ndx[0] = indices[stripStartIndex];
116 uint idx = ndx[0] * verticesStride;
117 for (uint j = 0; j < maxVerticesDataSize; ++j)
118 abc[0][j] = vertices[idx + j];
119 ++i;
120 while (i < indexInfo.count && (!indexInfo.restartEnabled || indexInfo.restartIndexValue != static_cast<int>(indices[i]))) {
121 ndx[1] = indices[i];
122 if (ndx[0] != ndx[1]) {
123 idx = ndx[1] * verticesStride;
124 for (uint j = 0; j < maxVerticesDataSize; ++j)
125 abc[1][j] = vertices[idx + j];
126 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
127 }
128 ++i;
129 ndx[0] = ndx[1];
130 abc[0] = abc[1];
131 }
132 if (loop) {
133 ndx[1] = indices[stripStartIndex];
134 if (ndx[0] != ndx[1]) {
135 idx = ndx[1] * verticesStride;
136 for (uint j = 0; j < maxVerticesDataSize; ++j)
137 abc[1][j] = vertices[idx + j];
138 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
139 }
140 }
141 }
142}
143
144// vertices are already offset
145template<typename Vertex>
146void traverseSegmentStrip(Vertex *vertices,
147 const BufferInfo &vertexInfo,
148 SegmentsVisitor *visitor,
149 bool loop)
150{
151 uint i = 0;
152
153 if (vertexInfo.count < 1)
154 return;
155
156 const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
157 const uint maxVerticesDataSize = qMin(a: vertexInfo.dataSize, b: 3U);
158
159 uint ndx[2];
160 Vector3D abc[2];
161 ndx[0] = i;
162 uint idx = ndx[0] * verticesStride;
163 for (uint j = 0; j < maxVerticesDataSize; ++j)
164 abc[0][j] = vertices[idx + j];
165 while (i < vertexInfo.count - 1) {
166 ndx[1] = (i + 1);
167 idx = ndx[1] * verticesStride;
168 for (uint j = 0; j < maxVerticesDataSize; ++j)
169 abc[1][j] = vertices[idx + j];
170 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
171 ++i;
172 ndx[0] = ndx[1];
173 abc[0] = abc[1];
174 }
175 if (loop) {
176 ndx[1] = 0;
177 idx = ndx[1] * verticesStride;
178 for (uint j = 0; j < maxVerticesDataSize; ++j)
179 abc[1][j] = vertices[idx + j];
180 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
181 }
182}
183
184// indices, vertices are already offset
185template<typename Index, typename Vertex>
186void traverseSegmentAdjacencyIndexed(Index *indices,
187 Vertex *vertices,
188 const BufferInfo &indexInfo,
189 const BufferInfo &vertexInfo,
190 SegmentsVisitor *visitor)
191{
192 uint i = 1;
193 uint n = indexInfo.count - 1;
194 const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
195 const uint maxVerticesDataSize = qMin(a: vertexInfo.dataSize, b: 3U);
196
197 uint ndx[2];
198 Vector3D abc[2];
199 while (i < n) {
200 for (uint u = 0; u < 2; ++u) {
201 ndx[u] = indices[i + u];
202 const uint idx = ndx[u] * verticesStride;
203 for (uint j = 0; j < maxVerticesDataSize; ++j) {
204 abc[u][j] = vertices[idx + j];
205 }
206 }
207 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
208 i += 2;
209 }
210}
211
212// vertices are already offset
213template<typename Vertex>
214void traverseSegmentAdjacency(Vertex *vertices,
215 const BufferInfo &vertexInfo,
216 SegmentsVisitor *visitor)
217{
218 uint i = 1;
219 uint n = vertexInfo.count - 1;
220
221 const uint verticesStride = vertexInfo.byteStride / sizeof(Vertex);
222 const uint maxVerticesDataSize = qMin(a: vertexInfo.dataSize, b: 3U);
223
224 uint ndx[2];
225 Vector3D abc[2];
226 while (i < n) {
227 for (uint u = 0; u < 2; ++u) {
228 ndx[u] = (i + u);
229 const uint idx = ndx[u] * verticesStride;
230 for (uint j = 0; j < maxVerticesDataSize; ++j)
231 abc[u][j] = vertices[idx + j];
232 }
233 visitor->visit(andx: ndx[0], a: abc[0], bndx: ndx[1], b: abc[1]);
234 i += 2;
235 }
236}
237
238template<typename Index, typename Visitor>
239struct IndexedVertexExecutor
240{
241 template<typename Vertex>
242 void operator ()(const BufferInfo &vertexInfo, Vertex * vertices)
243 {
244 switch (m_primitiveType) {
245 case Qt3DRender::QGeometryRenderer::Lines:
246 traverseSegmentsIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor);
247 return;
248 case Qt3DRender::QGeometryRenderer::LineStrip:
249 traverseSegmentStripIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor, false);
250 return;
251 case Qt3DRender::QGeometryRenderer::LineLoop:
252 traverseSegmentStripIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor, true);
253 return;
254 case Qt3DRender::QGeometryRenderer::LinesAdjacency:
255 traverseSegmentAdjacencyIndexed(m_indices, vertices, m_indexBufferInfo, vertexInfo, m_visitor);
256 return;
257 case Qt3DRender::QGeometryRenderer::LineStripAdjacency: // fall through
258 default:
259 Q_UNREACHABLE();
260 return;
261 }
262 }
263
264 BufferInfo m_indexBufferInfo;
265 Index *m_indices;
266 Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType;
267 Visitor* m_visitor;
268};
269
270template<typename Visitor>
271struct IndexExecutor
272{
273 template<typename Index>
274 void operator ()( const BufferInfo &indexInfo, Index *indices)
275 {
276 IndexedVertexExecutor<Index, Visitor> exec;
277 exec.m_primitiveType = m_primitiveType;
278 exec.m_indices = indices;
279 exec.m_indexBufferInfo = indexInfo;
280 exec.m_visitor = m_visitor;
281 Qt3DRender::Render::Visitor::processBuffer(m_vertexBufferInfo, exec);
282 }
283
284 BufferInfo m_vertexBufferInfo;
285 Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType;
286 Visitor* m_visitor;
287};
288
289template<typename Visitor>
290struct VertexExecutor
291{
292 template<typename Vertex>
293 void operator ()(const BufferInfo &vertexInfo, Vertex *vertices)
294 {
295 switch (m_primitiveType) {
296 case Qt3DRender::QGeometryRenderer::Lines:
297 traverseSegments(vertices, vertexInfo, m_visitor);
298 return;
299 case Qt3DRender::QGeometryRenderer::LineStrip:
300 traverseSegmentStrip(vertices, vertexInfo, m_visitor, false);
301 return;
302 case Qt3DRender::QGeometryRenderer::LineLoop:
303 traverseSegmentStrip(vertices, vertexInfo, m_visitor, true);
304 return;
305 case Qt3DRender::QGeometryRenderer::LinesAdjacency:
306 traverseSegmentAdjacency(vertices, vertexInfo, m_visitor);
307 return;
308 case Qt3DRender::QGeometryRenderer::LineStripAdjacency: // fall through
309 default:
310 Q_UNREACHABLE();
311 return;
312 }
313 }
314
315 Qt3DRender::QGeometryRenderer::PrimitiveType m_primitiveType;
316 Visitor* m_visitor;
317};
318
319} // anonymous
320
321
322SegmentsVisitor::~SegmentsVisitor()
323{
324
325}
326
327void SegmentsVisitor::apply(const Qt3DCore::QEntity *entity)
328{
329 GeometryRenderer *renderer = m_manager->geometryRendererManager()->lookupResource(id: entity->id());
330 apply(renderer, id: entity->id());
331}
332
333void SegmentsVisitor::apply(const GeometryRenderer *renderer, const Qt3DCore::QNodeId id)
334{
335 m_nodeId = id;
336 if (renderer && renderer->instanceCount() == 1 && isSegmentBased(type: renderer->primitiveType())) {
337 Visitor::visitPrimitives<GeometryRenderer, VertexExecutor<SegmentsVisitor>,
338 IndexExecutor<SegmentsVisitor>, SegmentsVisitor>(manager: m_manager, renderer, visitor: this);
339 }
340}
341
342void SegmentsVisitor::apply(const PickingProxy *proxy, const Qt3DCore::QNodeId id)
343{
344 m_nodeId = id;
345 if (proxy && proxy->instanceCount() == 1 && isSegmentBased(type: static_cast<Qt3DRender::QGeometryRenderer::PrimitiveType>(proxy->primitiveType()))) {
346 Visitor::visitPrimitives<PickingProxy, VertexExecutor<SegmentsVisitor>,
347 IndexExecutor<SegmentsVisitor>, SegmentsVisitor>(manager: m_manager, renderer: proxy, visitor: this);
348 }
349}
350
351} // namespace Render
352
353} // namespace Qt3DRender
354
355QT_END_NAMESPACE
356

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qt3d/src/render/backend/segmentsvisitor.cpp