Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
6
7#include "qssgrendermesh_p.h"
10
12
17
22
24{
25 return !m_lines.isEmpty() || !m_persistentLines.isEmpty() || !m_bounds.isEmpty() || !m_persistentBounds.isEmpty() || !m_persistentPoints.isEmpty() || !m_points.isEmpty();
26}
27
29 const QVector3D &endPoint,
30 const QColor &color,
31 bool isPersistent)
32{
33 LineData line = {startPoint, endPoint, color};
34 if (isPersistent)
35 m_persistentLines.append(line);
36 else
37 m_lines.append(line);
38}
39
41 const QColor &color,
42 bool isPersistent)
43{
44 BoundsData bound = {bounds, color};
45 if (isPersistent)
46 m_persistentBounds.append(bound);
47 else
48 m_bounds.append(bound);
49}
50
51void QSSGDebugDrawSystem::drawPoint(const QVector3D &vertex, const QColor &color, bool isPersistent)
52{
53 VertexData point = {vertex, {color.redF(), color.greenF(), color.blueF()}};
54 if (isPersistent)
55 m_persistentPoints.append(point);
56 else
57 m_points.append(point);
58}
59
60
62{
63
64 QVector<VertexData> vertexData;
65 QVector<quint32> indexData;
66 QVector<VertexData> pointsData;
67 for (const auto &line : m_persistentLines)
68 generateLine(line, vertexData, indexData);
69 for (const auto &line : m_lines)
70 generateLine(line, vertexData, indexData);
71 for (const auto &bounds : m_persistentBounds)
72 generateBox(bounds, vertexData, indexData);
73 for (const auto &bounds : m_bounds)
74 generateBox(bounds, vertexData, indexData);
75 pointsData = m_persistentPoints + m_points;
76
77 if (!vertexData.isEmpty()) {
78 // Lines
79 QByteArray vertexBufferData(reinterpret_cast<const char*>(vertexData.constData()), qsizetype(vertexData.count() * 6 * sizeof(float)));
80 QByteArray indexBufferData(reinterpret_cast<const char*>(indexData.constData()), qsizetype(indexData.count() * sizeof(quint32)));
81
82 if (m_lineVertexBuffer)
83 m_lineVertexBuffer.reset();
84 if (m_lineIndexBuffer)
85 m_lineIndexBuffer.reset();
86
87 m_lineVertexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
90 quint32(6 * sizeof(float)),
91 6 * sizeof(float) * vertexData.count());
92 m_lineVertexBuffer->buffer()->setName(QByteArrayLiteral("debug lines vertex buffer"));
93 rub->uploadStaticBuffer(m_lineVertexBuffer->buffer(), vertexBufferData.constData());
94
95 m_lineIndexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
98 0,
99 indexBufferData.size(),
101 m_lineIndexBuffer->buffer()->setName(QByteArrayLiteral("debug lines index buffer"));
102 rub->uploadStaticBuffer(m_lineIndexBuffer->buffer(), indexBufferData.constData());
103
104 m_indexSize = indexData.count();
105 }
106
107 if (!pointsData.isEmpty()) {
108 // Points
109 QByteArray vertexBufferData(reinterpret_cast<const char*>(pointsData.constData()), qsizetype(pointsData.count() * 6 * sizeof(float)));
110
111 if (m_pointVertexBuffer)
112 m_pointVertexBuffer.reset();
113
114 m_pointVertexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
117 quint32(6 * sizeof(float)),
118 vertexBufferData.size());
119 m_pointVertexBuffer->buffer()->setName(QByteArrayLiteral("debug points vertex buffer"));
120 rub->uploadStaticBuffer(m_pointVertexBuffer->buffer(), vertexBufferData.constData());
121 m_pointsSize = pointsData.count();
122 }
123}
124
129{
131 ia.inputLayout.setAttributes({
133 { 0, 1, QRhiVertexInputAttribute::Float3, 3 * sizeof(float) }
134 });
135 ia.inputs << QSSGRhiInputAssemblerState::PositionSemantic
136 << QSSGRhiInputAssemblerState::ColorSemantic;
137 ia.inputLayout.setBindings({6 * sizeof(float)});
138 ia.topology = QRhiGraphicsPipeline::Lines;
142
145 if (m_indexSize > 0) {
146 auto graphicsPipeline = rhiCtxD->pipeline(*ps, rpDesc, srb);
147 cb->setGraphicsPipeline(graphicsPipeline);
148 cb->setShaderResources(srb);
149 cb->setViewport(ps->viewport);
150
151 // Lines
152 QRhiCommandBuffer::VertexInput vb(m_lineVertexBuffer->buffer(), 0);
153 cb->setVertexInput(0, 1, &vb, m_lineIndexBuffer->buffer(), 0, m_lineIndexBuffer->indexFormat());
154 cb->drawIndexed(m_indexSize);
155 }
156
157 // Points
158 if (m_pointsSize > 0) {
159 ia.topology = QRhiGraphicsPipeline::Points;
160 auto graphicsPipeline = rhiCtxD->pipeline(*ps, rpDesc, srb);
161 cb->setGraphicsPipeline(graphicsPipeline);
162 cb->setShaderResources(srb);
163 cb->setViewport(ps->viewport);
164
165 QRhiCommandBuffer::VertexInput vb(m_pointVertexBuffer->buffer(), 0);
166 cb->setVertexInput(0, 1, &vb);
167 cb->draw(m_pointsSize);
168 }
169
170 m_lines.clear();
171 m_bounds.clear();
172 m_points.clear();
173 m_indexSize = 0;
174 m_pointsSize = 0;
175}
176
178{
179 modes = v ? (modes | ModeFlagT(Mode::Other)) : (modes & ~ModeFlagT(Mode::Other));
180}
181
182void QSSGDebugDrawSystem::generateLine(const LineData &line, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
183{
184 const QVector3D color = {line.color.redF(), line.color.greenF(), line.color.blueF()};
185 indexArray.append(vertexArray.count());
186 vertexArray.append({line.startPoint, color});
187 indexArray.append(vertexArray.count());
188 vertexArray.append({line.endPoint, color});
189}
190
191void QSSGDebugDrawSystem::generateBox(const BoundsData &bounds, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
192{
193 const QVector3D color = {bounds.color.redF(), bounds.color.greenF(), bounds.color.blueF()};
194
195 quint32 offset = vertexArray.count();
196 for (const QVector3D point : bounds.bounds.toQSSGBoxPoints())
197 vertexArray.append({point, color});
198
199 indexArray.append(offset + 0);
200 indexArray.append(offset + 3);
201
202 indexArray.append(offset + 3);
203 indexArray.append(offset + 6);
204
205 indexArray.append(offset + 6);
206 indexArray.append(offset + 1);
207
208 indexArray.append(offset + 1);
209 indexArray.append(offset + 0);
210
211 indexArray.append(offset + 2);
212 indexArray.append(offset + 5);
213
214 indexArray.append(offset + 5);
215 indexArray.append(offset + 4);
216
217 indexArray.append(offset + 4);
218 indexArray.append(offset + 7);
219
220 indexArray.append(offset + 7);
221 indexArray.append(offset + 2);
222
223 indexArray.append(offset + 0);
224 indexArray.append(offset + 2);
225
226 indexArray.append(offset + 3);
227 indexArray.append(offset + 5);
228
229 indexArray.append(offset + 6);
230 indexArray.append(offset + 4);
231
232 indexArray.append(offset + 1);
233 indexArray.append(offset + 7);
234
235}
236
237QColor QSSGDebugDrawSystem::levelOfDetailColor(quint32 lod)
238{
239 static const QColor colors[] {
254 };
255
256 const size_t idx = qBound<size_t>(0, lod, std::size(colors) - 1);
257 return colors[idx];
258}
259
260void QSSGDebugDrawSystem::debugNormals(QSSGBufferManager &bufferManager, const QSSGModelContext &theModelContext, const QSSGRenderSubset &theSubset, quint32 subsetLevelOfDetail, float lineLength)
261{
262 const auto &model = theModelContext.model;
263
264 QSSGMesh::Mesh mesh;
265 if (model.geometry)
266 mesh = bufferManager.loadMeshData(model.geometry);
267 else
268 mesh = bufferManager.loadMeshData(model.meshPath);
269
270 if (!mesh.isValid())
271 return; // invalid mesh
272
274 if (vertexData.isEmpty())
275 return; // no vertex dat
276 quint32 vertexStride = mesh.vertexBuffer().stride;
277 QByteArray indexData = mesh.indexBuffer().data;
278 if (indexData.isEmpty())
279 return; // no index data, not what we're after
280 if (mesh.indexBuffer().componentType != QSSGMesh::Mesh::ComponentType::UnsignedInt32)
281 return; // not uint3d, not what we're after either
282
283 quint32 positionOffset = UINT_MAX;
284 quint32 normalOffset = UINT_MAX;
285
286 for (const QSSGMesh::Mesh::VertexBufferEntry &vbe : mesh.vertexBuffer().entries) {
288 positionOffset = vbe.offset;
289 if (vbe.componentType != QSSGMesh::Mesh::ComponentType::Float32 &&
290 vbe.componentCount != 3)
291 return; // not a vec3, some weird stuff
292 } else if (vbe.name == QSSGMesh::MeshInternal::getNormalAttrName()) {
293 normalOffset = vbe.offset;
294 if (vbe.componentType != QSSGMesh::Mesh::ComponentType::Float32 &&
295 vbe.componentCount != 3)
296 return; // not a vec3, really weird normals I guess
297 }
298 }
299
300 const auto globalTransform = model.globalTransform;
301 // Draw original vertex normals as blue lines
302 {
303 // Get Indexes
304 const quint32 *p = reinterpret_cast<const quint32 *>(indexData.constData());
305 const char *vp = vertexData.constData();
306 p += theSubset.offset;
307 for (uint i = 0; i < theSubset.count; ++i) {
308 const quint32 index = *(p + i);
309 const char * posPtr = vp + (index * vertexStride) + positionOffset;
310 const float *fPosPtr = reinterpret_cast<const float *>(posPtr);
311 QVector3D position(fPosPtr[0], fPosPtr[1], fPosPtr[2]);
312 const char * normalPtr = vp + (index * vertexStride) + normalOffset;
313 const float *fNormalPtr = reinterpret_cast<const float *>(normalPtr);
314 QVector3D normal(fNormalPtr[0], fNormalPtr[1], fNormalPtr[2]);
315 position = globalTransform.map(position);
316 normal = QSSGUtils::mat33::transform(theModelContext.normalMatrix, normal);
317 normal = normal.normalized();
318 drawLine(position, position + (normal * lineLength), QColor(Qt::blue));
319 }
320 }
321
322 // Draw lod vertex normals as red lines
323 if (subsetLevelOfDetail != 0) {
324 // Get Indexes
325 const quint32 *p = reinterpret_cast<const quint32 *>(indexData.constData());
326 const char *vp = vertexData.constData();
327 p += theSubset.lodOffset(subsetLevelOfDetail);
328 const quint32 indexCount = theSubset.lodCount(subsetLevelOfDetail);
329 for (uint i = 0; i < indexCount; ++i) {
330 const quint32 index = *(p + i);
331 const char * posPtr = vp + (index * vertexStride) + positionOffset;
332 const float *fPosPtr = reinterpret_cast<const float *>(posPtr);
333 QVector3D position(fPosPtr[0], fPosPtr[1], fPosPtr[2]);
334 const char * normalPtr = vp + (index * vertexStride) + normalOffset;
335 const float *fNormalPtr = reinterpret_cast<const float *>(normalPtr);
336 QVector3D normal(fNormalPtr[0], fNormalPtr[1], fNormalPtr[2]);
337 position = globalTransform.map(position);
338 normal = QSSGUtils::mat33::transform(theModelContext.normalMatrix, normal);
339 normal = normal.normalized();
340 drawLine(position, position + (normal * lineLength), QColor(Qt::red));
341 }
342 }
343}
344
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
@ Immutable
Definition qrhi.h:849
@ IndexBuffer
Definition qrhi.h:856
@ VertexBuffer
Definition qrhi.h:855
\inmodule QtGui
Definition qrhi.h:1651
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
Definition qrhi.h:1680
\inmodule QtGui
Definition qrhi.h:1142
\inmodule QtGui
Definition qrhi.h:1731
\inmodule QtGui
Definition qrhi.h:1214
Class representing 3D range or axis aligned bounding box.
static QSSGMesh::Mesh loadMeshData(const QSSGRenderPath &inSourcePath)
void drawLine(const QVector3D &startPoint, const QVector3D &endPoint, const QColor &color, bool isPersistent=false)
void recordRenderDebugObjects(QSSGRhiContext *rhiCtx, QSSGRhiGraphicsPipelineState *ps, QRhiShaderResourceBindings *srb, QRhiRenderPassDescriptor *rpDesc)
void drawPoint(const QVector3D &vertex, const QColor &color, bool isPersistent=false)
void prepareGeometry(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *rub)
void drawBounds(const QSSGBounds3 &bounds, const QColor &color, bool isPersistent=false)
bool isValid() const
Definition qssgmesh_p.h:159
VertexBuffer vertexBuffer() const
Definition qssgmesh_p.h:140
IndexBuffer indexBuffer() const
Definition qssgmesh_p.h:141
static QSSGRhiContextPrivate * get(QSSGRhiContext *q)
\inmodule QtQuick3D
QRhiCommandBuffer * commandBuffer() const
QRhiGraphicsPipeline::CullMode cullMode
QString & append(QChar c)
Definition qstring.cpp:3252
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
list append(new Employee("Blackpool", "Stephen"))
QVector3D Q_QUICK3DUTILS_EXPORT transform(const QMatrix3x3 &m, const QVector3D &v)
Definition qssgutils.cpp:43
Combined button and popup list for selecting options.
@ darkRed
Definition qnamespace.h:41
@ darkCyan
Definition qnamespace.h:44
@ cyan
Definition qnamespace.h:38
@ white
Definition qnamespace.h:31
@ blue
Definition qnamespace.h:37
@ magenta
Definition qnamespace.h:39
@ yellow
Definition qnamespace.h:40
@ darkBlue
Definition qnamespace.h:43
@ darkGray
Definition qnamespace.h:32
@ darkMagenta
Definition qnamespace.h:45
@ green
Definition qnamespace.h:36
@ red
Definition qnamespace.h:35
@ darkGreen
Definition qnamespace.h:42
@ darkYellow
Definition qnamespace.h:46
#define QByteArrayLiteral(str)
Definition qbytearray.h:52
GLsizei const GLfloat * v
[13]
GLuint index
[2]
GLuint color
[2]
GLenum GLuint GLintptr offset
GLint lod
GLfloat GLfloat p
[1]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QT_BEGIN_NAMESPACE const QRgb colors[][14]
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
unsigned int quint32
Definition qtypes.h:50
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
float vertexData[]
QSqlQueryModel * model
[16]
static const char * getNormalAttrName()
Definition qssgmesh_p.h:393
static const char * getPositionAttrName()
Definition qssgmesh_p.h:392
static const InputAssemblerState & get(const QSSGRhiGraphicsPipelineState &ps)