1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef PHYSICSWORLD_H
5#define PHYSICSWORLD_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtQuick3DPhysics/qtquick3dphysicsglobal.h>
19
20#include <QtCore/QLoggingCategory>
21#include <QtCore/QObject>
22#include <QtCore/QTimerEvent>
23#include <QtCore/QElapsedTimer>
24#include <QtGui/QVector3D>
25#include <QtQml/qqml.h>
26#include <QBasicTimer>
27
28#include <QtQuick3D/private/qquick3dviewport_p.h>
29
30namespace physx {
31class PxMaterial;
32class PxPhysics;
33class PxShape;
34class PxRigidDynamic;
35class PxRigidActor;
36class PxRigidStatic;
37class PxCooking;
38class PxControllerManager;
39}
40
41QT_BEGIN_NAMESPACE
42
43Q_DECLARE_LOGGING_CATEGORY(lcQuick3dPhysics);
44
45class QAbstractPhysicsNode;
46class QAbstractCollisionShape;
47class QAbstractRigidBody;
48class QAbstractPhysXNode;
49class QQuick3DModel;
50class QQuick3DGeometry;
51class QQuick3DDefaultMaterial;
52class QPhysXWorld;
53
54class Q_QUICK3DPHYSICS_EXPORT QPhysicsWorld : public QObject, public QQmlParserStatus
55{
56 Q_OBJECT
57 Q_INTERFACES(QQmlParserStatus)
58 Q_PROPERTY(QVector3D gravity READ gravity WRITE setGravity NOTIFY gravityChanged)
59 Q_PROPERTY(bool running READ running WRITE setRunning NOTIFY runningChanged)
60 Q_PROPERTY(bool forceDebugDraw READ forceDebugDraw WRITE setForceDebugDraw NOTIFY
61 forceDebugDrawChanged)
62 Q_PROPERTY(bool enableCCD READ enableCCD WRITE setEnableCCD NOTIFY enableCCDChanged)
63 Q_PROPERTY(float typicalLength READ typicalLength WRITE setTypicalLength NOTIFY
64 typicalLengthChanged)
65 Q_PROPERTY(
66 float typicalSpeed READ typicalSpeed WRITE setTypicalSpeed NOTIFY typicalSpeedChanged)
67 Q_PROPERTY(float defaultDensity READ defaultDensity WRITE setDefaultDensity NOTIFY
68 defaultDensityChanged)
69 Q_PROPERTY(QQuick3DNode *viewport READ viewport WRITE setViewport NOTIFY viewportChanged
70 REVISION(6, 5))
71 Q_PROPERTY(float minimumTimestep READ minimumTimestep WRITE setMinimumTimestep NOTIFY
72 minimumTimestepChanged REVISION(6, 5))
73 Q_PROPERTY(float maximumTimestep READ maximumTimestep WRITE setMaximumTimestep NOTIFY
74 maximumTimestepChanged REVISION(6, 5))
75 Q_PROPERTY(QQuick3DNode *scene READ scene WRITE setScene NOTIFY sceneChanged REVISION(6, 5))
76
77 QML_NAMED_ELEMENT(PhysicsWorld)
78
79public:
80 explicit QPhysicsWorld(QObject *parent = nullptr);
81 ~QPhysicsWorld();
82
83 void classBegin() override;
84 void componentComplete() override;
85
86 QVector3D gravity() const;
87
88 bool running() const;
89 bool forceDebugDraw() const;
90 bool enableCCD() const;
91 float typicalLength() const;
92 float typicalSpeed() const;
93 float defaultDensity() const;
94 Q_REVISION(6, 5) float minimumTimestep() const;
95 Q_REVISION(6, 5) float maximumTimestep() const;
96
97 bool isNodeRemoved(QAbstractPhysicsNode *object);
98
99 static QPhysicsWorld *getWorld(QQuick3DNode *node);
100
101 static void registerNode(QAbstractPhysicsNode *physicsNode);
102 static void deregisterNode(QAbstractPhysicsNode *physicsNode);
103
104 Q_REVISION(6, 5) QQuick3DNode *viewport() const;
105 void setHasIndividualDebugDraw();
106 physx::PxControllerManager *controllerManager();
107 Q_REVISION(6, 5) QQuick3DNode *scene() const;
108
109public slots:
110 void setGravity(QVector3D gravity);
111 void setRunning(bool running);
112 void setForceDebugDraw(bool forceDebugDraw);
113 void setEnableCCD(bool enableCCD);
114 void setTypicalLength(float typicalLength);
115 void setTypicalSpeed(float typicalSpeed);
116 void setDefaultDensity(float defaultDensity);
117 Q_REVISION(6, 5) void setViewport(QQuick3DNode *viewport);
118 Q_REVISION(6, 5) void setMinimumTimestep(float minTimestep);
119 Q_REVISION(6, 5) void setMaximumTimestep(float maxTimestep);
120 Q_REVISION(6, 5) void setScene(QQuick3DNode *newScene);
121
122signals:
123 void gravityChanged(QVector3D gravity);
124 void runningChanged(bool running);
125 void enableCCDChanged(bool enableCCD);
126 void forceDebugDrawChanged(bool forceDebugDraw);
127 void typicalLengthChanged(float typicalLength);
128 void typicalSpeedChanged(float typicalSpeed);
129 void defaultDensityChanged(float defaultDensity);
130 Q_REVISION(6, 5) void viewportChanged(QQuick3DNode *viewport);
131 Q_REVISION(6, 5) void minimumTimestepChanged(float minimumTimestep);
132 Q_REVISION(6, 5) void maximumTimestepChanged(float maxTimestep);
133 void simulateFrame(float minTimestep, float maxTimestep);
134 Q_REVISION(6, 5) void frameDone(float timestep);
135 Q_REVISION(6, 5) void sceneChanged();
136
137private:
138 void frameFinished(float deltaTime);
139 void frameFinishedDesignStudio();
140 void initPhysics();
141 void cleanupRemovedNodes();
142 void updateDebugDraw();
143 void updateDebugDrawDesignStudio();
144 void setupDebugMaterials(QQuick3DNode *sceneNode);
145 void disableDebugDraw();
146 void matchOrphanNodes();
147 void findPhysicsNodes();
148
149 struct DebugModelHolder
150 {
151 QQuick3DModel *model = nullptr;
152 QQuick3DGeometry *geometry = nullptr;
153 QVector3D data;
154
155 const QVector3D &halfExtents() const { return data; }
156 void setHalfExtents(const QVector3D &halfExtents) { data = halfExtents; }
157
158 float radius() const { return data.x(); }
159 void setRadius(float radius) { data.setX(radius); }
160
161 float heightScale() const { return data.x(); }
162 void setHeightScale(float heightScale) { data.setX(heightScale); }
163
164 float halfHeight() const { return data.y(); }
165 void setHalfHeight(float halfHeight) { data.setY(halfHeight); }
166
167 float rowScale() const { return data.y(); }
168 void setRowScale(float rowScale) { data.setY(rowScale); }
169
170 float columnScale() const { return data.z(); }
171 void setColumnScale(float columnScale) { data.setZ(columnScale); }
172 };
173
174 QList<QAbstractPhysXNode *> m_physXBodies;
175 QList<QAbstractPhysicsNode *> m_newPhysicsNodes;
176 QHash<QPair<QAbstractCollisionShape *, QAbstractPhysicsNode *>, DebugModelHolder>
177 m_DesignStudioDebugModels;
178 QHash<QPair<QAbstractCollisionShape *, QAbstractPhysXNode *>, DebugModelHolder>
179 m_collisionShapeDebugModels;
180 QSet<QAbstractPhysicsNode *> m_removedPhysicsNodes;
181 QMutex m_removedPhysicsNodesMutex;
182
183 QVector3D m_gravity = QVector3D(0.f, -981.f, 0.f);
184 float m_typicalLength = 100.f; // 100 cm
185 float m_typicalSpeed = 1000.f; // 1000 cm/s
186 float m_defaultDensity = 0.001f; // 1 g/cm^3
187 float m_minTimestep = 16.667f; // 60 fps
188 float m_maxTimestep = 33.333f; // 30 fps
189
190 bool m_running = true;
191 bool m_forceDebugDraw = false;
192 // For performance, used to keep track if we have indiviually enabled debug drawing for any
193 // collision shape
194 bool m_hasIndividualDebugDraw = false;
195 bool m_physicsInitialized = false;
196 bool m_enableCCD = false;
197
198 QPhysXWorld *m_physx = nullptr;
199 QQuick3DNode *m_viewport = nullptr;
200 QVector<QQuick3DDefaultMaterial *> m_debugMaterials;
201
202 friend class QQuick3DPhysicsMesh; // TODO: better internal API
203 friend class QTriangleMeshShape; //####
204 friend class QHeightFieldShape;
205 friend class QQuick3DPhysicsHeightField;
206 friend class SimulationEventCallback;
207 friend class ControllerCallback;
208 static physx::PxPhysics *getPhysics();
209 static physx::PxCooking *getCooking();
210 QThread m_workerThread;
211 QQuick3DNode *m_scene = nullptr;
212 bool m_inDesignStudio = false;
213};
214
215QT_END_NAMESPACE
216
217#endif // PHYSICSWORLD_H
218

source code of qtquick3dphysics/src/quick3dphysics/qphysicsworld_p.h