Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qssgdebugdrawsystem.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
6#include "graphobjects/qssgrendermodel_p.h"
8
10#include "resourcemanager/qssgrenderbuffermanager_p.h"
11#include "rendererimpl/qssgrenderableobjects_p.h"
12#include "rendererimpl/qssglayerrenderdata_p.h"
13
15
16QSSGDebugDrawSystem::QSSGDebugDrawSystem()
17{
18
19}
20
21QSSGDebugDrawSystem::~QSSGDebugDrawSystem()
22{
23
24}
25
26bool QSSGDebugDrawSystem::hasContent() const
27{
28 return !m_lines.isEmpty() || !m_persistentLines.isEmpty() || !m_bounds.isEmpty() || !m_persistentBounds.isEmpty() || !m_persistentPoints.isEmpty() || !m_points.isEmpty();
29}
30
31void QSSGDebugDrawSystem::drawLine(const QVector3D &startPoint,
32 const QVector3D &endPoint,
33 const QColor &color,
34 bool isPersistent)
35{
36 LineData line = {startPoint, endPoint, color};
37 if (isPersistent)
38 m_persistentLines.append(line);
39 else
40 m_lines.append(line);
41}
42
43void QSSGDebugDrawSystem::drawBounds(const QSSGBounds3 &bounds,
44 const QColor &color,
45 bool isPersistent)
46{
47 BoundsData bound = {bounds, color};
48 if (isPersistent)
49 m_persistentBounds.append(bound);
50 else
51 m_bounds.append(bound);
52}
53
54void QSSGDebugDrawSystem::drawPoint(const QVector3D &vertex, const QColor &color, bool isPersistent)
55{
56 VertexData point = {vertex, {color.redF(), color.greenF(), color.blueF()}};
57 if (isPersistent)
58 m_persistentPoints.append(point);
59 else
60 m_points.append(point);
61}
62
63
64void QSSGDebugDrawSystem::prepareGeometry(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *rub)
65{
66
67 QVector<VertexData> vertexData;
68 QVector<quint32> indexData;
69 QVector<VertexData> pointsData;
70 for (const auto &line : m_persistentLines)
71 generateLine(line, vertexData, indexData);
72 for (const auto &line : m_lines)
73 generateLine(line, vertexData, indexData);
74 for (const auto &bounds : m_persistentBounds)
75 generateBox(bounds, vertexData, indexData);
76 for (const auto &bounds : m_bounds)
77 generateBox(bounds, vertexData, indexData);
78 pointsData = m_persistentPoints + m_points;
79
80 if (!vertexData.isEmpty()) {
81 // Lines
82 QByteArray vertexBufferData(reinterpret_cast<const char*>(vertexData.constData()), qsizetype(vertexData.count() * 6 * sizeof(float)));
83 QByteArray indexBufferData(reinterpret_cast<const char*>(indexData.constData()), qsizetype(indexData.count() * sizeof(quint32)));
84
85 if (m_lineVertexBuffer)
86 m_lineVertexBuffer.reset();
87 if (m_lineIndexBuffer)
88 m_lineIndexBuffer.reset();
89
90 m_lineVertexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
91 QRhiBuffer::Immutable,
92 QRhiBuffer::VertexBuffer,
93 quint32(6 * sizeof(float)),
94 6 * sizeof(float) * vertexData.count());
95 m_lineVertexBuffer->buffer()->setName(QByteArrayLiteral("debug lines vertex buffer"));
96 rub->uploadStaticBuffer(m_lineVertexBuffer->buffer(), vertexBufferData.constData());
97
98 m_lineIndexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
99 QRhiBuffer::Immutable,
100 QRhiBuffer::IndexBuffer,
101 0,
102 indexBufferData.size(),
103 QRhiCommandBuffer::IndexUInt32);
104 m_lineIndexBuffer->buffer()->setName(QByteArrayLiteral("debug lines index buffer"));
105 rub->uploadStaticBuffer(m_lineIndexBuffer->buffer(), indexBufferData.constData());
106
107 m_indexSize = indexData.count();
108 }
109
110 if (!pointsData.isEmpty()) {
111 // Points
112 QByteArray vertexBufferData(reinterpret_cast<const char*>(pointsData.constData()), qsizetype(pointsData.count() * 6 * sizeof(float)));
113
114 if (m_pointVertexBuffer)
115 m_pointVertexBuffer.reset();
116
117 m_pointVertexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
118 QRhiBuffer::Immutable,
119 QRhiBuffer::VertexBuffer,
120 quint32(6 * sizeof(float)),
121 vertexBufferData.size());
122 m_pointVertexBuffer->buffer()->setName(QByteArrayLiteral("debug points vertex buffer"));
123 rub->uploadStaticBuffer(m_pointVertexBuffer->buffer(), vertexBufferData.constData());
124 m_pointsSize = pointsData.count();
125 }
126}
127
128void QSSGDebugDrawSystem::recordRenderDebugObjects(QSSGRhiContext *rhiCtx,
129 QSSGRhiGraphicsPipelineState *ps,
130 QRhiShaderResourceBindings *srb,
131 QRhiRenderPassDescriptor *rpDesc)
132{
133 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
134 ia.inputLayout.setAttributes({
135 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
136 { 0, 1, QRhiVertexInputAttribute::Float3, 3 * sizeof(float) }
137 });
138 ia.inputs << QSSGRhiInputAssemblerState::PositionSemantic
139 << QSSGRhiInputAssemblerState::ColorSemantic;
140 ia.inputLayout.setBindings({6 * sizeof(float)});
141 ia.topology = QRhiGraphicsPipeline::Lines;
142 ps->flags |= QSSGRhiGraphicsPipelineState::Flag::DepthWriteEnabled;
143 ps->flags |= QSSGRhiGraphicsPipelineState::Flag::DepthTestEnabled;
144 ps->cullMode = QRhiGraphicsPipeline::None;
145
146 QSSGRhiContextPrivate *rhiCtxD = QSSGRhiContextPrivate::get(rhiCtx);
147 QRhiCommandBuffer *cb = rhiCtx->commandBuffer();
148 if (m_indexSize > 0) {
149 auto graphicsPipeline = rhiCtxD->pipeline(*ps, rpDesc, srb);
150 cb->setGraphicsPipeline(graphicsPipeline);
151 cb->setShaderResources(srb);
152 cb->setViewport(ps->viewport);
153
154 // Lines
155 QRhiCommandBuffer::VertexInput vb(m_lineVertexBuffer->buffer(), 0);
156 cb->setVertexInput(0, 1, &vb, m_lineIndexBuffer->buffer(), 0, m_lineIndexBuffer->indexFormat());
157 cb->drawIndexed(m_indexSize);
158 }
159
160 // Points
161 if (m_pointsSize > 0) {
162 ia.topology = QRhiGraphicsPipeline::Points;
163 auto graphicsPipeline = rhiCtxD->pipeline(*ps, rpDesc, srb);
164 cb->setGraphicsPipeline(graphicsPipeline);
165 cb->setShaderResources(srb);
166 cb->setViewport(ps->viewport);
167
168 QRhiCommandBuffer::VertexInput vb(m_pointVertexBuffer->buffer(), 0);
169 cb->setVertexInput(0, 1, &vb);
170 cb->draw(m_pointsSize);
171 }
172
173 m_lines.clear();
174 m_bounds.clear();
175 m_points.clear();
176 m_indexSize = 0;
177 m_pointsSize = 0;
178}
179
180void QSSGDebugDrawSystem::setEnabled(bool v)
181{
182 modes = v ? (modes | ModeFlagT(Mode::Other)) : (modes & ~ModeFlagT(Mode::Other));
183}
184
185void QSSGDebugDrawSystem::generateLine(const LineData &line, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
186{
187 const QVector3D color = {line.color.redF(), line.color.greenF(), line.color.blueF()};
188 indexArray.append(vertexArray.count());
189 vertexArray.append({line.startPoint, color});
190 indexArray.append(vertexArray.count());
191 vertexArray.append({line.endPoint, color});
192}
193
194void QSSGDebugDrawSystem::generateBox(const BoundsData &bounds, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
195{
196 const QVector3D color = {bounds.color.redF(), bounds.color.greenF(), bounds.color.blueF()};
197
198 quint32 offset = vertexArray.count();
199 for (const QVector3D point : bounds.bounds.toQSSGBoxPoints())
200 vertexArray.append({point, color});
201
202 indexArray.append(offset + 0);
203 indexArray.append(offset + 3);
204
205 indexArray.append(offset + 3);
206 indexArray.append(offset + 6);
207
208 indexArray.append(offset + 6);
209 indexArray.append(offset + 1);
210
211 indexArray.append(offset + 1);
212 indexArray.append(offset + 0);
213
214 indexArray.append(offset + 2);
215 indexArray.append(offset + 5);
216
217 indexArray.append(offset + 5);
218 indexArray.append(offset + 4);
219
220 indexArray.append(offset + 4);
221 indexArray.append(offset + 7);
222
223 indexArray.append(offset + 7);
224 indexArray.append(offset + 2);
225
226 indexArray.append(offset + 0);
227 indexArray.append(offset + 2);
228
229 indexArray.append(offset + 3);
230 indexArray.append(offset + 5);
231
232 indexArray.append(offset + 6);
233 indexArray.append(offset + 4);
234
235 indexArray.append(offset + 1);
236 indexArray.append(offset + 7);
237
238}
239
240QColor QSSGDebugDrawSystem::levelOfDetailColor(quint32 lod)
241{
242 static const QColor colors[] {
243 QColor(Qt::white),
244 QColor(Qt::red),
245 QColor(Qt::green),
246 QColor(Qt::blue),
247 QColor(Qt::yellow),
248 QColor(Qt::cyan),
249 QColor(Qt::magenta),
250 QColor(Qt::darkRed),
251 QColor(Qt::darkGreen),
252 QColor(Qt::darkBlue),
253 QColor(Qt::darkCyan),
254 QColor(Qt::darkMagenta),
255 QColor(Qt::darkYellow),
256 QColor(Qt::darkGray)
257 };
258
259 const size_t idx = qBound<size_t>(0, lod, std::size(colors) - 1);
260 return colors[idx];
261}
262
263void QSSGDebugDrawSystem::debugNormals(QSSGBufferManager &bufferManager, const QSSGModelContext &theModelContext, const QSSGRenderSubset &theSubset, quint32 subsetLevelOfDetail, float lineLength)
264{
265 const auto &model = theModelContext.model;
266
267 QSSGMesh::Mesh mesh;
268 if (model.geometry)
269 mesh = bufferManager.loadMeshData(model.geometry);
270 else
271 mesh = bufferManager.loadMeshData(model.meshPath);
272
273 if (!mesh.isValid())
274 return; // invalid mesh
275
276 QByteArray vertexData = mesh.vertexBuffer().data;
277 if (vertexData.isEmpty())
278 return; // no vertex dat
279 quint32 vertexStride = mesh.vertexBuffer().stride;
280 QByteArray indexData = mesh.indexBuffer().data;
281 if (indexData.isEmpty())
282 return; // no index data, not what we're after
283 if (mesh.indexBuffer().componentType != QSSGMesh::Mesh::ComponentType::UnsignedInt32)
284 return; // not uint3d, not what we're after either
285
286 quint32 positionOffset = UINT_MAX;
287 quint32 normalOffset = UINT_MAX;
288
289 for (const QSSGMesh::Mesh::VertexBufferEntry &vbe : mesh.vertexBuffer().entries) {
290 if (vbe.name == QSSGMesh::MeshInternal::getPositionAttrName()) {
291 positionOffset = vbe.offset;
292 if (vbe.componentType != QSSGMesh::Mesh::ComponentType::Float32 &&
293 vbe.componentCount != 3)
294 return; // not a vec3, some weird stuff
295 } else if (vbe.name == QSSGMesh::MeshInternal::getNormalAttrName()) {
296 normalOffset = vbe.offset;
297 if (vbe.componentType != QSSGMesh::Mesh::ComponentType::Float32 &&
298 vbe.componentCount != 3)
299 return; // not a vec3, really weird normals I guess
300 }
301 }
302
303 const auto &globalTransform = theModelContext.globalTransform;
304 // Draw original vertex normals as blue lines
305 {
306 // Get Indexes
307 const quint32 *p = reinterpret_cast<const quint32 *>(indexData.constData());
308 const char *vp = vertexData.constData();
309 p += theSubset.offset;
310 for (uint i = 0; i < theSubset.count; ++i) {
311 const quint32 index = *(p + i);
312 const char * posPtr = vp + (index * vertexStride) + positionOffset;
313 const float *fPosPtr = reinterpret_cast<const float *>(posPtr);
314 QVector3D position(fPosPtr[0], fPosPtr[1], fPosPtr[2]);
315 const char * normalPtr = vp + (index * vertexStride) + normalOffset;
316 const float *fNormalPtr = reinterpret_cast<const float *>(normalPtr);
317 QVector3D normal(fNormalPtr[0], fNormalPtr[1], fNormalPtr[2]);
318 position = globalTransform.map(position);
319 normal = QSSGUtils::mat33::transform(theModelContext.normalMatrix, normal);
320 normal = normal.normalized();
321 drawLine(position, position + (normal * lineLength), QColor(Qt::blue));
322 }
323 }
324
325 // Draw lod vertex normals as red lines
326 if (subsetLevelOfDetail != 0) {
327 // Get Indexes
328 const quint32 *p = reinterpret_cast<const quint32 *>(indexData.constData());
329 const char *vp = vertexData.constData();
330 p += theSubset.lodOffset(subsetLevelOfDetail);
331 const quint32 indexCount = theSubset.lodCount(subsetLevelOfDetail);
332 for (uint i = 0; i < indexCount; ++i) {
333 const quint32 index = *(p + i);
334 const char * posPtr = vp + (index * vertexStride) + positionOffset;
335 const float *fPosPtr = reinterpret_cast<const float *>(posPtr);
336 QVector3D position(fPosPtr[0], fPosPtr[1], fPosPtr[2]);
337 const char * normalPtr = vp + (index * vertexStride) + normalOffset;
338 const float *fNormalPtr = reinterpret_cast<const float *>(normalPtr);
339 QVector3D normal(fNormalPtr[0], fNormalPtr[1], fNormalPtr[2]);
340 position = globalTransform.map(position);
341 normal = QSSGUtils::mat33::transform(theModelContext.normalMatrix, normal);
342 normal = normal.normalized();
343 drawLine(position, position + (normal * lineLength), QColor(Qt::red));
344 }
345 }
346}
347
348QT_END_NAMESPACE
Combined button and popup list for selecting options.