1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #ifndef DYNAMICRIGIDBODY_H |
5 | #define DYNAMICRIGIDBODY_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/private/qabstractphysicsbody_p.h> |
19 | #include <QtQml/QQmlEngine> |
20 | |
21 | #include <QtCore/QQueue> |
22 | #include <QtQuick3DUtils/private/qssgutils_p.h> |
23 | |
24 | QT_BEGIN_NAMESPACE |
25 | |
26 | class QPhysicsCommand; |
27 | |
28 | class Q_QUICK3DPHYSICS_EXPORT QDynamicRigidBody : public QAbstractPhysicsBody |
29 | { |
30 | public: |
31 | enum class MassMode { |
32 | DefaultDensity, |
33 | CustomDensity, |
34 | Mass, |
35 | MassAndInertiaTensor, |
36 | MassAndInertiaMatrix, |
37 | }; |
38 | Q_ENUM(MassMode) |
39 | |
40 | enum AxisLock { |
41 | LockNone = 0, |
42 | LockX = 1, |
43 | LockY = 2, |
44 | LockZ = 4, |
45 | }; |
46 | Q_ENUM(AxisLock) |
47 | |
48 | Q_OBJECT |
49 | Q_PROPERTY(float mass READ mass WRITE setMass NOTIFY massChanged) |
50 | Q_PROPERTY(float density READ density WRITE setDensity NOTIFY densityChanged) |
51 | |
52 | Q_PROPERTY(AxisLock linearAxisLock READ linearAxisLock WRITE setLinearAxisLock NOTIFY |
53 | linearAxisLockChanged REVISION(6, 5)) |
54 | Q_PROPERTY(AxisLock angularAxisLock READ angularAxisLock WRITE setAngularAxisLock NOTIFY |
55 | angularAxisLockChanged REVISION(6, 5)) |
56 | |
57 | Q_PROPERTY(bool isKinematic READ isKinematic WRITE setIsKinematic NOTIFY isKinematicChanged) |
58 | Q_PROPERTY(bool gravityEnabled READ gravityEnabled WRITE setGravityEnabled NOTIFY |
59 | gravityEnabledChanged) |
60 | |
61 | Q_PROPERTY(MassMode massMode READ massMode WRITE setMassMode NOTIFY massModeChanged) |
62 | Q_PROPERTY(QVector3D inertiaTensor READ inertiaTensor WRITE setInertiaTensor NOTIFY |
63 | inertiaTensorChanged) |
64 | Q_PROPERTY(QVector3D centerOfMassPosition READ centerOfMassPosition WRITE |
65 | setCenterOfMassPosition NOTIFY centerOfMassPositionChanged) |
66 | Q_PROPERTY(QQuaternion centerOfMassRotation READ centerOfMassRotation WRITE |
67 | setCenterOfMassRotation NOTIFY centerOfMassRotationChanged) |
68 | Q_PROPERTY(QList<float> inertiaMatrix READ readInertiaMatrix WRITE setInertiaMatrix NOTIFY |
69 | inertiaMatrixChanged); |
70 | |
71 | Q_PROPERTY(QVector3D kinematicPosition READ kinematicPosition WRITE setKinematicPosition NOTIFY |
72 | kinematicPositionChanged REVISION(6, 5)); |
73 | Q_PROPERTY(QVector3D kinematicEulerRotation READ kinematicEulerRotation WRITE |
74 | setKinematicEulerRotation NOTIFY kinematicEulerRotationChanged REVISION(6, |
75 | 5)); |
76 | Q_PROPERTY(QQuaternion kinematicRotation READ kinematicRotation WRITE setKinematicRotation |
77 | NOTIFY kinematicRotationChanged REVISION(6, 5)); |
78 | Q_PROPERTY(QVector3D kinematicPivot READ kinematicPivot WRITE setKinematicPivot NOTIFY |
79 | kinematicPivotChanged REVISION(6, 5)); |
80 | |
81 | // clang-format off |
82 | // // ??? separate simulation control object? --- some of these have default values in the engine, so we need tristate |
83 | // Q_PROPERTY(float sleepThreshold READ sleepThreshold WRITE setSleepThreshold NOTIFY sleepThresholdChanged) |
84 | // Q_PROPERTY(float stabilizationThreshold READ stabilizationThreshold WRITE setStabilizationThreshold NOTIFY stabilizationThresholdChanged) |
85 | // Q_PROPERTY(float contactReportThreshold READ contactReportThreshold WRITE setContactReportThreshold NOTIFY contactReportThresholdChanged) |
86 | // Q_PROPERTY(float maxContactImpulse READ maxContactImpulse WRITE setMaxContactImpulse NOTIFY maxContactImpulseChanged) |
87 | // Q_PROPERTY(float maxDepenetrationVelocity READ maxDepenetrationVelocity WRITE setMaxDepenetrationVelocity NOTIFY maxDepenetrationVelocityChanged) |
88 | // Q_PROPERTY(float maxAngularVelocity READ maxAngularVelocity WRITE setMaxAngularVelocity NOTIFY maxAngularVelocityChanged) |
89 | // Q_PROPERTY(int minPositionIterationCount READ minPositionIterationCount WRITE setMinPositionIterationCount NOTIFY minPositionIterationCountChanged) |
90 | // Q_PROPERTY(int minVelocityIterationCount READ minVelocityIterationCount WRITE setMinVelocityIterationCount NOTIFY minVelocityIterationCountChanged) |
91 | // clang-format on |
92 | QML_NAMED_ELEMENT(DynamicRigidBody) |
93 | |
94 | public: |
95 | QDynamicRigidBody(); |
96 | ~QDynamicRigidBody(); |
97 | |
98 | float mass() const; |
99 | void setMass(float mass); |
100 | |
101 | float density() const; |
102 | void setDensity(float density); |
103 | |
104 | bool isKinematic() const; |
105 | void setIsKinematic(bool isKinematic); |
106 | |
107 | Q_REVISION(6, 5) AxisLock linearAxisLock() const; |
108 | Q_REVISION(6, 5) void setLinearAxisLock(AxisLock newAxisLockLinear); |
109 | |
110 | Q_REVISION(6, 5) AxisLock angularAxisLock() const; |
111 | Q_REVISION(6, 5) void setAngularAxisLock(AxisLock newAxisLockAngular); |
112 | |
113 | bool gravityEnabled() const; |
114 | void setGravityEnabled(bool gravityEnabled); |
115 | |
116 | Q_INVOKABLE void applyCentralForce(const QVector3D &force); |
117 | Q_INVOKABLE void applyForce(const QVector3D &force, const QVector3D &position); |
118 | Q_INVOKABLE void applyTorque(const QVector3D &torque); |
119 | Q_INVOKABLE void applyCentralImpulse(const QVector3D &impulse); |
120 | Q_INVOKABLE void applyImpulse(const QVector3D &impulse, const QVector3D &position); |
121 | Q_INVOKABLE void applyTorqueImpulse(const QVector3D &impulse); |
122 | Q_INVOKABLE void setAngularVelocity(const QVector3D &angularVelocity); |
123 | Q_INVOKABLE void setLinearVelocity(const QVector3D &linearVelocity); |
124 | Q_INVOKABLE void reset(const QVector3D &position, const QVector3D &eulerRotation); |
125 | |
126 | // Internal |
127 | QQueue<QPhysicsCommand *> &commandQueue(); |
128 | |
129 | void updateDefaultDensity(float defaultDensity); |
130 | |
131 | MassMode massMode() const; |
132 | void setMassMode(const MassMode newMassMode); |
133 | |
134 | const QVector3D &inertiaTensor() const; |
135 | void setInertiaTensor(const QVector3D &newInertiaTensor); |
136 | |
137 | const QVector3D ¢erOfMassPosition() const; |
138 | void setCenterOfMassPosition(const QVector3D &newCenterOfMassPosition); |
139 | |
140 | const QQuaternion ¢erOfMassRotation() const; |
141 | void setCenterOfMassRotation(const QQuaternion &newCenterOfMassRotation); |
142 | |
143 | const QList<float> &readInertiaMatrix() const; |
144 | void setInertiaMatrix(const QList<float> &newInertiaMatrix); |
145 | const QMatrix3x3 &inertiaMatrix() const; |
146 | |
147 | Q_REVISION(6, 5) void setKinematicPosition(const QVector3D &position); |
148 | Q_REVISION(6, 5) QVector3D kinematicPosition() const; |
149 | |
150 | Q_REVISION(6, 5) void setKinematicRotation(const QQuaternion &rotation); |
151 | Q_REVISION(6, 5) QQuaternion kinematicRotation() const; |
152 | |
153 | Q_REVISION(6, 5) void setKinematicEulerRotation(const QVector3D &rotation); |
154 | Q_REVISION(6, 5) QVector3D kinematicEulerRotation() const; |
155 | |
156 | Q_REVISION(6, 5) void setKinematicPivot(const QVector3D &pivot); |
157 | Q_REVISION(6, 5) QVector3D kinematicPivot() const; |
158 | |
159 | QAbstractPhysXNode *createPhysXBackend() final; |
160 | |
161 | Q_SIGNALS: |
162 | void massChanged(float mass); |
163 | void densityChanged(float density); |
164 | void isKinematicChanged(bool isKinematic); |
165 | Q_REVISION(6, 5) void linearAxisLockChanged(); |
166 | Q_REVISION(6, 5) void angularAxisLockChanged(); |
167 | void gravityEnabledChanged(); |
168 | void massModeChanged(); |
169 | void inertiaTensorChanged(); |
170 | void centerOfMassPositionChanged(); |
171 | void centerOfMassRotationChanged(); |
172 | void inertiaMatrixChanged(); |
173 | Q_REVISION(6, 5) void kinematicPositionChanged(const QVector3D &kinematicPosition); |
174 | Q_REVISION(6, 5) void kinematicRotationChanged(const QQuaternion &kinematicRotation); |
175 | Q_REVISION(6, 5) void kinematicEulerRotationChanged(const QVector3D &kinematicEulerRotation); |
176 | Q_REVISION(6, 5) void kinematicPivotChanged(const QVector3D &kinematicPivot); |
177 | |
178 | private: |
179 | float m_mass = 1.f; |
180 | float m_density = 0.001f; |
181 | QVector3D m_centerOfMassPosition; |
182 | QQuaternion m_centerOfMassRotation; |
183 | QList<float> m_inertiaMatrixList; |
184 | QMatrix3x3 m_inertiaMatrix; |
185 | QVector3D m_inertiaTensor; |
186 | |
187 | bool m_isKinematic = false; |
188 | AxisLock m_linearAxisLock = AxisLock::LockNone; |
189 | AxisLock m_angularAxisLock = AxisLock::LockNone; |
190 | QQueue<QPhysicsCommand *> m_commandQueue; |
191 | bool m_gravityEnabled = true; |
192 | MassMode m_massMode = MassMode::DefaultDensity; |
193 | |
194 | QVector3D m_kinematicPosition; |
195 | RotationData m_kinematicRotation; |
196 | QVector3D m_kinematicPivot; |
197 | }; |
198 | |
199 | QT_END_NAMESPACE |
200 | |
201 | #endif // DYNAMICRIGIDBODY_H |
202 | |