aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Karlsson <jonas.karlsson@qt.io>2024-01-09 12:32:17 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-01-22 13:55:18 +0000
commit3a96b26e24135a99fabfc3c124fb578c5a554d94 (patch)
treed61e5b17c2d85222ae7abed9f9326854678cf4cf
parenta8d7d34581b873810f5cffe9834f116238209385 (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.cpp66
-rw-r--r--tests/auto/geometry/tst_geometry.qml60
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() { }
+ }
}