4#include "graphobjects/qssgrendermodel_p.h"
8#include "resourcemanager/qssgrenderbuffermanager_p.h"
9#include "rendererimpl/qssgrenderableobjects_p.h"
10#include "rendererimpl/qssglayerrenderdata_p.h"
14QSSGDebugDrawSystem::QSSGDebugDrawSystem()
19QSSGDebugDrawSystem::~QSSGDebugDrawSystem()
24bool QSSGDebugDrawSystem::hasContent()
const
26 return !m_lines.isEmpty() || !m_persistentLines.isEmpty() || !m_bounds.isEmpty() || !m_persistentBounds.isEmpty() || !m_persistentPoints.isEmpty() || !m_points.isEmpty();
29void QSSGDebugDrawSystem::drawLine(
const QVector3D &startPoint,
30 const QVector3D &endPoint,
34 LineData line = {startPoint, endPoint, color};
36 m_persistentLines.append(line);
41void QSSGDebugDrawSystem::drawBounds(
const QSSGBounds3 &bounds,
45 BoundsData bound = {bounds, color};
47 m_persistentBounds.append(bound);
49 m_bounds.append(bound);
52void QSSGDebugDrawSystem::drawPoint(
const QVector3D &vertex,
const QColor &color,
bool isPersistent)
54 VertexData point = {vertex, {color.redF(), color.greenF(), color.blueF()}};
56 m_persistentPoints.append(point);
58 m_points.append(point);
62void QSSGDebugDrawSystem::prepareGeometry(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *rub)
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;
78 if (!vertexData.isEmpty()) {
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)));
83 if (m_lineVertexBuffer)
84 m_lineVertexBuffer.reset();
85 if (m_lineIndexBuffer)
86 m_lineIndexBuffer.reset();
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());
96 m_lineIndexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
97 QRhiBuffer::Immutable,
98 QRhiBuffer::IndexBuffer,
100 indexBufferData.size(),
101 QRhiCommandBuffer::IndexUInt32);
102 m_lineIndexBuffer->buffer()->setName(QByteArrayLiteral(
"debug lines index buffer"));
103 rub->uploadStaticBuffer(m_lineIndexBuffer->buffer(), indexBufferData.constData());
105 m_indexSize = indexData.count();
108 if (!pointsData.isEmpty()) {
110 QByteArray vertexBufferData(
reinterpret_cast<
const char*>(pointsData.constData()), qsizetype(pointsData.count() * 6 *
sizeof(
float)));
112 if (m_pointVertexBuffer)
113 m_pointVertexBuffer.reset();
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();
126void QSSGDebugDrawSystem::recordRenderDebugObjects(QSSGRhiContext *rhiCtx,
127 QSSGRhiGraphicsPipelineState *ps,
128 QRhiShaderResourceBindings *srb,
129 QRhiRenderPassDescriptor *rpDesc)
131 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
132 ia.inputLayout.setAttributes({
133 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
134 { 0, 1, QRhiVertexInputAttribute::Float3, 3 *
sizeof(
float) }
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;
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);
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);
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);
166 QRhiCommandBuffer::VertexInput vb(m_pointVertexBuffer->buffer(), 0);
167 cb->setVertexInput(0, 1, &vb);
168 cb->draw(m_pointsSize);
178void QSSGDebugDrawSystem::setEnabled(
bool v)
180 modes = v ? (modes | ModeFlagT(Mode::Other)) : (modes & ~ModeFlagT(Mode::Other));
183void QSSGDebugDrawSystem::generateLine(
const LineData &line, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
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});
192void QSSGDebugDrawSystem::generateBox(
const BoundsData &bounds, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
194 const QVector3D color = {bounds.color.redF(), bounds.color.greenF(), bounds.color.blueF()};
196 quint32 offset = vertexArray.count();
197 for (
const QVector3D point : bounds.bounds.toQSSGBoxPoints())
198 vertexArray.append({point, color});
200 indexArray.append(offset + 0);
201 indexArray.append(offset + 3);
203 indexArray.append(offset + 3);
204 indexArray.append(offset + 6);
206 indexArray.append(offset + 6);
207 indexArray.append(offset + 1);
209 indexArray.append(offset + 1);
210 indexArray.append(offset + 0);
212 indexArray.append(offset + 2);
213 indexArray.append(offset + 5);
215 indexArray.append(offset + 5);
216 indexArray.append(offset + 4);
218 indexArray.append(offset + 4);
219 indexArray.append(offset + 7);
221 indexArray.append(offset + 7);
222 indexArray.append(offset + 2);
224 indexArray.append(offset + 0);
225 indexArray.append(offset + 2);
227 indexArray.append(offset + 3);
228 indexArray.append(offset + 5);
230 indexArray.append(offset + 6);
231 indexArray.append(offset + 4);
233 indexArray.append(offset + 1);
234 indexArray.append(offset + 7);
238QColor QSSGDebugDrawSystem::levelOfDetailColor(quint32 lod)
240 static const QColor colors[] {
249 QColor(Qt::darkGreen),
250 QColor(Qt::darkBlue),
251 QColor(Qt::darkCyan),
252 QColor(Qt::darkMagenta),
253 QColor(Qt::darkYellow),
257 const size_t idx = qBound<size_t>(0, lod, std::size(colors) - 1);
261void QSSGDebugDrawSystem::debugNormals(QSSGBufferManager &bufferManager,
const QSSGModelContext &theModelContext,
const QSSGRenderSubset &theSubset, quint32 subsetLevelOfDetail,
float lineLength)
263 const auto &model = theModelContext.model;
267 mesh = bufferManager.loadMeshData(model.geometry);
269 mesh = bufferManager.loadMeshData(model.meshPath);
274 QByteArray vertexData = mesh.vertexBuffer().data;
275 if (vertexData.isEmpty())
277 quint32 vertexStride = mesh.vertexBuffer().stride;
278 QByteArray indexData = mesh.indexBuffer().data;
279 if (indexData.isEmpty())
281 if (mesh.indexBuffer().componentType != QSSGMesh::Mesh::ComponentType::UnsignedInt32)
284 quint32 positionOffset = UINT_MAX;
285 quint32 normalOffset = UINT_MAX;
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)
293 }
else if (vbe.name == QSSGMesh::MeshInternal::getNormalAttrName()) {
294 normalOffset = vbe.offset;
295 if (vbe.componentType != QSSGMesh::Mesh::ComponentType::Float32 &&
296 vbe.componentCount != 3)
301 const auto &globalTransform = theModelContext.globalTransform;
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));
324 if (subsetLevelOfDetail != 0) {
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));