19 auto boxGeometry =
new QQuick3DGeometry();
21 boxGeometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
22 QQuick3DGeometry::Attribute::ComponentType::F32Type);
23 boxGeometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
24 QQuick3DGeometry::Attribute::ComponentType::F32Type);
25 boxGeometry->setStride(32);
26 boxGeometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
27 boxGeometry->setBounds(-halfExtents, halfExtents);
29 const float x = halfExtents.x();
30 const float y = halfExtents.y();
31 const float z = halfExtents.z();
33 QCollisionDebugMeshBuilder builder;
35 builder.addLine(QVector3D(-x, -y, z), QVector3D(-x, y, z));
36 builder.addLine(QVector3D(-x, y, z), QVector3D(x, y, z));
37 builder.addLine(QVector3D(x, y, z), QVector3D(x, -y, z));
38 builder.addLine(QVector3D(x, -y, z), QVector3D(-x, -y, z));
41 builder.addLine(QVector3D(-x, -y, -z), QVector3D(-x, y, -z));
42 builder.addLine(QVector3D(-x, y, -z), QVector3D(x, y, -z));
43 builder.addLine(QVector3D(x, y, -z), QVector3D(x, -y, -z));
44 builder.addLine(QVector3D(x, -y, -z), QVector3D(-x, -y, -z));
47 builder.addLine(QVector3D(x, -y, z), QVector3D(x, -y, -z));
48 builder.addLine(QVector3D(-x, -y, -z), QVector3D(-x, -y, z));
51 builder.addLine(QVector3D(x, y, z), QVector3D(x, y, -z));
52 builder.addLine(QVector3D(-x, y, -z), QVector3D(-x, y, z));
54 boxGeometry->setVertexData(builder.generateVertexArray());
61 auto sphereGeometry =
new QQuick3DGeometry();
62 sphereGeometry->clear();
63 sphereGeometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
64 QQuick3DGeometry::Attribute::ComponentType::F32Type);
65 sphereGeometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
66 QQuick3DGeometry::Attribute::ComponentType::F32Type);
67 sphereGeometry->setStride(32);
68 sphereGeometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
69 sphereGeometry->setBounds(QVector3D(-radius, -radius, -radius),
70 QVector3D(radius, radius, radius));
74 const int circleSegments = 24;
75 constexpr double TAU = 2 * M_PI;
76 const float step =
float(TAU / circleSegments);
77 QVector<QVector2D> circlePoints;
78 for (
float theta = 0; theta < TAU; theta += step) {
79 const float x = radius * qCos(theta);
80 const float y = radius * qSin(theta);
81 circlePoints.append(QVector2D(x, y));
84 QCollisionDebugMeshBuilder builder;
86 for (
int i = 0; i < circlePoints.count(); ++i) {
87 const auto refPoint1 = circlePoints[i];
89 if (index2 == circlePoints.count())
91 const auto refPoint2 = circlePoints[index2];
92 const auto vertex1 =
QVector3D(0.0f, refPoint1.x(), refPoint1.y());
93 const auto vertex2 =
QVector3D(0.0f, refPoint2.x(), refPoint2.y());
94 builder.addLine(vertex1, vertex2, QVector3D(1, 0, 0));
98 for (
int i = 0; i < circlePoints.count(); ++i) {
99 const auto refPoint1 = circlePoints[i];
101 if (index2 == circlePoints.count())
103 const auto refPoint2 = circlePoints[index2];
104 const auto vertex1 =
QVector3D(refPoint1.x(), 0.0f, refPoint1.y());
105 const auto vertex2 =
QVector3D(refPoint2.x(), 0.0f, refPoint2.y());
106 builder.addLine(vertex1, vertex2, QVector3D(0, 1, 0));
110 for (
int i = 0; i < circlePoints.count(); ++i) {
111 const auto refPoint1 = circlePoints[i];
113 if (index2 == circlePoints.count())
115 const auto refPoint2 = circlePoints[index2];
116 const auto vertex1 =
QVector3D(refPoint1.x(), refPoint1.y(), 0.0f);
117 const auto vertex2 =
QVector3D(refPoint2.x(), refPoint2.y(), 0.0f);
118 builder.addLine(vertex1, vertex2, QVector3D(0, 0, 1));
120 sphereGeometry->setVertexData(builder.generateVertexArray());
122 return sphereGeometry;
126 const float halfHeight)
128 auto capsuleGeometry =
new QQuick3DGeometry();
129 capsuleGeometry->clear();
130 capsuleGeometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
131 QQuick3DGeometry::Attribute::ComponentType::F32Type);
132 capsuleGeometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
133 QQuick3DGeometry::Attribute::ComponentType::F32Type);
134 capsuleGeometry->setStride(32);
135 capsuleGeometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
136 capsuleGeometry->setBounds(QVector3D(-(halfHeight + radius), -radius, -radius),
137 QVector3D(halfHeight + radius, radius, radius));
143 const int circleSegments = 32;
144 constexpr double TAU = 2 * M_PI;
146 Q_ASSERT(circleSegments % 4 == 0);
147 const float step =
float(TAU / circleSegments);
148 QVector<QVector2D> circlePoints;
149 for (
float theta = 0; theta < TAU; theta += step) {
150 const float x = radius * qCos(theta);
151 const float y = radius * qSin(theta);
152 circlePoints.append(QVector2D(x, y));
155 QCollisionDebugMeshBuilder builder;
158 for (
int i = 0; i < circlePoints.count(); ++i) {
159 const auto refPoint1 = circlePoints[i];
161 if (index2 == circlePoints.count())
163 const auto refPoint2 = circlePoints[index2];
164 const auto vertex1 =
QVector3D(halfHeight, refPoint1.x(), refPoint1.y());
165 const auto vertex2 =
QVector3D(halfHeight, refPoint2.x(), refPoint2.y());
166 const auto normal = QVector3D(1, 0, 0);
167 builder.addLine(vertex1, vertex2, normal);
171 for (
int i = 0; i < circlePoints.count(); ++i) {
172 const auto refPoint1 = circlePoints[i];
174 if (index2 == circlePoints.count())
176 const auto refPoint2 = circlePoints[index2];
177 const auto vertex1 =
QVector3D(-halfHeight, refPoint1.x(), refPoint1.y());
178 const auto vertex2 =
QVector3D(-halfHeight, refPoint2.x(), refPoint2.y());
179 const auto normal = QVector3D(1, 0, 0);
180 builder.addLine(vertex1, vertex2, normal);
185 const auto vertex1 = QVector3D(halfHeight, 0, radius);
186 const auto vertex2 = QVector3D(-halfHeight, 0, radius);
187 const auto normal = QVector3D(0, 0, 1);
188 builder.addLine(vertex1, vertex2, normal);
193 const auto vertex1 = QVector3D(halfHeight, 0, -radius);
194 const auto vertex2 = QVector3D(-halfHeight, 0, -radius);
195 const auto normal = QVector3D(0, 0, -1);
196 builder.addLine(vertex1, vertex2, normal);
201 const auto vertex1 = QVector3D(halfHeight, -radius, 0);
202 const auto vertex2 = QVector3D(-halfHeight, -radius, 0);
203 const auto normal = QVector3D(0, -1, 0);
204 builder.addLine(vertex1, vertex2, normal);
209 const auto vertex1 = QVector3D(halfHeight, radius, 0);
210 const auto vertex2 = QVector3D(-halfHeight, radius, 0);
211 const auto normal = QVector3D(0, 1, 0);
212 builder.addLine(vertex1, vertex2, normal);
216 QVector<
int> topIndexes;
217 QVector<
int> bottomIndexes;
219 const int half = circlePoints.count() / 2;
220 for (
int i = 0; i < half + 1; ++i)
221 topIndexes.append(i);
223 for (
int i = half; i <= circlePoints.count(); ++i) {
225 if (i >= circlePoints.count())
226 index = index - circlePoints.count();
227 bottomIndexes.append(index);
232 for (
int i = 0; i < topIndexes.count(); ++i) {
233 const auto refPoint1 = circlePoints[topIndexes[i]];
235 if (index2 == topIndexes.count())
237 const auto refPoint2 = circlePoints[topIndexes[index2]];
238 const auto vertex1 =
QVector3D(refPoint1.y() + halfHeight, refPoint1.x(), 0.0f);
239 const auto vertex2 =
QVector3D(refPoint2.y() + halfHeight, refPoint2.x(), 0.0f);
240 const auto normal = QVector3D(0, 0, 1);
241 builder.addLine(vertex1, vertex2, normal);
245 for (
int i = 0; i < bottomIndexes.count(); ++i) {
246 const auto refPoint1 = circlePoints[bottomIndexes[i]];
248 if (index2 == bottomIndexes.count())
250 const auto refPoint2 = circlePoints[bottomIndexes[index2]];
251 const auto vertex1 =
QVector3D(refPoint1.y() - halfHeight, refPoint1.x(), 0.0f);
252 const auto vertex2 =
QVector3D(refPoint2.y() - halfHeight, refPoint2.x(), 0.0f);
253 const auto normal = QVector3D(0, 0, 1);
254 builder.addLine(vertex1, vertex2, normal);
258 for (
int i = 0; i < topIndexes.count(); ++i) {
259 const auto refPoint1 = circlePoints[topIndexes[i]];
261 if (index2 == topIndexes.count())
263 const auto refPoint2 = circlePoints[topIndexes[index2]];
264 const auto vertex1 =
QVector3D(refPoint1.y() + halfHeight, 0.0f, refPoint1.x());
265 const auto vertex2 =
QVector3D(refPoint2.y() + halfHeight, 0.0f, refPoint2.x());
266 const auto normal = QVector3D(0, 1, 0);
267 builder.addLine(vertex1, vertex2, normal);
271 for (
int i = 0; i < bottomIndexes.count(); ++i) {
272 const auto refPoint1 = circlePoints[bottomIndexes[i]];
274 if (index2 == bottomIndexes.count())
276 const auto refPoint2 = circlePoints[bottomIndexes[index2]];
277 const auto vertex1 =
QVector3D(refPoint1.y() - halfHeight, 0.0f, refPoint1.x());
278 const auto vertex2 =
QVector3D(refPoint2.y() - halfHeight, 0.0f, refPoint2.x());
279 const auto normal = QVector3D(0, 1, 0);
280 builder.addLine(vertex1, vertex2, normal);
283 capsuleGeometry->setVertexData(builder.generateVertexArray());
284 return capsuleGeometry;
289 auto planeGeometry =
new QQuick3DGeometry();
290 planeGeometry->clear();
291 planeGeometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
292 QQuick3DGeometry::Attribute::ComponentType::F32Type);
293 planeGeometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
294 QQuick3DGeometry::Attribute::ComponentType::F32Type);
295 planeGeometry->setStride(32);
296 planeGeometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
301 planeGeometry->setBounds({ -s, -s, -h }, { s, s, h });
302 QCollisionDebugMeshBuilder builder;
304 builder.addLine({ -s, -s, 0 }, { s, -s, 0 });
305 builder.addLine({ -s, -s, 0 }, { 0, 0, 0 });
307 builder.addLine({ s, -s, 0 }, { s, s, 0 });
308 builder.addLine({ s, -s, 0 }, { 0, 0, 0 });
310 builder.addLine({ s, s, 0 }, { -s, s, 0 });
311 builder.addLine({ s, s, 0 }, { 0, 0, 0 });
313 builder.addLine({ -s, s, 0 }, { -s, -s, 0 });
314 builder.addLine({ -s, s, 0 }, { 0, 0, 0 });
316 planeGeometry->setVertexData(builder.generateVertexArray());
317 return planeGeometry;
321 float heightScale,
float rowScale,
324 if (!heightField || heightField->getNbRows() < 2 || heightField->getNbColumns() < 2)
327 auto geometry =
new QQuick3DGeometry();
329 geometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
330 QQuick3DGeometry::Attribute::ComponentType::F32Type);
331 geometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
332 QQuick3DGeometry::Attribute::ComponentType::F32Type);
333 geometry->setStride(32);
334 geometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
336 QCollisionDebugMeshBuilder builder;
338 const int numRows = heightField->getNbRows();
339 const int numCols = heightField->getNbColumns();
341 const float sizeX = rowScale * (numRows - 1);
342 const float sizeZ = columnScale * (numCols - 1);
344 const float heightF = heightScale;
346 float minHeight = 0.f;
347 float maxHeight = 0.f;
349 auto sample = [&](
int row,
int col) ->
QVector3D {
350 const float height = heightField->getSample(row, col).height * heightF;
351 maxHeight = qMax(maxHeight, height);
352 minHeight = qMin(minHeight, height);
353 return QVector3D(row * rowScale, height, col * columnScale);
356 for (
int row = 0; row < numRows; row++) {
357 for (
int col = 0; col < numCols; col++) {
358 if (row < numRows - 1)
359 builder.addLine(sample(row, col), sample(row + 1, col));
360 if (col < numCols - 1)
361 builder.addLine(sample(row, col), sample(row, col + 1));
365 geometry->setBounds(QVector3D(0, minHeight, 0), QVector3D(sizeX, maxHeight, sizeZ));
366 geometry->setVertexData(builder.generateVertexArray());
375 auto geometry =
new QQuick3DGeometry();
377 geometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
378 QQuick3DGeometry::Attribute::ComponentType::F32Type);
379 geometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
380 QQuick3DGeometry::Attribute::ComponentType::F32Type);
381 geometry->setStride(32);
382 geometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
384 QCollisionDebugMeshBuilder builder;
386 const physx::PxU32 nbPolys = convexMesh->getNbPolygons();
387 const physx::PxU8 *polygons = convexMesh->getIndexBuffer();
388 const physx::PxVec3 *verts = convexMesh->getVertices();
389 const physx::PxU32 nbVerts = convexMesh->getNbVertices();
391 physx::PxHullPolygon data;
392 for (physx::PxU32 i = 0; i < nbPolys; i++) {
393 convexMesh->getPolygonData(i, data);
395 Q_ASSERT(data.mNbVerts > 2);
396 const physx::PxU32 nbTris = physx::PxU32(data.mNbVerts - 2);
397 const physx::PxU8 vref0 = polygons[data.mIndexBase + 0];
398 Q_ASSERT(vref0 < nbVerts);
400 for (physx::PxU32 j = 0; j < nbTris; j++) {
401 const physx::PxU32 vref1 = polygons[data.mIndexBase + 0 + j + 1];
402 const physx::PxU32 vref2 = polygons[data.mIndexBase + 0 + j + 2];
403 Q_ASSERT(vref1 < nbVerts);
404 Q_ASSERT(vref2 < nbVerts);
406 const QVector3D p0 = QPhysicsUtils::toQtType(verts[vref0]);
407 const QVector3D p1 = QPhysicsUtils::toQtType(verts[vref1]);
408 const QVector3D p2 = QPhysicsUtils::toQtType(verts[vref2]);
410 builder.addLine(p0, p1);
411 builder.addLine(p1, p2);
412 builder.addLine(p2, p0);
416 auto bounds = convexMesh->getLocalBounds();
418 geometry->setBounds(QPhysicsUtils::toQtType(bounds.minimum),
419 QPhysicsUtils::toQtType(bounds.maximum));
420 geometry->setVertexData(builder.generateVertexArray());
430 auto geometry =
new QQuick3DGeometry();
432 geometry->addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0,
433 QQuick3DGeometry::Attribute::ComponentType::F32Type);
434 geometry->addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 16,
435 QQuick3DGeometry::Attribute::ComponentType::F32Type);
436 geometry->setStride(32);
437 geometry->setPrimitiveType(QQuick3DGeometry::PrimitiveType::Lines);
439 QCollisionDebugMeshBuilder builder;
441 const physx::PxU32 triangleCount = triangleMesh->getNbTriangles();
442 const physx::PxU32 has16BitIndices =
443 triangleMesh->getTriangleMeshFlags() & physx::PxTriangleMeshFlag::e16_BIT_INDICES;
444 const void *indexBuffer = triangleMesh->getTriangles();
445 const physx::PxVec3 *vertexBuffer = triangleMesh->getVertices();
446 const physx::PxU32 *intIndices =
reinterpret_cast<
const physx::PxU32 *>(indexBuffer);
447 const physx::PxU16 *shortIndices =
reinterpret_cast<
const physx::PxU16 *>(indexBuffer);
448 for (physx::PxU32 i = 0; i < triangleCount; ++i) {
449 physx::PxVec3 triVert[3];
451 if (has16BitIndices) {
452 triVert[0] = vertexBuffer[*shortIndices++];
453 triVert[1] = vertexBuffer[*shortIndices++];
454 triVert[2] = vertexBuffer[*shortIndices++];
456 triVert[0] = vertexBuffer[*intIndices++];
457 triVert[1] = vertexBuffer[*intIndices++];
458 triVert[2] = vertexBuffer[*intIndices++];
461 const QVector3D p0 = QPhysicsUtils::toQtType(triVert[0]);
462 const QVector3D p1 = QPhysicsUtils::toQtType(triVert[1]);
463 const QVector3D p2 = QPhysicsUtils::toQtType(triVert[2]);
465 builder.addLine(p0, p1);
466 builder.addLine(p1, p2);
467 builder.addLine(p2, p0);
470 auto bounds = triangleMesh->getLocalBounds();
472 geometry->setBounds(QPhysicsUtils::toQtType(bounds.minimum),
473 QPhysicsUtils::toQtType(bounds.maximum));
474 geometry->setVertexData(builder.generateVertexArray());