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