Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qphysicsworld_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef PHYSICSWORLD_H
6#define PHYSICSWORLD_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtQuick3DPhysics/qtquick3dphysicsglobal.h>
20
21#include <QtCore/QLoggingCategory>
22#include <QtCore/QObject>
23#include <QtCore/QTimerEvent>
24#include <QtCore/QElapsedTimer>
25#include <QtCore/QSpan>
26#include <QtGui/QVector3D>
27#include <QtQml/qqml.h>
28#include <QBasicTimer>
29#include <QtQuick3DPhysics/private/qquick3dphysicslocationhit_p.h>
30
31#include <QtQuick3D/private/qquick3dviewport_p.h>
32
33namespace physx {
34class PxMaterial;
35class PxPhysics;
36class PxShape;
37class PxRigidDynamic;
38class PxRigidActor;
39class PxRigidStatic;
40struct PxCookingParams;
41class PxControllerManager;
42class PxConvexMesh;
43class PxTriangleMesh;
44class PxHeightField;
45class PxJoint;
46}
47
49
51
52class QAbstractPhysicsNode;
53class QAbstractCollisionShape;
54class QAbstractRigidBody;
56class QQuick3DModel;
57class QQuick3DGeometry;
58class QQuick3DPrincipledMaterial;
59class QPhysXWorld;
60class FrameAnimator;
61class QPhysicsJoint;
62
63class Q_QUICK3DPHYSICS_EXPORT QPhysicsWorld : public QObject, public QQmlParserStatus
64{
66 Q_INTERFACES(QQmlParserStatus)
67 Q_PROPERTY(QVector3D gravity READ gravity WRITE setGravity NOTIFY gravityChanged)
68 Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
69 Q_PROPERTY(bool forceDebugDraw READ forceDebugDraw WRITE setForceDebugDraw NOTIFY
70 forceDebugDrawChanged)
71 Q_PROPERTY(bool enableCCD READ enableCCD WRITE setEnableCCD NOTIFY enableCCDChanged)
72 Q_PROPERTY(float typicalLength READ typicalLength WRITE setTypicalLength NOTIFY
73 typicalLengthChanged)
75 float typicalSpeed READ typicalSpeed WRITE setTypicalSpeed NOTIFY typicalSpeedChanged)
76 Q_PROPERTY(float defaultDensity READ defaultDensity WRITE setDefaultDensity NOTIFY
77 defaultDensityChanged)
78 Q_PROPERTY(QQuick3DNode *viewport READ viewport WRITE setViewport NOTIFY viewportChanged
79 REVISION(6, 5))
80 Q_PROPERTY(float minimumTimestep READ minimumTimestep WRITE setMinimumTimestep NOTIFY
81 minimumTimestepChanged REVISION(6, 5))
82 Q_PROPERTY(float maximumTimestep READ maximumTimestep WRITE setMaximumTimestep NOTIFY
83 maximumTimestepChanged REVISION(6, 5))
84 Q_PROPERTY(QQuick3DNode *scene READ scene WRITE setScene NOTIFY sceneChanged REVISION(6, 5))
85 Q_PROPERTY(int numThreads READ numThreads WRITE setNumThreads NOTIFY numThreadsChanged
86 REVISION(6, 7))
87 Q_PROPERTY(bool reportKinematicKinematicCollisions READ reportKinematicKinematicCollisions WRITE
88 setReportKinematicKinematicCollisions NOTIFY
89 reportKinematicKinematicCollisionsChanged FINAL REVISION(6, 7))
90 Q_PROPERTY(bool reportStaticKinematicCollisions READ reportStaticKinematicCollisions WRITE
91 setReportStaticKinematicCollisions NOTIFY
92 reportStaticKinematicCollisionsChanged FINAL REVISION(6, 7))
94 Q_PROPERTY(QueryStructure staticQueryStructure READ staticQueryStructure WRITE
95 setStaticQueryStructure NOTIFY staticQueryStructureChanged FINAL REVISION(6, 13))
96
97 Q_PROPERTY(QueryStructure dynamicQueryStructure READ dynamicQueryStructure WRITE
98 setDynamicQueryStructure NOTIFY dynamicQueryStructureChanged FINAL REVISION(6, 13))
99
100 QML_NAMED_ELEMENT(PhysicsWorld)
101
102public:
103 enum class QueryStructure {
104 NoStructure, // eNONE
105 StaticTree, // eSTATIC_AABB_TREE
106 DynamicTree // eDYNAMIC_AABB_TREE
107 };
108 Q_ENUM(QueryStructure)
109
110 explicit QPhysicsWorld(QObject *parent = nullptr);
111 ~QPhysicsWorld();
113 void classBegin() override;
114 void componentComplete() override;
115
116 QVector3D gravity() const;
117
118 bool running() const;
119 bool forceDebugDraw() const;
120 bool enableCCD() const;
121 float typicalLength() const;
122 float typicalSpeed() const;
123 float defaultDensity() const;
124 Q_REVISION(6, 5) float minimumTimestep() const;
125 Q_REVISION(6, 5) float maximumTimestep() const;
126
127 bool isNodeRemoved(QAbstractPhysicsNode *object);
128
129 static QPhysicsWorld *getWorld(QQuick3DNode *node);
130 static QPhysicsWorld *getWorld(QPhysicsJoint *joint);
131
132 static void registerNode(QAbstractPhysicsNode *physicsNode);
133 static void deregisterNode(QAbstractPhysicsNode *physicsNode);
135 static void registerJoint(QPhysicsJoint *joint);
136 static void deregisterJoint(QPhysicsJoint *joint);
137
138 void registerContact(QAbstractPhysicsNode *sender, QAbstractPhysicsNode *receiver,
139 const QVector<QVector3D> &positions, const QVector<QVector3D> &impulses,
140 const QVector<QVector3D> &normals);
141
142 Q_REVISION(6, 5) QQuick3DNode *viewport() const;
143 void setHasIndividualDebugDraw();
144 physx::PxControllerManager *controllerManager();
145 Q_REVISION(6, 5) QQuick3DNode *scene() const;
146 Q_REVISION(6, 7) int numThreads() const;
147 Q_REVISION(6, 7) bool reportKinematicKinematicCollisions() const;
149 void setReportKinematicKinematicCollisions(bool newReportKinematicKinematicCollisions);
150 Q_REVISION(6, 7) bool reportStaticKinematicCollisions() const;
152 void setReportStaticKinematicCollisions(bool newReportStaticKinematicCollisions);
154 void cleanupRemovedJoints();
155
156 Q_REVISION(6, 13) QueryStructure staticQueryStructure() const;
157 Q_REVISION(6, 13) void setStaticQueryStructure(QueryStructure newStaticQueryStructure);
158
159 Q_REVISION(6, 13) QueryStructure dynamicQueryStructure() const;
160 Q_REVISION(6, 13) void setDynamicQueryStructure(QueryStructure newDynamicQueryStructure);
161
162 Q_REVISION(6, 13) Q_INVOKABLE bool testRaycastQuery(const QVector3D &origin,
163 const QVector3D &direction,
164 float maxDistance,
165 bool includeStatic = true,
166 bool includeDynamic = true) const;
167
168 Q_REVISION(6, 13) Q_INVOKABLE QQuick3DPhysicsLocationHit singleRaycastQuery(const QVector3D &origin,
169 const QVector3D &direction,
170 float maxDistance,
171 bool includeStatic = true,
172 bool includeDynamic = true) const;
173
174 Q_REVISION(6, 13) Q_INVOKABLE QList<QQuick3DPhysicsLocationHit> multiRaycastQuery(const QVector3D &origin,
175 const QVector3D &direction,
176 float maxDistance,
177 bool includeStatic = true,
178 bool includeDynamic = true) const;
179
180 Q_REVISION(6, 13) Q_INVOKABLE bool testSweepQuery(QAbstractCollisionShape *shape,
181 const QVector3D &direction,
182 float maxDistance,
183 bool includeStatic = true,
184 bool includeDynamic = true) const;
185
186 Q_REVISION(6, 13) Q_INVOKABLE QQuick3DPhysicsLocationHit singleSweepQuery(QAbstractCollisionShape *shape,
187 const QVector3D &direction,
188 float maxDistance,
189 bool includeStatic = true,
190 bool includeDynamic = true) const;
191
192 Q_REVISION(6, 13) Q_INVOKABLE QList<QQuick3DPhysicsLocationHit> multiSweepQuery(QAbstractCollisionShape *shape,
193 const QVector3D &direction,
194 float maxDistance,
195 bool includeStatic = true,
196 bool includeDynamic = true) const;
197
198 Q_REVISION(6, 13) Q_INVOKABLE bool testOverlapQuery(QAbstractCollisionShape *shape,
199 bool includeStatic = true,
200 bool includeDynamic = true) const;
201
202 Q_REVISION(6, 13) Q_INVOKABLE QList<QQuick3DPhysicsQueryHit> multiOverlapQuery(QAbstractCollisionShape *shape,
203 bool includeStatic = true,
204 bool includeDynamic = true) const;
206public slots:
207 void setGravity(QVector3D gravity);
208 void setRunning(bool running);
209 void setForceDebugDraw(bool forceDebugDraw);
210 void setEnableCCD(bool enableCCD);
211 void setTypicalLength(float typicalLength);
212 void setTypicalSpeed(float typicalSpeed);
213 void setDefaultDensity(float defaultDensity);
214 Q_REVISION(6, 5) void setViewport(QQuick3DNode *viewport);
215 Q_REVISION(6, 5) void setMinimumTimestep(float minTimestep);
216 Q_REVISION(6, 5) void setMaximumTimestep(float maxTimestep);
217 Q_REVISION(6, 5) void setScene(QQuick3DNode *newScene);
218 Q_REVISION(6, 7) void setNumThreads(int newNumThreads);
221 void gravityChanged(QVector3D gravity);
222 void runningChanged(bool running);
223 void enableCCDChanged(bool enableCCD);
224 void forceDebugDrawChanged(bool forceDebugDraw);
225 void typicalLengthChanged(float typicalLength);
226 void typicalSpeedChanged(float typicalSpeed);
227 void defaultDensityChanged(float defaultDensity);
228 Q_REVISION(6, 5) void viewportChanged(QQuick3DNode *viewport);
229 Q_REVISION(6, 5) void minimumTimestepChanged(float minimumTimestep);
230 Q_REVISION(6, 5) void maximumTimestepChanged(float maxTimestep);
231 Q_REVISION(6, 5) void frameDone(float timestep);
232 Q_REVISION(6, 5) void sceneChanged();
233 Q_REVISION(6, 7) void numThreadsChanged();
234 Q_REVISION(6, 7) void reportKinematicKinematicCollisionsChanged();
235 Q_REVISION(6, 7) void reportStaticKinematicCollisionsChanged();
236
237 Q_REVISION(6, 13) void staticQueryStructureChanged();
238 Q_REVISION(6, 13) void dynamicQueryStructureChanged();
239
240private:
241 void simulateFrame();
242 void frameFinished(float deltaTime);
243 void frameFinishedDesignStudio();
244 void initPhysics();
245 void invalidateTriggerOverlaps(QSpan<QAbstractPhysXNode *const> rebuiltBodies);
246 void dropUnreportedTriggerOverlaps();
247 void cleanupRemovedNodes();
248 void updateDebugDraw();
249 void updateDebugDrawDesignStudio();
250 void setupDebugMaterials(QQuick3DNode *sceneNode);
251 void disableDebugDraw();
252 void matchOrphanNodes();
253 void matchOrphanJoints();
254 void findPhysicsNodes();
255 void emitContactCallbacks();
256
257 struct BodyContact
258 {
259 QAbstractPhysicsNode *sender = nullptr;
260 QAbstractPhysicsNode *receiver = nullptr;
261 QVector<QVector3D> positions;
262 QVector<QVector3D> impulses;
263 QVector<QVector3D> normals;
264 };
265
266 struct DebugModelHolder
267 {
268 QQuick3DModel *model = nullptr;
269 QQuick3DGeometry *geometry = nullptr;
270 QVector3D data;
271 void *ptr = nullptr;
272
273 void releaseMeshPointer();
274
275 const QVector3D &halfExtents() const;
276 void setHalfExtents(const QVector3D &halfExtents);
277
278 float radius() const;
279 void setRadius(float radius);
280
281 float heightScale() const;
282 void setHeightScale(float heightScale);
283
284 float halfHeight() const;
285 void setHalfHeight(float halfHeight);
286
287 float rowScale() const;
288 void setRowScale(float rowScale);
289
290 float columnScale() const;
291 void setColumnScale(float columnScale);
292
293 physx::PxConvexMesh *getConvexMesh();
294 void setConvexMesh(physx::PxConvexMesh *mesh);
295
296 physx::PxTriangleMesh *getTriangleMesh();
297 void setTriangleMesh(physx::PxTriangleMesh *mesh);
298
299 physx::PxHeightField *getHeightField();
300 void setHeightField(physx::PxHeightField *hf);
301 };
302
303 QList<QAbstractPhysXNode *> m_physXBodies;
304 QList<QPhysicsJoint *> m_joints;
305 QList<QAbstractPhysicsNode *> m_newPhysicsNodes;
306 QHash<QPair<QAbstractCollisionShape *, QAbstractPhysicsNode *>, DebugModelHolder>
307 m_DesignStudioDebugModels;
308 QHash<QPair<QAbstractCollisionShape *, QAbstractPhysXNode *>, DebugModelHolder>
309 m_collisionShapeDebugModels;
310 QSet<QAbstractPhysicsNode *> m_removedPhysicsNodes;
311 QSet<physx::PxJoint *> m_removedJoints;
312 // Whether any trigger is holding shape pairs that are waiting to be reported
313 // again after the shapes on one side of them were replaced.
314 bool m_triggerOverlapsInvalidated = false;
315 QList<BodyContact> m_registeredContacts;
316
317 QVector3D m_gravity = QVector3D(0.f, -981.f, 0.f);
318 float m_typicalLength = 100.f; // 100 cm
319 float m_typicalSpeed = 1000.f; // 1000 cm/s
320 float m_defaultDensity = 0.001f; // 1 g/cm^3
321 float m_minTimestep = 1.0f; // 1000 fps
322 float m_maxTimestep = 33.333f; // 30 fps
323
324 bool m_running = true;
325 bool m_forceDebugDraw = false;
326 // For performance, used to keep track if we have indiviually enabled debug drawing for any
327 // collision shape
328 bool m_hasIndividualDebugDraw = false;
329 bool m_physicsInitialized = false;
330 bool m_enableCCD = false;
331
332 QPhysXWorld *m_physx = nullptr;
333 QQuick3DNode *m_viewport = nullptr;
334 QVector<QQuick3DPrincipledMaterial *> m_debugMaterials;
335
336 friend class QQuick3DPhysicsMesh; // TODO: better internal API
337 friend class QTriangleMeshShape; //####
338 friend class QHeightFieldShape;
339 friend class QQuick3DPhysicsHeightField;
340 friend class SimulationEventCallback;
341 friend class ControllerCallback;
342 static physx::PxPhysics *getPhysics();
343 static const physx::PxCookingParams *getCookingParams();
344 FrameAnimator *m_frameAnimator = nullptr;
345 QQuick3DNode *m_scene = nullptr;
346 bool m_inDesignStudio = false;
347 int m_numThreads = -1;
348 bool m_reportKinematicKinematicCollisions = false;
349 bool m_reportStaticKinematicCollisions = false;
350 QElapsedTimer m_timer;
351 float m_currTimeStep = 0.f;
352 QList<float> m_frameTimings;
353 bool m_frameFetched = false;
354 QueryStructure m_staticQueryStructure = QueryStructure::DynamicTree;
355 QueryStructure m_dynamicQueryStructure = QueryStructure::DynamicTree;
356};
357
359
360#endif // PHYSICSWORLD_H
Q_ALWAYS_INLINE bool fuzzyEquals(const physx::PxTransform &a, const physx::PxTransform &b)
const QQuaternion kMinus90YawRotation
Q_ALWAYS_INLINE bool isFinite(const QVector3D &v)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQuick3dPhysics)
#define QML_NAMED_ELEMENT(NAME)
#define QT_BEGIN_NAMESPACE
#define QT_END_NAMESPACE
#define Q_ENUM(x)
#define Q_PROPERTY(...)
#define Q_OBJECT
#define Q_REVISION(...)
#define Q_INVOKABLE
#define Q_INTERFACES(x)
#define slots
#define signals
#define emit