aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Karlsson <jonas.karlsson@qt.io>2023-11-28 14:27:00 +0100
committerJonas Karlsson <jonas.karlsson@qt.io>2023-12-06 16:18:03 +0100
commitf43d8bf1aed47da1ae13d73d59e439ce6ef53348 (patch)
treea2b5c5b1fc15c311c6aa8fbfb2f81d4b92d9025d
parent3012a8a2b9c6bc5315f3a597300b5d447840c6a5 (diff)
Move almost identical code into QMeshShape
QTriangleMeshShape and QConvexMeshShape are basically identical so move the common code into a new class QMeshShape. Using an enum ShapeType to differentiate the mesh types. Pick-to: 6.6 6.5 Task-number: QTBUG-109818 Change-Id: Ia2e72eb84d14bcf1a38fa0d2df046805d175a5ad Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/quick3dphysics/CMakeLists.txt1
-rw-r--r--src/quick3dphysics/qconvexmeshshape.cpp292
-rw-r--r--src/quick3dphysics/qconvexmeshshape_p.h39
-rw-r--r--src/quick3dphysics/qmeshshape.cpp310
-rw-r--r--src/quick3dphysics/qmeshshape_p.h69
-rw-r--r--src/quick3dphysics/qtrianglemeshshape.cpp66
-rw-r--r--src/quick3dphysics/qtrianglemeshshape_p.h40
7 files changed, 394 insertions, 423 deletions
diff --git a/src/quick3dphysics/CMakeLists.txt b/src/quick3dphysics/CMakeLists.txt
index 350a4bd..541f636 100644
--- a/src/quick3dphysics/CMakeLists.txt
+++ b/src/quick3dphysics/CMakeLists.txt
@@ -34,6 +34,7 @@ qt_internal_add_qml_module(Quick3DPhysics
qdebugdrawhelper.cpp qdebugdrawhelper_p.h
qdynamicrigidbody.cpp qdynamicrigidbody_p.h
qheightfieldshape.cpp qheightfieldshape_p.h
+ qmeshshape.cpp qmeshshape_p.h
qphysicscommands.cpp qphysicscommands_p.h
qphysicsmaterial.cpp qphysicsmaterial_p.h
qphysicsmeshutils_p_p.h
diff --git a/src/quick3dphysics/qconvexmeshshape.cpp b/src/quick3dphysics/qconvexmeshshape.cpp
index a8a420e..cddeef9 100644
--- a/src/quick3dphysics/qconvexmeshshape.cpp
+++ b/src/quick3dphysics/qconvexmeshshape.cpp
@@ -1,248 +1,10 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-#include "qcacheutils_p.h"
#include "qconvexmeshshape_p.h"
-#include <QFile>
-#include <QFileInfo>
-#include <QtQuick3D/QQuick3DGeometry>
-#include <extensions/PxExtensionsAPI.h>
-
-#include "foundation/PxVec3.h"
-#include "cooking/PxConvexMeshDesc.h"
-#include "extensions/PxDefaultStreams.h"
-
-#include <QtQml/qqml.h>
-#include <QtQml/QQmlFile>
-#include <QtQml/qqmlcontext.h>
-
-#include <QtQuick3DUtils/private/qssgmesh_p.h>
-#include "qphysicsworld_p.h"
-#include "qphysicsmeshutils_p_p.h"
-#include "qphysicsutils_p.h"
-
QT_BEGIN_NAMESPACE
-physx::PxConvexMesh *QQuick3DPhysicsMesh::convexMesh()
-{
- if (m_convexMesh != nullptr)
- return m_convexMesh;
-
- physx::PxPhysics *thePhysics = QPhysicsWorld::getPhysics();
- if (thePhysics == nullptr)
- return nullptr;
-
- m_convexMesh = QCacheUtils::readCachedConvexMesh(m_meshPath, *thePhysics);
- if (m_convexMesh != nullptr)
- return m_convexMesh;
-
- m_convexMesh = QCacheUtils::readCookedConvexMesh(m_meshPath, *thePhysics);
- if (m_convexMesh != nullptr)
- return m_convexMesh;
-
- loadSsgMesh();
-
- if (!m_ssgMesh.isValid())
- return nullptr;
-
- physx::PxDefaultMemoryOutputStream buf;
- physx::PxConvexMeshCookingResult::Enum result;
- int vStride = m_ssgMesh.vertexBuffer().stride;
- int vCount = m_ssgMesh.vertexBuffer().data.size() / vStride;
- const auto *vd = m_ssgMesh.vertexBuffer().data.constData();
-
- qCDebug(lcQuick3dPhysics) << "prepare cooking" << vCount << "verts";
-
- QVector<physx::PxVec3> verts;
-
- for (int i = 0; i < vCount; ++i) {
- auto *vp = reinterpret_cast<const QVector3D *>(vd + vStride * i + m_posOffset);
- verts << physx::PxVec3 { vp->x(), vp->y(), vp->z() };
- }
-
- const auto *convexVerts = verts.constData();
-
- physx::PxConvexMeshDesc convexDesc;
- convexDesc.points.count = vCount;
- convexDesc.points.stride = sizeof(physx::PxVec3);
- convexDesc.points.data = convexVerts;
- convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
-
- const auto cooking = QPhysicsWorld::getCooking();
- if (cooking && cooking->cookConvexMesh(convexDesc, buf, &result)) {
- auto size = buf.getSize();
- auto *data = buf.getData();
- physx::PxDefaultMemoryInputData input(data, size);
- m_convexMesh = thePhysics->createConvexMesh(input);
- qCDebug(lcQuick3dPhysics) << "Created convex mesh" << m_convexMesh << "for mesh" << this;
- QCacheUtils::writeCachedConvexMesh(m_meshPath, buf);
- } else {
- qCWarning(lcQuick3dPhysics) << "Could not create convex mesh from" << m_meshPath;
- }
-
- return m_convexMesh;
-}
-
-physx::PxTriangleMesh *QQuick3DPhysicsMesh::triangleMesh()
-{
-
- if (m_triangleMesh != nullptr)
- return m_triangleMesh;
-
- physx::PxPhysics *thePhysics = QPhysicsWorld::getPhysics();
- if (thePhysics == nullptr)
- return nullptr;
-
- m_triangleMesh = QCacheUtils::readCachedTriangleMesh(m_meshPath, *thePhysics);
- if (m_triangleMesh != nullptr)
- return m_triangleMesh;
-
- m_triangleMesh = QCacheUtils::readCookedTriangleMesh(m_meshPath, *thePhysics);
- if (m_triangleMesh != nullptr)
- return m_triangleMesh;
-
- loadSsgMesh();
- if (!m_ssgMesh.isValid())
- return nullptr;
-
- physx::PxDefaultMemoryOutputStream buf;
- physx::PxTriangleMeshCookingResult::Enum result;
- const int vStride = m_ssgMesh.vertexBuffer().stride;
- const int vCount = m_ssgMesh.vertexBuffer().data.size() / vStride;
- const auto *vd = m_ssgMesh.vertexBuffer().data.constData();
-
- const int iStride =
- m_ssgMesh.indexBuffer().componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16
- ? 2
- : 4;
- const int iCount = m_ssgMesh.indexBuffer().data.size() / iStride;
-
- qCDebug(lcQuick3dPhysics) << "prepare cooking" << vCount << "verts" << iCount << "idxs";
-
- physx::PxTriangleMeshDesc triangleDesc;
- triangleDesc.points.count = vCount;
- triangleDesc.points.stride = vStride;
- triangleDesc.points.data = vd + m_posOffset;
-
- triangleDesc.flags = {}; //??? physx::PxMeshFlag::eFLIPNORMALS or
- // physx::PxMeshFlag::e16_BIT_INDICES
- triangleDesc.triangles.count = iCount / 3;
- triangleDesc.triangles.stride = iStride * 3;
- triangleDesc.triangles.data = m_ssgMesh.indexBuffer().data.constData();
-
- const auto cooking = QPhysicsWorld::getCooking();
- if (cooking && cooking->cookTriangleMesh(triangleDesc, buf, &result)) {
- auto size = buf.getSize();
- auto *data = buf.getData();
- physx::PxDefaultMemoryInputData input(data, size);
- m_triangleMesh = thePhysics->createTriangleMesh(input);
- qCDebug(lcQuick3dPhysics) << "Created triangle mesh" << m_triangleMesh << "for mesh"
- << this;
- QCacheUtils::writeCachedTriangleMesh(m_meshPath, buf);
- } else {
- qCWarning(lcQuick3dPhysics) << "Could not create triangle mesh from" << m_meshPath;
- }
-
- return m_triangleMesh;
-}
-
-void QQuick3DPhysicsMesh::loadSsgMesh()
-{
- if (m_ssgMesh.isValid())
- return;
-
- static const char *compTypes[] = { "Null", "UnsignedInt8", "Int8", "UnsignedInt16",
- "Int16", "UnsignedInt32", "Int32", "UnsignedInt64",
- "Int64", "Float16", "Float32", "Float64" };
-
- QFileInfo fileInfo = QFileInfo(m_meshPath);
- if (fileInfo.exists()) {
- QFile file(fileInfo.absoluteFilePath());
- if (file.open(QFile::ReadOnly))
- m_ssgMesh = QSSGMesh::Mesh::loadMesh(&file);
- }
- qCDebug(lcQuick3dPhysics) << "Loaded SSG mesh from" << m_meshPath << m_ssgMesh.isValid()
- << "draw" << int(m_ssgMesh.drawMode()) << "wind"
- << int(m_ssgMesh.winding()) << "subs" << m_ssgMesh.subsets().count()
- << "attrs" << m_ssgMesh.vertexBuffer().entries.count()
- << m_ssgMesh.vertexBuffer().data.size() << "stride"
- << m_ssgMesh.vertexBuffer().stride << "verts"
- << m_ssgMesh.vertexBuffer().data.size()
- / m_ssgMesh.vertexBuffer().stride;
-
- for (auto &v : m_ssgMesh.vertexBuffer().entries) {
- qCDebug(lcQuick3dPhysics) << " attr" << v.name << compTypes[int(v.componentType)] << "cc"
- << v.componentCount << "offs" << v.offset;
- Q_ASSERT(v.componentType == QSSGMesh::Mesh::ComponentType::Float32);
- if (v.name == "attr_pos")
- m_posOffset = v.offset;
- }
-
- if (m_ssgMesh.isValid()) {
- auto sub = m_ssgMesh.subsets().constFirst();
- qCDebug(lcQuick3dPhysics) << "..." << sub.name << "count" << sub.count << "bounds"
- << sub.bounds.min << sub.bounds.max << "offset" << sub.offset;
- }
-
-#if 0 // EXTRA_DEBUG
-
- int iStride = m_ssgMesh.indexBuffer().componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16 ? 2 : 4;
- int vStride = m_ssgMesh.vertexBuffer().stride;
- qDebug() << "IDX" << compTypes[int(m_ssgMesh.indexBuffer().componentType)] << m_ssgMesh.indexBuffer().data.size() / iStride;
- const auto ib = m_ssgMesh.indexBuffer().data;
- const auto vb = m_ssgMesh.vertexBuffer().data;
-
- auto getPoint = [&vb, vStride, this](int idx) -> QVector3D {
- auto *vp = vb.constData() + vStride * idx + m_posOffset;
- return *reinterpret_cast<const QVector3D *>(vp);
- return {};
- };
-
- if (iStride == 2) {
-
- } else {
- auto *ip = reinterpret_cast<const uint32_t *>(ib.data());
- int n = ib.size() / iStride;
- for (int i = 0; i < qMin(50,n); i += 3) {
-
- qDebug() << " " << ip [i] << ip[i+1] << ip[i+2] << " --- "
- << getPoint(ip[i]) << getPoint(ip[i+1]) << getPoint(ip[i+2]);
- }
- }
-#endif
- if (!m_ssgMesh.isValid())
- qCWarning(lcQuick3dPhysics) << "Could not read mesh from" << m_meshPath;
-}
-
-QQuick3DPhysicsMesh *QQuick3DPhysicsMeshManager::getMesh(const QUrl &source,
- const QObject *contextObject)
-{
- const QQmlContext *context = qmlContext(contextObject);
- const auto resolvedUrl = context ? context->resolvedUrl(source) : source;
- const auto qmlSource = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
- auto *mesh = meshHash.value(qmlSource);
- if (!mesh) {
- mesh = new QQuick3DPhysicsMesh(qmlSource);
- meshHash[qmlSource] = mesh;
- }
- mesh->ref();
- return mesh;
-}
-
-void QQuick3DPhysicsMeshManager::releaseMesh(QQuick3DPhysicsMesh *mesh)
-{
- if (mesh->deref() == 0) {
- qCDebug(lcQuick3dPhysics()) << "deleting mesh" << mesh;
- erase_if(meshHash, [mesh](std::pair<const QString &, QQuick3DPhysicsMesh *&> h) {
- return h.second == mesh;
- });
- delete mesh;
- }
-}
-
-QHash<QString, QQuick3DPhysicsMesh *> QQuick3DPhysicsMeshManager::meshHash;
-
/*!
\qmltype ConvexMeshShape
\inherits CollisionShape
@@ -268,57 +30,9 @@ QHash<QString, QQuick3DPhysicsMesh *> QQuick3DPhysicsMeshManager::meshHash;
for details.
*/
-QConvexMeshShape::QConvexMeshShape() = default;
-
-QConvexMeshShape::~QConvexMeshShape()
-{
- delete m_meshGeometry;
- if (m_mesh)
- QQuick3DPhysicsMeshManager::releaseMesh(m_mesh);
-}
-
-physx::PxGeometry *QConvexMeshShape::getPhysXGeometry()
-{
- if (m_dirtyPhysx || m_scaleDirty) {
- updatePhysXGeometry();
- }
- return m_meshGeometry;
-}
-
-void QConvexMeshShape::updatePhysXGeometry()
-{
- delete m_meshGeometry;
- m_meshGeometry = nullptr;
-
- auto *convexMesh = m_mesh->convexMesh();
- if (!convexMesh)
- return;
-
- auto meshScale = sceneScale();
- physx::PxMeshScale scale(physx::PxVec3(meshScale.x(), meshScale.y(), meshScale.z()),
- physx::PxQuat(physx::PxIdentity));
-
- m_meshGeometry = new physx::PxConvexMeshGeometry(convexMesh, scale);
- m_dirtyPhysx = false;
-}
-
-const QUrl &QConvexMeshShape::source() const
+QMeshShape::MeshType QConvexMeshShape::shapeType() const
{
- return m_meshSource;
-}
-
-void QConvexMeshShape::setSource(const QUrl &newSource)
-{
- if (m_meshSource == newSource)
- return;
- m_meshSource = newSource;
- m_mesh = QQuick3DPhysicsMeshManager::getMesh(m_meshSource, this);
- updatePhysXGeometry();
-
- m_dirtyPhysx = true;
-
- emit needsRebuild(this);
- emit sourceChanged();
+ return QMeshShape::MeshType::CONVEX;
}
QT_END_NAMESPACE
diff --git a/src/quick3dphysics/qconvexmeshshape_p.h b/src/quick3dphysics/qconvexmeshshape_p.h
index 75ddad9..d48b915 100644
--- a/src/quick3dphysics/qconvexmeshshape_p.h
+++ b/src/quick3dphysics/qconvexmeshshape_p.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef CONVEXMESHSHAPE_H
@@ -15,46 +15,15 @@
// We mean it.
//
-#include <QtQuick3DPhysics/qtquick3dphysicsglobal.h>
-#include <QtQuick3DPhysics/private/qabstractcollisionshape_p.h>
-#include <QtCore/QObject>
-#include <QtGui/QVector3D>
-#include <QtQml/QQmlEngine>
-
-namespace physx {
-class PxBoxGeometry;
-class PxConvexMesh;
-class PxConvexMeshGeometry;
-}
+#include "qmeshshape_p.h"
QT_BEGIN_NAMESPACE
-class QQuick3DPhysicsMesh;
-class Q_QUICK3DPHYSICS_EXPORT QConvexMeshShape : public QAbstractCollisionShape
+class Q_QUICK3DPHYSICS_EXPORT QConvexMeshShape : public QMeshShape
{
Q_OBJECT
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged REVISION(6, 5))
QML_NAMED_ELEMENT(ConvexMeshShape)
-public:
- QConvexMeshShape();
- ~QConvexMeshShape();
-
- physx::PxGeometry *getPhysXGeometry() override;
-
- Q_REVISION(6, 5) const QUrl &source() const;
- Q_REVISION(6, 5) void setSource(const QUrl &newSource);
- bool isStaticShape() const override { return false; }
-
-signals:
- Q_REVISION(6, 5) void sourceChanged();
-
-private:
- void updatePhysXGeometry();
-
- bool m_dirtyPhysx = false;
- physx::PxConvexMeshGeometry *m_meshGeometry = nullptr;
- QUrl m_meshSource;
- QQuick3DPhysicsMesh *m_mesh = nullptr;
+ virtual QMeshShape::MeshType shapeType() const override;
};
QT_END_NAMESPACE
diff --git a/src/quick3dphysics/qmeshshape.cpp b/src/quick3dphysics/qmeshshape.cpp
new file mode 100644
index 0000000..f7d38da
--- /dev/null
+++ b/src/quick3dphysics/qmeshshape.cpp
@@ -0,0 +1,310 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qcacheutils_p.h"
+#include "qmeshshape_p.h"
+
+#include <QFile>
+#include <QFileInfo>
+#include <QtQuick3D/QQuick3DGeometry>
+#include <extensions/PxExtensionsAPI.h>
+
+#include "foundation/PxVec3.h"
+#include "cooking/PxConvexMeshDesc.h"
+#include "extensions/PxDefaultStreams.h"
+
+#include <QtQml/qqml.h>
+#include <QtQml/QQmlFile>
+#include <QtQml/qqmlcontext.h>
+
+#include <QtQuick3DUtils/private/qssgmesh_p.h>
+#include "qmeshshape_p.h"
+#include "qphysicsworld_p.h"
+#include "qphysicsmeshutils_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+physx::PxConvexMesh *QQuick3DPhysicsMesh::convexMesh()
+{
+ if (m_convexMesh != nullptr)
+ return m_convexMesh;
+
+ physx::PxPhysics *thePhysics = QPhysicsWorld::getPhysics();
+ if (thePhysics == nullptr)
+ return nullptr;
+
+ m_convexMesh = QCacheUtils::readCachedConvexMesh(m_meshPath, *thePhysics);
+ if (m_convexMesh != nullptr)
+ return m_convexMesh;
+
+ m_convexMesh = QCacheUtils::readCookedConvexMesh(m_meshPath, *thePhysics);
+ if (m_convexMesh != nullptr)
+ return m_convexMesh;
+
+ loadSsgMesh();
+
+ if (!m_ssgMesh.isValid())
+ return nullptr;
+
+ physx::PxDefaultMemoryOutputStream buf;
+ physx::PxConvexMeshCookingResult::Enum result;
+ int vStride = m_ssgMesh.vertexBuffer().stride;
+ int vCount = m_ssgMesh.vertexBuffer().data.size() / vStride;
+ const auto *vd = m_ssgMesh.vertexBuffer().data.constData();
+
+ qCDebug(lcQuick3dPhysics) << "prepare cooking" << vCount << "verts";
+
+ QVector<physx::PxVec3> verts;
+
+ for (int i = 0; i < vCount; ++i) {
+ auto *vp = reinterpret_cast<const QVector3D *>(vd + vStride * i + m_posOffset);
+ verts << physx::PxVec3 { vp->x(), vp->y(), vp->z() };
+ }
+
+ const auto *convexVerts = verts.constData();
+
+ physx::PxConvexMeshDesc convexDesc;
+ convexDesc.points.count = vCount;
+ convexDesc.points.stride = sizeof(physx::PxVec3);
+ convexDesc.points.data = convexVerts;
+ convexDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;
+
+ const auto cooking = QPhysicsWorld::getCooking();
+ if (cooking && cooking->cookConvexMesh(convexDesc, buf, &result)) {
+ auto size = buf.getSize();
+ auto *data = buf.getData();
+ physx::PxDefaultMemoryInputData input(data, size);
+ m_convexMesh = thePhysics->createConvexMesh(input);
+ qCDebug(lcQuick3dPhysics) << "Created convex mesh" << m_convexMesh << "for mesh" << this;
+ QCacheUtils::writeCachedConvexMesh(m_meshPath, buf);
+ } else {
+ qCWarning(lcQuick3dPhysics) << "Could not create convex mesh from" << m_meshPath;
+ }
+
+ return m_convexMesh;
+}
+
+physx::PxTriangleMesh *QQuick3DPhysicsMesh::triangleMesh()
+{
+ if (m_triangleMesh != nullptr)
+ return m_triangleMesh;
+
+ physx::PxPhysics *thePhysics = QPhysicsWorld::getPhysics();
+ if (thePhysics == nullptr)
+ return nullptr;
+
+ m_triangleMesh = QCacheUtils::readCachedTriangleMesh(m_meshPath, *thePhysics);
+ if (m_triangleMesh != nullptr)
+ return m_triangleMesh;
+
+ m_triangleMesh = QCacheUtils::readCookedTriangleMesh(m_meshPath, *thePhysics);
+ if (m_triangleMesh != nullptr)
+ return m_triangleMesh;
+
+ loadSsgMesh();
+ if (!m_ssgMesh.isValid())
+ return nullptr;
+
+ physx::PxDefaultMemoryOutputStream buf;
+ physx::PxTriangleMeshCookingResult::Enum result;
+ const int vStride = m_ssgMesh.vertexBuffer().stride;
+ const int vCount = m_ssgMesh.vertexBuffer().data.size() / vStride;
+ const auto *vd = m_ssgMesh.vertexBuffer().data.constData();
+
+ const int iStride =
+ m_ssgMesh.indexBuffer().componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16
+ ? 2
+ : 4;
+ const int iCount = m_ssgMesh.indexBuffer().data.size() / iStride;
+
+ qCDebug(lcQuick3dPhysics) << "prepare cooking" << vCount << "verts" << iCount << "idxs";
+
+ physx::PxTriangleMeshDesc triangleDesc;
+ triangleDesc.points.count = vCount;
+ triangleDesc.points.stride = vStride;
+ triangleDesc.points.data = vd + m_posOffset;
+
+ triangleDesc.flags = {}; //??? physx::PxMeshFlag::eFLIPNORMALS or
+ // physx::PxMeshFlag::e16_BIT_INDICES
+ triangleDesc.triangles.count = iCount / 3;
+ triangleDesc.triangles.stride = iStride * 3;
+ triangleDesc.triangles.data = m_ssgMesh.indexBuffer().data.constData();
+
+ const auto cooking = QPhysicsWorld::getCooking();
+ if (cooking && cooking->cookTriangleMesh(triangleDesc, buf, &result)) {
+ auto size = buf.getSize();
+ auto *data = buf.getData();
+ physx::PxDefaultMemoryInputData input(data, size);
+ m_triangleMesh = thePhysics->createTriangleMesh(input);
+ qCDebug(lcQuick3dPhysics) << "Created triangle mesh" << m_triangleMesh << "for mesh"
+ << this;
+ QCacheUtils::writeCachedTriangleMesh(m_meshPath, buf);
+ } else {
+ qCWarning(lcQuick3dPhysics) << "Could not create triangle mesh from" << m_meshPath;
+ }
+
+ return m_triangleMesh;
+}
+
+void QQuick3DPhysicsMesh::loadSsgMesh()
+{
+ if (m_ssgMesh.isValid())
+ return;
+
+ static const char *compTypes[] = { "Null", "UnsignedInt8", "Int8", "UnsignedInt16",
+ "Int16", "UnsignedInt32", "Int32", "UnsignedInt64",
+ "Int64", "Float16", "Float32", "Float64" };
+
+ QFileInfo fileInfo = QFileInfo(m_meshPath);
+ if (fileInfo.exists()) {
+ QFile file(fileInfo.absoluteFilePath());
+ if (file.open(QFile::ReadOnly))
+ m_ssgMesh = QSSGMesh::Mesh::loadMesh(&file);
+ }
+ qCDebug(lcQuick3dPhysics) << "Loaded SSG mesh from" << m_meshPath << m_ssgMesh.isValid()
+ << "draw" << int(m_ssgMesh.drawMode()) << "wind"
+ << int(m_ssgMesh.winding()) << "subs" << m_ssgMesh.subsets().count()
+ << "attrs" << m_ssgMesh.vertexBuffer().entries.count()
+ << m_ssgMesh.vertexBuffer().data.size() << "stride"
+ << m_ssgMesh.vertexBuffer().stride << "verts"
+ << m_ssgMesh.vertexBuffer().data.size()
+ / m_ssgMesh.vertexBuffer().stride;
+
+ for (auto &v : m_ssgMesh.vertexBuffer().entries) {
+ qCDebug(lcQuick3dPhysics) << " attr" << v.name << compTypes[int(v.componentType)] << "cc"
+ << v.componentCount << "offs" << v.offset;
+ Q_ASSERT(v.componentType == QSSGMesh::Mesh::ComponentType::Float32);
+ if (v.name == "attr_pos")
+ m_posOffset = v.offset;
+ }
+
+ if (m_ssgMesh.isValid()) {
+ auto sub = m_ssgMesh.subsets().constFirst();
+ qCDebug(lcQuick3dPhysics) << "..." << sub.name << "count" << sub.count << "bounds"
+ << sub.bounds.min << sub.bounds.max << "offset" << sub.offset;
+ }
+
+#if 0 // EXTRA_DEBUG
+
+ int iStride = m_ssgMesh.indexBuffer().componentType == QSSGMesh::Mesh::ComponentType::UnsignedInt16 ? 2 : 4;
+ int vStride = m_ssgMesh.vertexBuffer().stride;
+ qDebug() << "IDX" << compTypes[int(m_ssgMesh.indexBuffer().componentType)] << m_ssgMesh.indexBuffer().data.size() / iStride;
+ const auto ib = m_ssgMesh.indexBuffer().data;
+ const auto vb = m_ssgMesh.vertexBuffer().data;
+
+ auto getPoint = [&vb, vStride, this](int idx) -> QVector3D {
+ auto *vp = vb.constData() + vStride * idx + m_posOffset;
+ return *reinterpret_cast<const QVector3D *>(vp);
+ return {};
+ };
+
+ if (iStride == 2) {
+
+ } else {
+ auto *ip = reinterpret_cast<const uint32_t *>(ib.data());
+ int n = ib.size() / iStride;
+ for (int i = 0; i < qMin(50,n); i += 3) {
+
+ qDebug() << " " << ip [i] << ip[i+1] << ip[i+2] << " --- "
+ << getPoint(ip[i]) << getPoint(ip[i+1]) << getPoint(ip[i+2]);
+ }
+ }
+#endif
+ if (!m_ssgMesh.isValid())
+ qCWarning(lcQuick3dPhysics) << "Could not read mesh from" << m_meshPath;
+}
+
+QQuick3DPhysicsMesh *QQuick3DPhysicsMeshManager::getMesh(const QUrl &source,
+ const QObject *contextObject)
+{
+ const QQmlContext *context = qmlContext(contextObject);
+ const auto resolvedUrl = context ? context->resolvedUrl(source) : source;
+ const auto qmlSource = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
+ auto *mesh = meshHash.value(qmlSource);
+ if (!mesh) {
+ mesh = new QQuick3DPhysicsMesh(qmlSource);
+ meshHash[qmlSource] = mesh;
+ }
+ mesh->ref();
+ return mesh;
+}
+
+void QQuick3DPhysicsMeshManager::releaseMesh(QQuick3DPhysicsMesh *mesh)
+{
+ if (mesh->deref() == 0) {
+ qCDebug(lcQuick3dPhysics()) << "deleting mesh" << mesh;
+ erase_if(meshHash, [mesh](std::pair<const QString &, QQuick3DPhysicsMesh *&> h) {
+ return h.second == mesh;
+ });
+ delete mesh;
+ }
+}
+
+QHash<QString, QQuick3DPhysicsMesh *> QQuick3DPhysicsMeshManager::meshHash;
+
+QMeshShape::~QMeshShape()
+{
+ delete m_convexGeometry;
+ if (m_mesh)
+ QQuick3DPhysicsMeshManager::releaseMesh(m_mesh);
+}
+
+physx::PxGeometry *QMeshShape::getPhysXGeometry()
+{
+ if (m_dirtyPhysx || m_scaleDirty)
+ updatePhysXGeometry();
+ if (shapeType() == MeshType::CONVEX)
+ return m_convexGeometry;
+ if (shapeType() == MeshType::TRIANGLE)
+ return m_triangleGeometry;
+
+ Q_UNREACHABLE_RETURN(nullptr);
+}
+
+void QMeshShape::updatePhysXGeometry()
+{
+ delete m_convexGeometry;
+ delete m_triangleGeometry;
+ m_convexGeometry = nullptr;
+ m_triangleGeometry = nullptr;
+
+ if (!m_mesh)
+ return;
+
+ auto *convexMesh = shapeType() == MeshType::CONVEX ? m_mesh->convexMesh() : nullptr;
+ auto *triangleMesh = shapeType() == MeshType::TRIANGLE ? m_mesh->triangleMesh() : nullptr;
+ if (!convexMesh && !triangleMesh)
+ return;
+
+ auto meshScale = sceneScale();
+ physx::PxMeshScale scale(physx::PxVec3(meshScale.x(), meshScale.y(), meshScale.z()),
+ physx::PxQuat(physx::PxIdentity));
+
+ if (convexMesh)
+ m_convexGeometry = new physx::PxConvexMeshGeometry(convexMesh, scale);
+ if (triangleMesh)
+ m_triangleGeometry = new physx::PxTriangleMeshGeometry(triangleMesh, scale);
+
+ m_dirtyPhysx = false;
+}
+
+const QUrl &QMeshShape::source() const
+{
+ return m_meshSource;
+}
+
+void QMeshShape::setSource(const QUrl &newSource)
+{
+ if (m_meshSource == newSource)
+ return;
+ m_meshSource = newSource;
+ m_mesh = QQuick3DPhysicsMeshManager::getMesh(m_meshSource, this);
+ updatePhysXGeometry();
+
+ m_dirtyPhysx = true;
+
+ emit needsRebuild(this);
+ emit sourceChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick3dphysics/qmeshshape_p.h b/src/quick3dphysics/qmeshshape_p.h
new file mode 100644
index 0000000..a903390
--- /dev/null
+++ b/src/quick3dphysics/qmeshshape_p.h
@@ -0,0 +1,69 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef MESHSHAPE_H
+#define MESHSHAPE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick3DPhysics/qtquick3dphysicsglobal.h>
+#include <QtQuick3DPhysics/private/qabstractcollisionshape_p.h>
+#include <QtCore/QObject>
+#include <QtGui/QVector3D>
+#include <QtQml/QQmlEngine>
+
+namespace physx {
+class PxBoxGeometry;
+class PxConvexMesh;
+class PxConvexMeshGeometry;
+class PxTriangleMesh;
+class PxTriangleMeshGeometry;
+}
+
+QT_BEGIN_NAMESPACE
+class QQuick3DPhysicsMesh;
+
+class Q_QUICK3DPHYSICS_EXPORT QMeshShape : public QAbstractCollisionShape
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged REVISION(6, 5))
+ QML_NAMED_ELEMENT(MeshShape)
+ QML_UNCREATABLE("abstract interface")
+
+public:
+ ~QMeshShape();
+
+ enum class MeshType { TRIANGLE, CONVEX };
+ virtual MeshType shapeType() const = 0;
+
+ physx::PxGeometry *getPhysXGeometry() override;
+
+ Q_REVISION(6, 5) const QUrl &source() const;
+ Q_REVISION(6, 5) void setSource(const QUrl &newSource);
+ bool isStaticShape() const override { return false; }
+
+signals:
+ Q_REVISION(6, 5) void sourceChanged();
+
+private:
+ void updatePhysXGeometry();
+
+ bool m_dirtyPhysx = false;
+ physx::PxConvexMeshGeometry *m_convexGeometry = nullptr;
+ physx::PxTriangleMeshGeometry *m_triangleGeometry = nullptr;
+ QUrl m_meshSource;
+ QQuick3DPhysicsMesh *m_mesh = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // MESHSHAPE_H
diff --git a/src/quick3dphysics/qtrianglemeshshape.cpp b/src/quick3dphysics/qtrianglemeshshape.cpp
index f804d48..64f86e1 100644
--- a/src/quick3dphysics/qtrianglemeshshape.cpp
+++ b/src/quick3dphysics/qtrianglemeshshape.cpp
@@ -1,19 +1,8 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qtrianglemeshshape_p.h"
-#include <QtQuick3D/QQuick3DGeometry>
-#include <extensions/PxExtensionsAPI.h>
-
-#include "qphysicsmeshutils_p_p.h"
-
-//########################################################################################
-// NOTE:
-// Triangle mesh, heightfield or plane geometry shapes configured as eSIMULATION_SHAPE are
-// not supported for non-kinematic PxRigidDynamic instances.
-//########################################################################################
-
QT_BEGIN_NAMESPACE
/*!
@@ -42,58 +31,9 @@ QT_BEGIN_NAMESPACE
for details.
*/
-QTriangleMeshShape::QTriangleMeshShape() = default;
-
-QTriangleMeshShape::~QTriangleMeshShape()
+QMeshShape::MeshType QTriangleMeshShape::shapeType() const
{
- delete m_meshGeometry;
- if (m_mesh)
- QQuick3DPhysicsMeshManager::releaseMesh(m_mesh);
-}
-
-physx::PxGeometry *QTriangleMeshShape::getPhysXGeometry()
-{
- if (m_dirtyPhysx || m_scaleDirty) {
- updatePhysXGeometry();
- }
- return m_meshGeometry;
-}
-
-void QTriangleMeshShape::updatePhysXGeometry()
-{
- delete m_meshGeometry;
- m_meshGeometry = nullptr;
-
- if (!m_mesh)
- return;
- auto *triangleMesh = m_mesh->triangleMesh();
- if (!triangleMesh)
- return;
-
- auto meshScale = sceneScale();
- physx::PxMeshScale scale(physx::PxVec3(meshScale.x(), meshScale.y(), meshScale.z()),
- physx::PxQuat(physx::PxIdentity));
-
- m_meshGeometry = new physx::PxTriangleMeshGeometry(triangleMesh, scale);
- m_dirtyPhysx = false;
-}
-
-const QUrl &QTriangleMeshShape::source() const
-{
- return m_meshSource;
-}
-
-void QTriangleMeshShape::setSource(const QUrl &newSource)
-{
- if (m_meshSource == newSource)
- return;
- m_meshSource = newSource;
- m_mesh = QQuick3DPhysicsMeshManager::getMesh(m_meshSource, this);
-
- updatePhysXGeometry();
-
- emit needsRebuild(this);
- emit sourceChanged();
+ return QMeshShape::MeshType::TRIANGLE;
}
QT_END_NAMESPACE
diff --git a/src/quick3dphysics/qtrianglemeshshape_p.h b/src/quick3dphysics/qtrianglemeshshape_p.h
index a974e50..1fac3f2 100644
--- a/src/quick3dphysics/qtrianglemeshshape_p.h
+++ b/src/quick3dphysics/qtrianglemeshshape_p.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TRIANGLEMESHSHAPE_H
@@ -15,47 +15,15 @@
// We mean it.
//
-#include <QtQuick3DPhysics/qtquick3dphysicsglobal.h>
-#include <QtQuick3DPhysics/private/qabstractcollisionshape_p.h>
-#include <QtCore/QObject>
-#include <QtGui/QVector3D>
-#include <QtQml/QQmlEngine>
-
-namespace physx {
-class PxBoxGeometry;
-class PxTriangleMesh;
-class PxTriangleMeshGeometry;
-}
+#include "qmeshshape_p.h"
QT_BEGIN_NAMESPACE
-class QQuick3DPhysicsMesh;
-class Q_QUICK3DPHYSICS_EXPORT QTriangleMeshShape : public QAbstractCollisionShape
+class Q_QUICK3DPHYSICS_EXPORT QTriangleMeshShape : public QMeshShape
{
Q_OBJECT
- Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged REVISION(6, 5))
-
QML_NAMED_ELEMENT(TriangleMeshShape)
-public:
- QTriangleMeshShape();
- ~QTriangleMeshShape();
-
- physx::PxGeometry *getPhysXGeometry() override;
- Q_REVISION(6, 5) const QUrl &source() const;
- Q_REVISION(6, 5) void setSource(const QUrl &newSource);
- bool isStaticShape() const override { return true; }
-
-signals:
- Q_REVISION(6, 5) void sourceChanged();
-
-private:
- void updatePhysXGeometry();
-
- bool m_dirtyPhysx = false;
- QUrl m_meshSource;
- QQuick3DPhysicsMesh *m_mesh = nullptr;
-
- physx::PxTriangleMeshGeometry *m_meshGeometry = nullptr;
+ virtual QMeshShape::MeshType shapeType() const override;
};
QT_END_NAMESPACE