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
300
301
302
303
306
307
308
309
312
313
314
315
318
319
320
321
324
325
326
327
330
331
332
333
336
337
338
339
342
343
344
345
347QDynamicRigidBody::QDynamicRigidBody() =
default;
349QDynamicRigidBody::~QDynamicRigidBody()
351 qDeleteAll(m_commandQueue);
352 m_commandQueue.clear();
355const QQuaternion &QDynamicRigidBody::centerOfMassRotation()
const
357 return m_centerOfMassRotation;
360void QDynamicRigidBody::setCenterOfMassRotation(
const QQuaternion &newCenterOfMassRotation)
362 if (!QPhysicsUtils::isFinite(newCenterOfMassRotation)) {
363 qWarning() <<
"DynamicRigidBody: centerOfMassRotation must be finite, ignoring"
364 << newCenterOfMassRotation;
368 if (qFuzzyCompare(m_centerOfMassRotation, newCenterOfMassRotation))
370 m_centerOfMassRotation = newCenterOfMassRotation;
373 if (m_massMode == MassMode::MassAndInertiaTensor)
374 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
376 emit centerOfMassRotationChanged();
379const QVector3D &QDynamicRigidBody::centerOfMassPosition()
const
381 return m_centerOfMassPosition;
384void QDynamicRigidBody::setCenterOfMassPosition(
const QVector3D &newCenterOfMassPosition)
386 if (!QPhysicsUtils::isFinite(newCenterOfMassPosition)) {
387 qWarning() <<
"DynamicRigidBody: centerOfMassPosition must be finite, ignoring"
388 << newCenterOfMassPosition;
392 if (qFuzzyCompare(m_centerOfMassPosition, newCenterOfMassPosition))
395 switch (m_massMode) {
396 case MassMode::MassAndInertiaTensor: {
397 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
400 case MassMode::MassAndInertiaMatrix: {
401 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
404 case MassMode::DefaultDensity:
405 case MassMode::CustomDensity:
410 m_centerOfMassPosition = newCenterOfMassPosition;
411 emit centerOfMassPositionChanged();
414QDynamicRigidBody::MassMode QDynamicRigidBody::massMode()
const
419void QDynamicRigidBody::setMassMode(
const MassMode newMassMode)
421 if (m_massMode == newMassMode)
424 switch (newMassMode) {
425 case MassMode::DefaultDensity: {
426 auto world = QPhysicsWorld::getWorld(
this);
428 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(world->defaultDensity()));
430 qWarning() <<
"No physics world found, cannot set default density.";
434 case MassMode::CustomDensity: {
435 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(m_density));
438 case MassMode::Mass: {
439 m_commandQueue.enqueue(
new QPhysicsCommandSetMass(m_mass));
442 case MassMode::MassAndInertiaTensor: {
443 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
446 case MassMode::MassAndInertiaMatrix: {
447 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
452 m_massMode = newMassMode;
453 emit massModeChanged();
456const QVector3D &QDynamicRigidBody::inertiaTensor()
const
458 return m_inertiaTensor;
461void QDynamicRigidBody::setInertiaTensor(
const QVector3D &newInertiaTensor)
463 if (!QPhysicsUtils::isFinite(newInertiaTensor) || newInertiaTensor.x() < 0.f
464 || newInertiaTensor.y() < 0.f || newInertiaTensor.z() < 0.f) {
465 qWarning() <<
"DynamicRigidBody: inertiaTensor" << newInertiaTensor
466 <<
"must be finite and non-negative, ignoring.";
470 if (qFuzzyCompare(m_inertiaTensor, newInertiaTensor))
472 m_inertiaTensor = newInertiaTensor;
474 if (m_massMode == MassMode::MassAndInertiaTensor)
475 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
477 emit inertiaTensorChanged();
480const QList<
float> &QDynamicRigidBody::readInertiaMatrix()
const
482 return m_inertiaMatrixList;
485static bool fuzzyEquals(
const QList<
float> &a,
const QList<
float> &b)
487 if (a.length() != b.length())
490 const int length = a.length();
491 for (
int i = 0; i < length; i++)
492 if (!qFuzzyCompare(a[i], b[i]))
498void QDynamicRigidBody::setInertiaMatrix(
const QList<
float> &newInertiaMatrix)
500 if (fuzzyEquals(m_inertiaMatrixList, newInertiaMatrix))
503 m_inertiaMatrixList = newInertiaMatrix;
504 const int elemsToCopy = qMin(m_inertiaMatrixList.length(), 9);
505 memcpy(m_inertiaMatrix.data(), m_inertiaMatrixList.data(), elemsToCopy *
sizeof(
float));
506 memset(m_inertiaMatrix.data() + elemsToCopy, 0, (9 - elemsToCopy) *
sizeof(
float));
508 if (m_massMode == MassMode::MassAndInertiaMatrix)
509 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
511 emit inertiaMatrixChanged();
514const QMatrix3x3 &QDynamicRigidBody::inertiaMatrix()
const
516 return m_inertiaMatrix;
519float QDynamicRigidBody::mass()
const
524bool QDynamicRigidBody::isKinematic()
const
526 return m_isKinematic;
529QDynamicRigidBody::CCDType QDynamicRigidBody::ccd()
const
534bool QDynamicRigidBody::gravityEnabled()
const
536 return m_gravityEnabled;
539void QDynamicRigidBody::setMass(
float mass)
541 if (!qIsFinite(mass) || mass < 0.f || qFuzzyCompare(m_mass, mass))
544 switch (m_massMode) {
545 case QDynamicRigidBody::MassMode::Mass:
546 m_commandQueue.enqueue(
new QPhysicsCommandSetMass(mass));
548 case QDynamicRigidBody::MassMode::MassAndInertiaTensor:
549 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaTensor(mass, m_inertiaTensor));
551 case QDynamicRigidBody::MassMode::MassAndInertiaMatrix:
552 m_commandQueue.enqueue(
new QPhysicsCommandSetMassAndInertiaMatrix(mass, m_inertiaMatrix));
554 case QDynamicRigidBody::MassMode::DefaultDensity:
555 case QDynamicRigidBody::MassMode::CustomDensity:
560 emit massChanged(m_mass);
563float QDynamicRigidBody::density()
const
568void QDynamicRigidBody::setDensity(
float density)
570 density = qBound(0.0000001f, density, PX_MAX_F32);
572 if (qFuzzyCompare(m_density, density))
575 if (m_massMode == MassMode::CustomDensity)
576 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(density));
579 emit densityChanged(m_density);
582void QDynamicRigidBody::setIsKinematic(
bool isKinematic)
584 if (m_isKinematic == isKinematic)
587 if (hasStaticShapes() && !isKinematic) {
589 <<
"Cannot make body containing trimesh/heightfield/plane non-kinematic, ignoring.";
593 m_isKinematic = isKinematic;
594 auto world = QPhysicsWorld::getWorld(
this);
595 m_commandQueue.enqueue(
596 new QPhysicsCommandSetIsKinematic(m_isKinematic, world && world->enableCCD()));
597 emit isKinematicChanged(m_isKinematic);
600void QDynamicRigidBody::setCCD(CCDType newCCD)
606 auto world = QPhysicsWorld::getWorld(
this);
607 m_commandQueue.enqueue(
new QPhysicsCommandSetCCD(m_CCD, world && world->enableCCD()));
611void QDynamicRigidBody::setGravityEnabled(
bool gravityEnabled)
613 if (m_gravityEnabled == gravityEnabled)
616 m_gravityEnabled = gravityEnabled;
617 m_commandQueue.enqueue(
new QPhysicsCommandSetGravityEnabled(m_gravityEnabled));
618 emit gravityEnabledChanged();
621void QDynamicRigidBody::setAngularVelocity(
const QVector3D &angularVelocity)
623 if (!QPhysicsUtils::isFinite(angularVelocity)) {
624 qWarning() <<
"DynamicRigidBody: angularVelocity must be finite, ignoring"
628 m_commandQueue.enqueue(
new QPhysicsCommandSetAngularVelocity(angularVelocity));
631QDynamicRigidBody::AxisLock QDynamicRigidBody::linearAxisLock()
const
633 return m_linearAxisLock;
636void QDynamicRigidBody::setLinearAxisLock(AxisLock newAxisLockLinear)
638 if (m_linearAxisLock == newAxisLockLinear)
640 m_linearAxisLock = newAxisLockLinear;
641 emit linearAxisLockChanged();
644QDynamicRigidBody::AxisLock QDynamicRigidBody::angularAxisLock()
const
646 return m_angularAxisLock;
649void QDynamicRigidBody::setAngularAxisLock(AxisLock newAxisLockAngular)
651 if (m_angularAxisLock == newAxisLockAngular)
653 m_angularAxisLock = newAxisLockAngular;
654 emit angularAxisLockChanged();
657QQueue<QPhysicsCommand *> &QDynamicRigidBody::commandQueue()
659 return m_commandQueue;
662void QDynamicRigidBody::updateDefaultDensity(
float defaultDensity)
664 if (m_massMode == MassMode::DefaultDensity)
665 m_commandQueue.enqueue(
new QPhysicsCommandSetDensity(defaultDensity));
668void QDynamicRigidBody::applyCentralForce(
const QVector3D &force)
670 if (!QPhysicsUtils::isFinite(force)) {
671 qWarning() <<
"DynamicRigidBody: applyCentralForce() force must be finite, ignoring"
675 m_commandQueue.enqueue(
new QPhysicsCommandApplyCentralForce(force));
678void QDynamicRigidBody::applyForce(
const QVector3D &force,
const QVector3D &position)
680 if (!QPhysicsUtils::isFinite(force) || !QPhysicsUtils::isFinite(position)) {
681 qWarning() <<
"DynamicRigidBody: applyForce() force/position must be finite, ignoring"
682 << force << position;
685 m_commandQueue.enqueue(
new QPhysicsCommandApplyForce(force, position));
688void QDynamicRigidBody::applyTorque(
const QVector3D &torque)
690 if (!QPhysicsUtils::isFinite(torque)) {
691 qWarning() <<
"DynamicRigidBody: applyTorque() torque must be finite, ignoring" << torque;
694 m_commandQueue.enqueue(
new QPhysicsCommandApplyTorque(torque));
697void QDynamicRigidBody::applyCentralImpulse(
const QVector3D &impulse)
699 if (!QPhysicsUtils::isFinite(impulse)) {
700 qWarning() <<
"DynamicRigidBody: applyCentralImpulse() impulse must be finite, ignoring"
704 m_commandQueue.enqueue(
new QPhysicsCommandApplyCentralImpulse(impulse));
707void QDynamicRigidBody::applyImpulse(
const QVector3D &impulse,
const QVector3D &position)
709 if (!QPhysicsUtils::isFinite(impulse) || !QPhysicsUtils::isFinite(position)) {
710 qWarning() <<
"DynamicRigidBody: applyImpulse() impulse/position must be finite, ignoring"
711 << impulse << position;
714 m_commandQueue.enqueue(
new QPhysicsCommandApplyImpulse(impulse, position));
717void QDynamicRigidBody::applyTorqueImpulse(
const QVector3D &impulse)
719 if (!QPhysicsUtils::isFinite(impulse)) {
720 qWarning() <<
"DynamicRigidBody: applyTorqueImpulse() impulse must be finite, ignoring"
724 m_commandQueue.enqueue(
new QPhysicsCommandApplyTorqueImpulse(impulse));
727void QDynamicRigidBody::setLinearVelocity(
const QVector3D &linearVelocity)
729 if (!QPhysicsUtils::isFinite(linearVelocity)) {
730 qWarning() <<
"DynamicRigidBody: linearVelocity must be finite, ignoring"
734 m_commandQueue.enqueue(
new QPhysicsCommandSetLinearVelocity(linearVelocity));
737void QDynamicRigidBody::reset(
const QVector3D &position,
const QVector3D &eulerRotation)
739 if (!QPhysicsUtils::isFinite(position) || !QPhysicsUtils::isFinite(eulerRotation)) {
740 qWarning() <<
"DynamicRigidBody: reset() position/eulerRotation must be finite, ignoring"
741 << position << eulerRotation;
744 m_commandQueue.enqueue(
new QPhysicsCommandReset(position, eulerRotation));
747void QDynamicRigidBody::setKinematicRotation(
const QQuaternion &rotation)
749 if (!QPhysicsUtils::isFinite(rotation)) {
750 qWarning() <<
"DynamicRigidBody: kinematicRotation must be finite, ignoring" << rotation;
753 if (m_kinematicRotation == rotation)
756 m_kinematicRotation = rotation;
757 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
758 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
761QQuaternion QDynamicRigidBody::kinematicRotation()
const
763 return m_kinematicRotation.toQuaternion();
766void QDynamicRigidBody::setKinematicEulerRotation(
const QVector3D &rotation)
768 if (!QPhysicsUtils::isFinite(rotation)) {
769 qWarning() <<
"DynamicRigidBody: kinematicEulerRotation must be finite, ignoring"
773 if (m_kinematicRotation == rotation)
776 m_kinematicRotation = rotation;
777 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
778 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
781QVector3D QDynamicRigidBody::kinematicEulerRotation()
const
783 return m_kinematicRotation.toEulerAngles();
786void QDynamicRigidBody::setKinematicPivot(
const QVector3D &pivot)
788 if (!QPhysicsUtils::isFinite(pivot)) {
789 qWarning() <<
"DynamicRigidBody: kinematicPivot must be finite, ignoring" << pivot;
793 m_kinematicPivot = pivot;
794 emit kinematicPivotChanged(m_kinematicPivot);
797QVector3D QDynamicRigidBody::kinematicPivot()
const
799 return m_kinematicPivot;
802bool QDynamicRigidBody::isSleeping()
const
807void QDynamicRigidBody::setIsSleeping(
bool newIsSleeping)
809 if (m_isSleeping == newIsSleeping)
812 m_isSleeping = newIsSleeping;
813 emit isSleepingChanged(newIsSleeping);
816QAbstractPhysXNode *QDynamicRigidBody::createPhysXBackend()
818 return new QPhysXDynamicBody(
this);
821void QDynamicRigidBody::setKinematicPosition(
const QVector3D &position)
823 if (!QPhysicsUtils::isFinite(position)) {
824 qWarning() <<
"DynamicRigidBody: kinematicPosition must be finite, ignoring" << position;
828 m_kinematicPosition = position;
829 emit kinematicPositionChanged(m_kinematicPosition);
832QVector3D QDynamicRigidBody::kinematicPosition()
const
834 return m_kinematicPosition;
static bool fuzzyEquals(const QList< float > &a, const QList< float > &b)
#define QT_BEGIN_NAMESPACE