diff options
author | Jonas Karlsson <jonas.karlsson@qt.io> | 2024-01-09 12:32:17 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-01-22 13:55:18 +0000 |
commit | 3a96b26e24135a99fabfc3c124fb578c5a554d94 (patch) | |
tree | d61e5b17c2d85222ae7abed9f9326854678cf4cf | |
parent | a8d7d34581b873810f5cffe9834f116238209385 (diff) |
Fix TriangleMeshShape geometry cooking
The triangle mesh description needs to take the indices of the triangle
into account if present, as well as use the correct offsets and strides.
This is in contrast to the convex mesh that only needs to take the
points into account since it just creates a convex hull of them.
Fixes: QTBUG-120569
Change-Id: Icb31f1eb78f9deb60382922fd8f54be477acd200
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
(cherry picked from commit b8c5361782809a778900dbce11ad7190adb277e4)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/quick3dphysics/qmeshshape.cpp | 66 | ||||
-rw-r--r-- | tests/auto/geometry/tst_geometry.qml | 60 |
2 files changed, 112 insertions, 14 deletions
diff --git a/src/quick3dphysics/qmeshshape.cpp b/src/quick3dphysics/qmeshshape.cpp index 6ee5f4e..92c53a0 100644 --- a/src/quick3dphysics/qmeshshape.cpp +++ b/src/quick3dphysics/qmeshshape.cpp @@ -24,6 +24,20 @@ QT_BEGIN_NAMESPACE +static QQuick3DGeometry::Attribute +attributeBySemantic(const QQuick3DGeometry *geometry, + QQuick3DGeometry::Attribute::Semantic semantic) +{ + for (int i = 0; i < geometry->attributeCount(); i++) { + const auto attr = geometry->attribute(i); + if (attr.semantic == semantic) + return attr; + } + + Q_UNREACHABLE(); + return QQuick3DGeometry::Attribute(); +}; + physx::PxConvexMesh *QQuick3DPhysicsMesh::convexMesh() { if (m_convexMesh != nullptr) @@ -213,17 +227,53 @@ physx::PxTriangleMesh *QQuick3DPhysicsMesh::triangleMeshQmlSource() physx::PxTriangleMesh *QQuick3DPhysicsMesh::triangleMeshGeometrySource() { - physx::PxDefaultMemoryOutputStream buf; - physx::PxTriangleMeshCookingResult::Enum result; - int vStride = m_meshGeometry->stride(); - const auto vertexData = m_meshGeometry->vertexData(); - int vCount = vertexData.size() / vStride; + auto vertexBuffer = m_meshGeometry->vertexData(); + + if (m_meshGeometry->primitiveType() != QQuick3DGeometry::PrimitiveType::Triangles) { + qWarning() << "QQuick3DPhysicsMesh: Invalid geometry primitive type, must be Triangles. "; + return nullptr; + } + + if (!vertexBuffer.size()) { + qWarning() << "QQuick3DPhysicsMesh: Invalid geometry, vertexData is empty. "; + return nullptr; + } + + const auto vertexAttribute = + attributeBySemantic(m_meshGeometry, QQuick3DGeometry::Attribute::PositionSemantic); + Q_ASSERT(vertexAttribute.componentType == QQuick3DGeometry::Attribute::F32Type); + + const int posOffset = vertexAttribute.offset; + const auto stride = m_meshGeometry->stride(); + const auto numVertices = vertexBuffer.size() / stride; physx::PxTriangleMeshDesc triangleDesc; - triangleDesc.points.count = vCount; - triangleDesc.points.stride = sizeof(physx::PxVec3); - triangleDesc.points.data = vertexData.constData(); + triangleDesc.points.count = numVertices; + triangleDesc.points.stride = stride; + triangleDesc.points.data = vertexBuffer.constData() + posOffset; + + auto indexBuffer = m_meshGeometry->indexData(); + if (indexBuffer.size()) { + const auto indexAttribute = + attributeBySemantic(m_meshGeometry, QQuick3DGeometry::Attribute::IndexSemantic); + const bool u16IndexType = + indexAttribute.componentType == QQuick3DGeometry::Attribute::U16Type; + + Q_ASSERT(indexAttribute.componentType == QQuick3DGeometry::Attribute::U16Type + || indexAttribute.componentType == QQuick3DGeometry::Attribute::U32Type); + + triangleDesc.triangles.data = indexBuffer.constData(); + if (u16IndexType) { + triangleDesc.flags.set(physx::PxMeshFlag::e16_BIT_INDICES); + triangleDesc.triangles.stride = sizeof(quint16) * 3; + } else { + triangleDesc.triangles.stride = sizeof(quint32) * 3; + } + triangleDesc.triangles.count = indexBuffer.size() / triangleDesc.triangles.stride; + } + physx::PxDefaultMemoryOutputStream buf; + physx::PxTriangleMeshCookingResult::Enum result; const auto cooking = QPhysicsWorld::getCooking(); if (cooking && cooking->cookTriangleMesh(triangleDesc, buf, &result)) { auto size = buf.getSize(); diff --git a/tests/auto/geometry/tst_geometry.qml b/tests/auto/geometry/tst_geometry.qml index a28cbf5..9451dce 100644 --- a/tests/auto/geometry/tst_geometry.qml +++ b/tests/auto/geometry/tst_geometry.qml @@ -15,6 +15,7 @@ Item { PhysicsWorld { scene: viewport.scene + forceDebugDraw: true } View3D { @@ -27,7 +28,7 @@ Item { } PerspectiveCamera { - position: Qt.vector3d(-200, 100, 500) + position: Qt.vector3d(-200, 300, 500) eulerRotation: Qt.vector3d(-20, -20, 0) clipFar: 5000 clipNear: 1 @@ -63,9 +64,9 @@ Item { dynamicBox.hit = true } receiveContactReports: true - sendContactReports: true + sendContactReports: false - position: Qt.vector3d(-50, 300, 0) + position: Qt.vector3d(-50, 400, 0) collisionShapes: ConvexMeshShape { geometry: ExampleTriangleGeometry { } } @@ -79,9 +80,50 @@ Item { StaticRigidBody { sendContactReports: true - position: Qt.vector3d(0, 50, 0) + position: Qt.vector3d(-175, 250, 0) collisionShapes: TriangleMeshShape { - geometry: ExampleTriangleGeometry { } + geometry: CapsuleGeometry { + enableNormals: true + enableUV: true + } + } + Model { + geometry: CapsuleGeometry { } + materials: PrincipledMaterial { + baseColor: "yellow" + } + } + } + + DynamicRigidBody { + id: dynamicCapsule + property bool hit : false + onBodyContact: () => { + dynamicCapsule.hit = true + } + receiveContactReports: true + sendContactReports: false + + position: Qt.vector3d(175, 400, 0) + collisionShapes: ConvexMeshShape { + geometry: CapsuleGeometry { + enableNormals: true + enableUV: true + } + } + Model { + geometry: CapsuleGeometry { } + materials: PrincipledMaterial { + baseColor: "yellow" + } + } + } + + StaticRigidBody { + sendContactReports: true + position: Qt.vector3d(275, 250, 0) + collisionShapes: TriangleMeshShape { + geometry: ExampleTriangleGeometry {} } Model { geometry: ExampleTriangleGeometry { } @@ -93,8 +135,14 @@ Item { } TestCase { - name: "scene" + name: "box hit" when: dynamicBox.hit function triggered() { } } + + TestCase { + name: "capsule hit" + when: dynamicCapsule.hit + function triggered() { } + } } |