9#include "physxnode/qphysxdynamicbody_p.h"
11#include <foundation/PxSimpleTypes.h>
16
17
18
19
20
21
22
23
24
25
26
27
28
31
32
33
34
35
36
37
38
39
40
41
42
45
46
47
48
49
50
51
52
53
54
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
132
133
134
135
136
137
138
139
140
141
142
145
146
147
148
149
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
198
199
200
201
202
203
204
205
206
209
210
211
212
213
214
215
216
217
218
221
222
223
224
225
226
227
228
229
230
233
234
235
236
237
238
239
240
241
242
243
246
247
248
249
250
251
252
253
254
255
256
259
260
261
262
263
264
265
266
267
268
269
272
273
274
275
276
277
278
279
280
281
282
285
286
287
288
289
290
291
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
339
340
341
342
345
346
347
348
351
352
353
354
357
358
359
360
363
364
365
366
369
370
371
372
375
376
377
378
379
380
383
384
385
386
387
388
391
392
393
394
396QDynamicRigidBody::QDynamicRigidBody() =
default;
398QDynamicRigidBody::~QDynamicRigidBody()
400 qDeleteAll(m_commandQueue);
401 m_commandQueue.clear();
404const QQuaternion &QDynamicRigidBody::centerOfMassRotation()
const
406 return m_centerOfMassRotation;
409void QDynamicRigidBody::setCenterOfMassRotation(
const QQuaternion &newCenterOfMassRotation)
411 if (!QPhysicsUtils::isFinite(newCenterOfMassRotation)) {
412 qWarning() <<
"DynamicRigidBody: centerOfMassRotation must be finite, ignoring"
413 << newCenterOfMassRotation;
417 if (qFuzzyCompare(m_centerOfMassRotation, newCenterOfMassRotation))
419 m_centerOfMassRotation = newCenterOfMassRotation;
422 if (m_massMode == MassMode::MassAndInertiaTensor)
423 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
425 emit centerOfMassRotationChanged();
428const QVector3D &QDynamicRigidBody::centerOfMassPosition()
const
430 return m_centerOfMassPosition;
433void QDynamicRigidBody::setCenterOfMassPosition(
const QVector3D &newCenterOfMassPosition)
435 if (!QPhysicsUtils::isFinite(newCenterOfMassPosition)) {
436 qWarning() <<
"DynamicRigidBody: centerOfMassPosition must be finite, ignoring"
437 << newCenterOfMassPosition;
441 if (qFuzzyCompare(m_centerOfMassPosition, newCenterOfMassPosition))
444 switch (m_massMode) {
445 case MassMode::MassAndInertiaTensor: {
446 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
449 case MassMode::MassAndInertiaMatrix: {
450 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
453 case MassMode::DefaultDensity:
454 case MassMode::CustomDensity:
459 m_centerOfMassPosition = newCenterOfMassPosition;
460 emit centerOfMassPositionChanged();
463QDynamicRigidBody::MassMode QDynamicRigidBody::massMode()
const
468void QDynamicRigidBody::setMassMode(
const MassMode newMassMode)
470 if (m_massMode == newMassMode)
473 switch (newMassMode) {
474 case MassMode::DefaultDensity: {
475 auto world = QPhysicsWorld::getWorld(
this);
477 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(world->defaultDensity()));
479 qWarning() <<
"No physics world found, cannot set default density.";
483 case MassMode::CustomDensity: {
484 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(m_density));
487 case MassMode::Mass: {
488 m_commandQueue.enqueue(
new QPhysicsCommandSetMass(m_mass));
491 case MassMode::MassAndInertiaTensor: {
492 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
495 case MassMode::MassAndInertiaMatrix: {
496 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
501 m_massMode = newMassMode;
502 emit massModeChanged();
505const QVector3D &QDynamicRigidBody::inertiaTensor()
const
507 return m_inertiaTensor;
510void QDynamicRigidBody::setInertiaTensor(
const QVector3D &newInertiaTensor)
512 if (!QPhysicsUtils::isFinite(newInertiaTensor) || newInertiaTensor.x() < 0.f
513 || newInertiaTensor.y() < 0.f || newInertiaTensor.z() < 0.f) {
514 qWarning() <<
"DynamicRigidBody: inertiaTensor" << newInertiaTensor
515 <<
"must be finite and non-negative, ignoring.";
519 if (qFuzzyCompare(m_inertiaTensor, newInertiaTensor))
521 m_inertiaTensor = newInertiaTensor;
523 if (m_massMode == MassMode::MassAndInertiaTensor)
524 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
526 emit inertiaTensorChanged();
529const QList<
float> &QDynamicRigidBody::readInertiaMatrix()
const
531 return m_inertiaMatrixList;
534static bool fuzzyEquals(
const QList<
float> &a,
const QList<
float> &b)
536 if (a.length() != b.length())
539 const int length = a.length();
540 for (
int i = 0; i < length; i++)
541 if (!qFuzzyCompare(a[i], b[i]))
547void QDynamicRigidBody::setInertiaMatrix(
const QList<
float> &newInertiaMatrix)
549 if (fuzzyEquals(m_inertiaMatrixList, newInertiaMatrix))
552 m_inertiaMatrixList = newInertiaMatrix;
553 const int elemsToCopy = qMin(m_inertiaMatrixList.length(), 9);
554 memcpy(m_inertiaMatrix.data(), m_inertiaMatrixList.data(), elemsToCopy *
sizeof(
float));
555 memset(m_inertiaMatrix.data() + elemsToCopy, 0, (9 - elemsToCopy) *
sizeof(
float));
557 if (m_massMode == MassMode::MassAndInertiaMatrix)
558 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
560 emit inertiaMatrixChanged();
563const QMatrix3x3 &QDynamicRigidBody::inertiaMatrix()
const
565 return m_inertiaMatrix;
568float QDynamicRigidBody::mass()
const
573bool QDynamicRigidBody::isKinematic()
const
575 return m_isKinematic;
578QDynamicRigidBody::CCDType QDynamicRigidBody::ccd()
const
583bool QDynamicRigidBody::gravityEnabled()
const
585 return m_gravityEnabled;
588void QDynamicRigidBody::setMass(
float mass)
590 if (!qIsFinite(mass) || mass < 0.f || qFuzzyCompare(m_mass, mass))
593 switch (m_massMode) {
594 case QDynamicRigidBody::MassMode::Mass:
595 m_commandQueue.enqueue(
new QPhysicsCommandSetMass(mass));
597 case QDynamicRigidBody::MassMode::MassAndInertiaTensor:
598 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(mass, m_inertiaTensor));
600 case QDynamicRigidBody::MassMode::MassAndInertiaMatrix:
601 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(mass, m_inertiaMatrix));
603 case QDynamicRigidBody::MassMode::DefaultDensity:
604 case QDynamicRigidBody::MassMode::CustomDensity:
609 emit massChanged(m_mass);
612float QDynamicRigidBody::density()
const
617void QDynamicRigidBody::setDensity(
float density)
619 density = qBound(0.0000001f, density, PX_MAX_F32);
621 if (qFuzzyCompare(m_density, density))
624 if (m_massMode == MassMode::CustomDensity)
625 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(density));
628 emit densityChanged(m_density);
631void QDynamicRigidBody::setIsKinematic(
bool isKinematic)
633 if (m_isKinematic == isKinematic)
636 if (hasStaticShapes() && !isKinematic) {
638 <<
"Cannot make body containing trimesh/heightfield/plane non-kinematic, ignoring.";
642 m_isKinematic = isKinematic;
643 auto world = QPhysicsWorld::getWorld(
this);
644 m_commandQueue.enqueue(
645 new QPhysicsCommandSetIsKinematic(m_isKinematic, world && world->enableCCD()));
646 emit isKinematicChanged(m_isKinematic);
649void QDynamicRigidBody::setCCD(CCDType newCCD)
655 auto world = QPhysicsWorld::getWorld(
this);
656 m_commandQueue.enqueue(
new QPhysicsCommandSetCCD(m_CCD, world && world->enableCCD()));
660void QDynamicRigidBody::setGravityEnabled(
bool gravityEnabled)
662 if (m_gravityEnabled == gravityEnabled)
665 m_gravityEnabled = gravityEnabled;
666 m_commandQueue.enqueue(
new QPhysicsCommandSetGravityEnabled(m_gravityEnabled));
667 emit gravityEnabledChanged();
670void QDynamicRigidBody::setAngularVelocity(
const QVector3D &angularVelocity)
672 if (!QPhysicsUtils::isFinite(angularVelocity)) {
673 qWarning() <<
"DynamicRigidBody: angularVelocity must be finite, ignoring"
677 m_commandQueue.enqueue(
new QPhysicsCommandSetAngularVelocity(angularVelocity));
680QDynamicRigidBody::AxisLock QDynamicRigidBody::linearAxisLock()
const
682 return m_linearAxisLock;
685void QDynamicRigidBody::setLinearAxisLock(AxisLock newAxisLockLinear)
687 if (m_linearAxisLock == newAxisLockLinear)
689 m_linearAxisLock = newAxisLockLinear;
690 emit linearAxisLockChanged();
693QDynamicRigidBody::AxisLock QDynamicRigidBody::angularAxisLock()
const
695 return m_angularAxisLock;
698void QDynamicRigidBody::setAngularAxisLock(AxisLock newAxisLockAngular)
700 if (m_angularAxisLock == newAxisLockAngular)
702 m_angularAxisLock = newAxisLockAngular;
703 emit angularAxisLockChanged();
706QQueue<QPhysicsCommand *> &QDynamicRigidBody::commandQueue()
708 return m_commandQueue;
711void QDynamicRigidBody::updateDefaultDensity(
float defaultDensity)
713 if (m_massMode == MassMode::DefaultDensity)
714 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(defaultDensity));
717void QDynamicRigidBody::applyCentralForce(
const QVector3D &force)
719 if (!QPhysicsUtils::isFinite(force)) {
720 qWarning() <<
"DynamicRigidBody: applyCentralForce() force must be finite, ignoring"
724 m_commandQueue.enqueue(
new QPhysicsCommandApplyCentralForce(force));
727void QDynamicRigidBody::applyForce(
const QVector3D &force,
const QVector3D &position)
729 if (!QPhysicsUtils::isFinite(force) || !QPhysicsUtils::isFinite(position)) {
730 qWarning() <<
"DynamicRigidBody: applyForce() force/position must be finite, ignoring"
731 << force << position;
734 m_commandQueue.enqueue(
new QPhysicsCommandApplyForce(force, position));
737void QDynamicRigidBody::applyTorque(
const QVector3D &torque)
739 if (!QPhysicsUtils::isFinite(torque)) {
740 qWarning() <<
"DynamicRigidBody: applyTorque() torque must be finite, ignoring" << torque;
743 m_commandQueue.enqueue(
new QPhysicsCommandApplyTorque(torque));
746void QDynamicRigidBody::applyCentralImpulse(
const QVector3D &impulse)
748 if (!QPhysicsUtils::isFinite(impulse)) {
749 qWarning() <<
"DynamicRigidBody: applyCentralImpulse() impulse must be finite, ignoring"
753 m_commandQueue.enqueue(
new QPhysicsCommandApplyCentralImpulse(impulse));
756void QDynamicRigidBody::applyImpulse(
const QVector3D &impulse,
const QVector3D &position)
758 if (!QPhysicsUtils::isFinite(impulse) || !QPhysicsUtils::isFinite(position)) {
759 qWarning() <<
"DynamicRigidBody: applyImpulse() impulse/position must be finite, ignoring"
760 << impulse << position;
763 m_commandQueue.enqueue(
new QPhysicsCommandApplyImpulse(impulse, position));
766void QDynamicRigidBody::applyTorqueImpulse(
const QVector3D &impulse)
768 if (!QPhysicsUtils::isFinite(impulse)) {
769 qWarning() <<
"DynamicRigidBody: applyTorqueImpulse() impulse must be finite, ignoring"
773 m_commandQueue.enqueue(
new QPhysicsCommandApplyTorqueImpulse(impulse));
776void QDynamicRigidBody::setLinearVelocity(
const QVector3D &linearVelocity)
778 if (!QPhysicsUtils::isFinite(linearVelocity)) {
779 qWarning() <<
"DynamicRigidBody: linearVelocity must be finite, ignoring"
783 m_commandQueue.enqueue(
new QPhysicsCommandSetLinearVelocity(linearVelocity));
786void QDynamicRigidBody::reset(
const QVector3D &position,
const QVector3D &eulerRotation)
788 if (!QPhysicsUtils::isFinite(position) || !QPhysicsUtils::isFinite(eulerRotation)) {
789 qWarning() <<
"DynamicRigidBody: reset() position/eulerRotation must be finite, ignoring"
790 << position << eulerRotation;
793 m_commandQueue.enqueue(
new QPhysicsCommandReset(position, eulerRotation));
796void QDynamicRigidBody::setKinematicRotation(
const QQuaternion &rotation)
798 if (!QPhysicsUtils::isFinite(rotation)) {
799 qWarning() <<
"DynamicRigidBody: kinematicRotation must be finite, ignoring" << rotation;
802 if (m_kinematicRotation == rotation)
805 m_kinematicRotation = rotation;
806 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
807 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
810QQuaternion QDynamicRigidBody::kinematicRotation()
const
812 return m_kinematicRotation.toQuaternion();
815void QDynamicRigidBody::setKinematicEulerRotation(
const QVector3D &rotation)
817 if (!QPhysicsUtils::isFinite(rotation)) {
818 qWarning() <<
"DynamicRigidBody: kinematicEulerRotation must be finite, ignoring"
822 if (m_kinematicRotation == rotation)
825 m_kinematicRotation = rotation;
826 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
827 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
830QVector3D QDynamicRigidBody::kinematicEulerRotation()
const
832 return m_kinematicRotation.toEulerAngles();
835void QDynamicRigidBody::setKinematicPivot(
const QVector3D &pivot)
837 if (!QPhysicsUtils::isFinite(pivot)) {
838 qWarning() <<
"DynamicRigidBody: kinematicPivot must be finite, ignoring" << pivot;
842 m_kinematicPivot = pivot;
843 emit kinematicPivotChanged(m_kinematicPivot);
846QVector3D QDynamicRigidBody::kinematicPivot()
const
848 return m_kinematicPivot;
851bool QDynamicRigidBody::isSleeping()
const
856QVector3D QDynamicRigidBody::linearVelocity()
const
858 return m_linearVelocity;
861QVector3D QDynamicRigidBody::angularVelocity()
const
863 return m_angularVelocity;
866void QDynamicRigidBody::updateLinearVelocity(
const QVector3D &velocity)
868 if (m_linearVelocity == velocity)
870 m_linearVelocity = velocity;
871 emit linearVelocityChanged(m_linearVelocity);
874void QDynamicRigidBody::updateAngularVelocity(
const QVector3D &velocity)
876 if (m_angularVelocity == velocity)
878 m_angularVelocity = velocity;
879 emit angularVelocityChanged(m_angularVelocity);
882void QDynamicRigidBody::setIsSleeping(
bool newIsSleeping)
884 if (m_isSleeping == newIsSleeping)
887 m_isSleeping = newIsSleeping;
888 emit isSleepingChanged(newIsSleeping);
891QAbstractPhysXNode *QDynamicRigidBody::createPhysXBackend()
893 return new QPhysXDynamicBody(
this);
896void QDynamicRigidBody::setKinematicPosition(
const QVector3D &position)
898 if (!QPhysicsUtils::isFinite(position)) {
899 qWarning() <<
"DynamicRigidBody: kinematicPosition must be finite, ignoring" << position;
903 m_kinematicPosition = position;
904 emit kinematicPositionChanged(m_kinematicPosition);
907QVector3D QDynamicRigidBody::kinematicPosition()
const
909 return m_kinematicPosition;
static bool fuzzyEquals(const QList< float > &a, const QList< float > &b)
#define QT_BEGIN_NAMESPACE