6#include "graphobjects/qssgrendermodel_p.h"
10#include "resourcemanager/qssgrenderbuffermanager_p.h"
11#include "rendererimpl/qssgrenderableobjects_p.h"
12#include "rendererimpl/qssglayerrenderdata_p.h"
16QSSGDebugDrawSystem::QSSGDebugDrawSystem()
21QSSGDebugDrawSystem::~QSSGDebugDrawSystem()
26bool QSSGDebugDrawSystem::hasContent()
const
28 return !m_lines.isEmpty() || !m_persistentLines.isEmpty() || !m_bounds.isEmpty() || !m_persistentBounds.isEmpty() || !m_persistentPoints.isEmpty() || !m_points.isEmpty();
31void QSSGDebugDrawSystem::drawLine(
const QVector3D &startPoint,
32 const QVector3D &endPoint,
36 LineData line = {startPoint, endPoint, color};
38 m_persistentLines.append(line);
43void QSSGDebugDrawSystem::drawBounds(
const QSSGBounds3 &bounds,
47 BoundsData bound = {bounds, color};
49 m_persistentBounds.append(bound);
51 m_bounds.append(bound);
54void QSSGDebugDrawSystem::drawPoint(
const QVector3D &vertex,
const QColor &color,
bool isPersistent)
56 VertexData point = {vertex, {color.redF(), color.greenF(), color.blueF()}};
58 m_persistentPoints.append(point);
60 m_points.append(point);
64void QSSGDebugDrawSystem::prepareGeometry(QSSGRhiContext *rhiCtx, QRhiResourceUpdateBatch *rub)
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;
80 if (!vertexData.isEmpty()) {
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)));
85 if (m_lineVertexBuffer)
86 m_lineVertexBuffer.reset();
87 if (m_lineIndexBuffer)
88 m_lineIndexBuffer.reset();
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());
98 m_lineIndexBuffer = std::make_shared<QSSGRhiBuffer>(*rhiCtx,
99 QRhiBuffer::Immutable,
100 QRhiBuffer::IndexBuffer,
102 indexBufferData.size(),
103 QRhiCommandBuffer::IndexUInt32);
104 m_lineIndexBuffer->buffer()->setName(QByteArrayLiteral(
"debug lines index buffer"));
105 rub->uploadStaticBuffer(m_lineIndexBuffer->buffer(), indexBufferData.constData());
107 m_indexSize = indexData.count();
110 if (!pointsData.isEmpty()) {
112 QByteArray vertexBufferData(
reinterpret_cast<
const char*>(pointsData.constData()), qsizetype(pointsData.count() * 6 *
sizeof(
float)));
114 if (m_pointVertexBuffer)
115 m_pointVertexBuffer.reset();
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();
128void QSSGDebugDrawSystem::recordRenderDebugObjects(QSSGRhiContext *rhiCtx,
129 QSSGRhiGraphicsPipelineState *ps,
130 QRhiShaderResourceBindings *srb,
131 QRhiRenderPassDescriptor *rpDesc)
133 auto &ia = QSSGRhiInputAssemblerStatePrivate::get(*ps);
134 ia.inputLayout.setAttributes({
135 { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
136 { 0, 1, QRhiVertexInputAttribute::Float3, 3 *
sizeof(
float) }
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;
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);
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);
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);
168 QRhiCommandBuffer::VertexInput vb(m_pointVertexBuffer->buffer(), 0);
169 cb->setVertexInput(0, 1, &vb);
170 cb->draw(m_pointsSize);
180void QSSGDebugDrawSystem::setEnabled(
bool v)
182 modes = v ? (modes | ModeFlagT(Mode::Other)) : (modes & ~ModeFlagT(Mode::Other));
185void QSSGDebugDrawSystem::generateLine(
const LineData &line, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
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});
194void QSSGDebugDrawSystem::generateBox(
const BoundsData &bounds, QVector<VertexData> &vertexArray, QVector<quint32> &indexArray)
196 const QVector3D color = {bounds.color.redF(), bounds.color.greenF(), bounds.color.blueF()};
198 quint32 offset = vertexArray.count();
199 for (
const QVector3D point : bounds.bounds.toQSSGBoxPoints())
200 vertexArray.append({point, color});
202 indexArray.append(offset + 0);
203 indexArray.append(offset + 3);
205 indexArray.append(offset + 3);
206 indexArray.append(offset + 6);
208 indexArray.append(offset + 6);
209 indexArray.append(offset + 1);
211 indexArray.append(offset + 1);
212 indexArray.append(offset + 0);
214 indexArray.append(offset + 2);
215 indexArray.append(offset + 5);
217 indexArray.append(offset + 5);
218 indexArray.append(offset + 4);
220 indexArray.append(offset + 4);
221 indexArray.append(offset + 7);
223 indexArray.append(offset + 7);
224 indexArray.append(offset + 2);
226 indexArray.append(offset + 0);
227 indexArray.append(offset + 2);
229 indexArray.append(offset + 3);
230 indexArray.append(offset + 5);
232 indexArray.append(offset + 6);
233 indexArray.append(offset + 4);
235 indexArray.append(offset + 1);
236 indexArray.append(offset + 7);
240QColor QSSGDebugDrawSystem::levelOfDetailColor(quint32 lod)
242 static const QColor colors[] {
251 QColor(Qt::darkGreen),
252 QColor(Qt::darkBlue),
253 QColor(Qt::darkCyan),
254 QColor(Qt::darkMagenta),
255 QColor(Qt::darkYellow),
259 const size_t idx = qBound<size_t>(0, lod, std::size(colors) - 1);
263void QSSGDebugDrawSystem::debugNormals(QSSGBufferManager &bufferManager,
const QSSGModelContext &theModelContext,
const QSSGRenderSubset &theSubset, quint32 subsetLevelOfDetail,
float lineLength)
265 const auto &model = theModelContext.model;
269 mesh = bufferManager.loadMeshData(model.geometry);
271 mesh = bufferManager.loadMeshData(model.meshPath);
276 QByteArray vertexData = mesh.vertexBuffer().data;
277 if (vertexData.isEmpty())
279 quint32 vertexStride = mesh.vertexBuffer().stride;
280 QByteArray indexData = mesh.indexBuffer().data;
281 if (indexData.isEmpty())
283 if (mesh.indexBuffer().componentType != QSSGMesh::Mesh::ComponentType::UnsignedInt32)
286 quint32 positionOffset = UINT_MAX;
287 quint32 normalOffset = UINT_MAX;
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)
295 }
else if (vbe.name == QSSGMesh::MeshInternal::getNormalAttrName()) {
296 normalOffset = vbe.offset;
297 if (vbe.componentType != QSSGMesh::Mesh::ComponentType::Float32 &&
298 vbe.componentCount != 3)
303 const auto &globalTransform = theModelContext.globalTransform;
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));
326 if (subsetLevelOfDetail != 0) {
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));
Combined button and popup list for selecting options.