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
qdynamicrigidbody.cpp
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
9#include "physxnode/qphysxdynamicbody_p.h"
10
11#include <foundation/PxSimpleTypes.h>
12
14
15/*!
16 \qmltype DynamicRigidBody
17 \inqmlmodule QtQuick3D.Physics
18 \inherits PhysicsBody
19 \since 6.4
20 \brief A physical body that can move or be moved.
21
22 This type defines a dynamic rigid body: an object that is part of the physics
23 scene and behaves like a physical object with mass and velocity.
24
25 \note \l{TriangleMeshShape}{triangle mesh}, \l{HeightFieldShape}{height field} and
26 \l{PlaneShape}{plane} geometry shapes are not allowed as collision shapes when
27 \l isKinematic is \c false.
28*/
29
30/*!
31 \qmlproperty real DynamicRigidBody::mass
32
33 This property defines the mass of the body. Note that this is only used when massMode is not
34 \c {DynamicRigidBody.CustomDensity} or \c {DynamicRigidBody.DefaultDensity}. Also note that
35 a value of 0 is interpreted as infinite mass and that negative numbers are not allowed.
36
37 Default value: \c 1
38
39 Range: \c{[0, inf]}
40
41 \sa massMode
42*/
43
44/*!
45 \qmlproperty real DynamicRigidBody::density
46
47 This property defines the density of the body. This is only used when massMode is set to \c
48 {DynamicRigidBody.CustomDensity}.
49
50 Default value: \c{0.001}
51
52 Range: \c{(0, inf]}
53 \sa massMode
54*/
55
56/*!
57 \qmlproperty AxisLock DynamicRigidBody::linearAxisLock
58
59 This property locks the linear velocity of the body along the axes defined by the
60 DynamicRigidBody.AxisLock enum. To lock several axes just bitwise-or their enum values.
61
62 Available options:
63
64 \value DynamicRigidBody.None
65 No axis lock.
66
67 \value DynamicRigidBody.LockX
68 Lock X axis.
69
70 \value DynamicRigidBody.LockY
71 Lock Y axis.
72
73 \value DynamicRigidBody.LockZ
74 Lock Z axis.
75
76 Default value: \c{DynamicRigidBody.None}
77*/
78
79/*!
80 \qmlproperty AxisLock DynamicRigidBody::angularAxisLock
81
82 This property locks the angular velocity of the body along the axes defined by the
83 DynamicRigidBody.AxisLock enum. To lock several axes just bitwise-or their enum values.
84
85 Available options:
86
87 \value DynamicRigidBody.None
88 No axis lock.
89
90 \value DynamicRigidBody.LockX
91 Lock X axis.
92
93 \value DynamicRigidBody.LockY
94 Lock Y axis.
95
96 \value DynamicRigidBody.LockZ
97 Lock Z axis.
98
99 Default value: \c{DynamicRigidBody.None}
100*/
101
102/*!
103 \qmlproperty enumeration DynamicRigidBody::ccd
104 \since 6.13
105
106 This property determines the continuous collision detection (CCD) mode
107 used for this body. Enabling CCD reduces the risk of fast-moving objects passing
108 through geometry between physics frames (tunnelling). The following values
109 are available:
110
111 \value DynamicRigidBody.None
112 CCD is disabled for this body unless enabled globally by \l PhysicsWorld::enableCCD.
113
114 \value DynamicRigidBody.SpeculativeCCD
115 Uses speculative continuous collision detection. Supported for both dynamic and
116 kinematic bodies.
117
118 \value DynamicRigidBody.SweepBasedCCD
119 Uses sweep-based continuous collision detection. This mode is supported only
120 for non-kinematic dynamic bodies. If applied to a kinematic body, it automatically
121 falls back to \c SpeculativeCCD.
122
123 \default DynamicRigidBody.None
124
125 \note CCD processing can significantly impact simulation performance. Enable it only for
126 objects moving at high velocities or having small bounds relative to their speed.
127
128 \sa PhysicsWorld::enableCCD
129*/
130
131/*!
132 \qmlproperty bool DynamicRigidBody::isKinematic
133 This property defines whether the object is kinematic or not. A kinematic object does not get
134 influenced by external forces and can be seen as an object of infinite mass. If this property is
135 set then in every simulation frame the physical object will be moved to its target position
136 regardless of external forces. Note that to move and rotate the kinematic object you need to use
137 the kinematicPosition, kinematicRotation, kinematicEulerRotation and kinematicPivot properties.
138
139 Default value: \c{false}
140
141 \sa kinematicPosition, kinematicRotation, kinematicEulerRotation, kinematicPivot
142*/
143
144/*!
145 \qmlproperty bool DynamicRigidBody::gravityEnabled
146 This property defines whether the object is going to be affected by gravity or not.
147
148 Default value: \c{true}
149*/
150
151/*!
152 \qmlproperty MassMode DynamicRigidBody::massMode
153
154 This property holds the enum which describes how mass and inertia are calculated for this body.
155
156 Available options:
157
158 \value DynamicRigidBody.DefaultDensity
159 Use the density specified in the \l {PhysicsWorld::}{defaultDensity} property in
160 PhysicsWorld to calculate mass and inertia assuming a uniform density.
161
162 \value DynamicRigidBody.CustomDensity
163 Use specified density in the specified in the \l {DynamicRigidBody::}{density} to
164 calculate mass and inertia assuming a uniform density.
165
166 \value DynamicRigidBody.Mass
167 Use the specified mass to calculate inertia assuming a uniform density.
168
169 \value DynamicRigidBody.MassAndInertiaTensor
170 Use the specified mass value and inertia tensor.
171
172 \value DynamicRigidBody.MassAndInertiaMatrix
173 Use the specified mass value and calculate inertia from the specified inertia
174 matrix.
175
176 Default value: \c{DynamicRigidBody.DefaultDensity}
177*/
178
179/*!
180 \qmlproperty vector3d DynamicRigidBody::inertiaTensor
181
182 Defines the inertia tensor vector, using a parameter specified in mass space coordinates.
183
184 This is the diagonal vector of a 3x3 diagonal matrix, if you have a non diagonal world/actor
185 space inertia tensor then you should use \l{DynamicRigidBody::inertiaMatrix}{inertiaMatrix}
186 instead.
187
188 The inertia tensor components must be positive and a value of 0 in any component is
189 interpreted as infinite inertia along that axis. Note that this is only used when
190 massMode is set to \c DynamicRigidBody.MassAndInertiaTensor.
191
192 Default value: \c{(1, 1, 1)}
193
194 \sa massMode, inertiaMatrix
195*/
196
197/*!
198 \qmlproperty vector3d DynamicRigidBody::centerOfMassPosition
199
200 Defines the position of the center of mass relative to the body. Note that this is only used
201 when massMode is set to \c DynamicRigidBody.MassAndInertiaTensor.
202
203 Default value: \c{(0, 0, 0)}
204
205 \sa massMode, inertiaTensor
206*/
207
208/*!
209 \qmlproperty quaternion DynamicRigidBody::centerOfMassRotation
210
211 Defines the rotation of the center of mass pose, i.e. it specifies the orientation of the body's
212 principal inertia axes relative to the body. Note that this is only used when massMode is set to
213 \c DynamicRigidBody.MassAndInertiaTensor.
214
215 Default value: \c{(1, 0, 0, 0)}
216
217 \sa massMode, inertiaTensor
218*/
219
220/*!
221 \qmlproperty list<real> DynamicRigidBody::inertiaMatrix
222
223 Defines the inertia tensor matrix. This is a 3x3 matrix in column-major order. Note that this
224 matrix is expected to be diagonalizable. Note that this is only used when massMode is set to
225 \c DynamicRigidBody.MassAndInertiaMatrix.
226
227 Default value: A 3x3 identity matrix
228
229 \sa massMode, inertiaTensor
230*/
231
232/*!
233 \qmlproperty vector3d DynamicRigidBody::kinematicPosition
234 \since 6.5
235
236 Defines the position of the object when it is kinematic, i.e. when \l isKinematic is set to \c
237 true. On each iteration of the simulation the physical object will be updated according to this
238 value.
239
240 Default value: \c{(0, 0, 0)}
241
242 \sa isKinematic, kinematicRotation, kinematicEulerRotation, kinematicPivot
243*/
244
245/*!
246 \qmlproperty quaternion DynamicRigidBody::kinematicRotation
247 \since 6.5
248
249 Defines the rotation of the object when it is kinematic, i.e. when \l isKinematic is set to \c
250 true. On each iteration of the simulation the physical object will be updated according to this
251 value.
252
253 Default value: \c{(1, 0, 0, 0)}
254
255 \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicPivot
256*/
257
258/*!
259 \qmlproperty vector3d DynamicRigidBody::kinematicEulerRotation
260 \since 6.5
261
262 Defines the euler rotation of the object when it is kinematic, i.e. when \l isKinematic is set to \c
263 true. On each iteration of the simulation the physical object will be updated according to this
264 value.
265
266 Default value: \c{(0, 0, 0)}
267
268 \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicPivot
269*/
270
271/*!
272 \qmlproperty vector3d DynamicRigidBody::kinematicPivot
273 \since 6.5
274
275 Defines the pivot of the object when it is kinematic, i.e. when \l isKinematic is set to \c
276 true. On each iteration of the simulation the physical object will be updated according to this
277 value.
278
279 Default value: \c{(0, 0, 0)}
280
281 \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicRotation
282*/
283
284/*!
285 \qmlproperty bool DynamicRigidBody::isSleeping
286 \since 6.9
287
288 Is set to \c{true} if the body is sleeping. While it is technically possible to set this property
289 it should be seen as a read-only property that is set on every frame the physics simulation is
290 running.
291*/
292
293/*!
294 \qmlmethod void DynamicRigidBody::applyCentralForce(vector3d force)
295
296 Applies a \a force on the center of the body.
297*/
298
299/*!
300 \qmlmethod void DynamicRigidBody::applyForce(vector3d force, vector3d position)
301
302 Applies a \a force at a \a position on the body.
303*/
304
305/*!
306 \qmlmethod void DynamicRigidBody::applyTorque(vector3d torque)
307
308 Applies a \a torque on the body.
309*/
310
311/*!
312 \qmlmethod void DynamicRigidBody::applyCentralImpulse(vector3d impulse)
313
314 Applies an \a impulse on the center of the body.
315*/
316
317/*!
318 \qmlmethod void DynamicRigidBody::applyImpulse(vector3d impulse, vector3d position)
319
320 Applies an \a impulse at a \a position on the body.
321*/
322
323/*!
324 \qmlmethod void DynamicRigidBody::applyTorqueImpulse(vector3d impulse)
325
326 Applies a torque \a impulse on the body.
327*/
328
329/*!
330 \qmlmethod void DynamicRigidBody::setAngularVelocity(vector3d angularVelocity)
331
332 Sets the \a angularVelocity of the body.
333*/
334
335/*!
336 \qmlmethod void DynamicRigidBody::setLinearVelocity(vector3d linearVelocity)
337
338 Sets the \a linearVelocity of the body.
339*/
340
341/*!
342 \qmlmethod void DynamicRigidBody::reset(vector3d position, vector3d eulerRotation)
343
344 Resets the body's \a position and \a eulerRotation.
345*/
346
347QDynamicRigidBody::QDynamicRigidBody() = default;
348
349QDynamicRigidBody::~QDynamicRigidBody()
350{
351 qDeleteAll(m_commandQueue);
352 m_commandQueue.clear();
353}
354
355const QQuaternion &QDynamicRigidBody::centerOfMassRotation() const
356{
357 return m_centerOfMassRotation;
358}
359
360void QDynamicRigidBody::setCenterOfMassRotation(const QQuaternion &newCenterOfMassRotation)
361{
362 if (!QPhysicsUtils::isFinite(newCenterOfMassRotation)) {
363 qWarning() << "DynamicRigidBody: centerOfMassRotation must be finite, ignoring"
364 << newCenterOfMassRotation;
365 return;
366 }
367
368 if (qFuzzyCompare(m_centerOfMassRotation, newCenterOfMassRotation))
369 return;
370 m_centerOfMassRotation = newCenterOfMassRotation;
371
372 // Only inertia tensor is using rotation
373 if (m_massMode == MassMode::MassAndInertiaTensor)
374 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
375
376 emit centerOfMassRotationChanged();
377}
378
379const QVector3D &QDynamicRigidBody::centerOfMassPosition() const
380{
381 return m_centerOfMassPosition;
382}
383
384void QDynamicRigidBody::setCenterOfMassPosition(const QVector3D &newCenterOfMassPosition)
385{
386 if (!QPhysicsUtils::isFinite(newCenterOfMassPosition)) {
387 qWarning() << "DynamicRigidBody: centerOfMassPosition must be finite, ignoring"
388 << newCenterOfMassPosition;
389 return;
390 }
391
392 if (qFuzzyCompare(m_centerOfMassPosition, newCenterOfMassPosition))
393 return;
394
395 switch (m_massMode) {
396 case MassMode::MassAndInertiaTensor: {
397 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
398 break;
399 }
400 case MassMode::MassAndInertiaMatrix: {
401 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
402 break;
403 }
404 case MassMode::DefaultDensity:
405 case MassMode::CustomDensity:
406 case MassMode::Mass:
407 break;
408 }
409
410 m_centerOfMassPosition = newCenterOfMassPosition;
411 emit centerOfMassPositionChanged();
412}
413
414QDynamicRigidBody::MassMode QDynamicRigidBody::massMode() const
415{
416 return m_massMode;
417}
418
419void QDynamicRigidBody::setMassMode(const MassMode newMassMode)
420{
421 if (m_massMode == newMassMode)
422 return;
423
424 switch (newMassMode) {
425 case MassMode::DefaultDensity: {
426 auto world = QPhysicsWorld::getWorld(this);
427 if (world) {
428 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(world->defaultDensity()));
429 } else {
430 qWarning() << "No physics world found, cannot set default density.";
431 }
432 break;
433 }
434 case MassMode::CustomDensity: {
435 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(m_density));
436 break;
437 }
438 case MassMode::Mass: {
439 m_commandQueue.enqueue(new QPhysicsCommandSetMass(m_mass));
440 break;
441 }
442 case MassMode::MassAndInertiaTensor: {
443 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
444 break;
445 }
446 case MassMode::MassAndInertiaMatrix: {
447 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
448 break;
449 }
450 }
451
452 m_massMode = newMassMode;
453 emit massModeChanged();
454}
455
456const QVector3D &QDynamicRigidBody::inertiaTensor() const
457{
458 return m_inertiaTensor;
459}
460
461void QDynamicRigidBody::setInertiaTensor(const QVector3D &newInertiaTensor)
462{
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.";
467 return;
468 }
469
470 if (qFuzzyCompare(m_inertiaTensor, newInertiaTensor))
471 return;
472 m_inertiaTensor = newInertiaTensor;
473
474 if (m_massMode == MassMode::MassAndInertiaTensor)
475 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
476
477 emit inertiaTensorChanged();
478}
479
480const QList<float> &QDynamicRigidBody::readInertiaMatrix() const
481{
482 return m_inertiaMatrixList;
483}
484
485static bool fuzzyEquals(const QList<float> &a, const QList<float> &b)
486{
487 if (a.length() != b.length())
488 return false;
489
490 const int length = a.length();
491 for (int i = 0; i < length; i++)
492 if (!qFuzzyCompare(a[i], b[i]))
493 return false;
494
495 return true;
496}
497
498void QDynamicRigidBody::setInertiaMatrix(const QList<float> &newInertiaMatrix)
499{
500 if (fuzzyEquals(m_inertiaMatrixList, newInertiaMatrix))
501 return;
502
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));
507
508 if (m_massMode == MassMode::MassAndInertiaMatrix)
509 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
510
511 emit inertiaMatrixChanged();
512}
513
514const QMatrix3x3 &QDynamicRigidBody::inertiaMatrix() const
515{
516 return m_inertiaMatrix;
517}
518
519float QDynamicRigidBody::mass() const
520{
521 return m_mass;
522}
523
524bool QDynamicRigidBody::isKinematic() const
525{
526 return m_isKinematic;
527}
528
529QDynamicRigidBody::CCDType QDynamicRigidBody::ccd() const
530{
531 return m_CCD;
532}
533
534bool QDynamicRigidBody::gravityEnabled() const
535{
536 return m_gravityEnabled;
537}
538
539void QDynamicRigidBody::setMass(float mass)
540{
541 if (!qIsFinite(mass) || mass < 0.f || qFuzzyCompare(m_mass, mass))
542 return;
543
544 switch (m_massMode) {
545 case QDynamicRigidBody::MassMode::Mass:
546 m_commandQueue.enqueue(new QPhysicsCommandSetMass(mass));
547 break;
548 case QDynamicRigidBody::MassMode::MassAndInertiaTensor:
549 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(mass, m_inertiaTensor));
550 break;
551 case QDynamicRigidBody::MassMode::MassAndInertiaMatrix:
552 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(mass, m_inertiaMatrix));
553 break;
554 case QDynamicRigidBody::MassMode::DefaultDensity:
555 case QDynamicRigidBody::MassMode::CustomDensity:
556 break;
557 }
558
559 m_mass = mass;
560 emit massChanged(m_mass);
561}
562
563float QDynamicRigidBody::density() const
564{
565 return m_density;
566}
567
568void QDynamicRigidBody::setDensity(float density)
569{
570 density = qBound(0.0000001f, density, PX_MAX_F32);
571
572 if (qFuzzyCompare(m_density, density))
573 return;
574
575 if (m_massMode == MassMode::CustomDensity)
576 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(density));
577
578 m_density = density;
579 emit densityChanged(m_density);
580}
581
582void QDynamicRigidBody::setIsKinematic(bool isKinematic)
583{
584 if (m_isKinematic == isKinematic)
585 return;
586
587 if (hasStaticShapes() && !isKinematic) {
588 qWarning()
589 << "Cannot make body containing trimesh/heightfield/plane non-kinematic, ignoring.";
590 return;
591 }
592
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);
598}
599
600void QDynamicRigidBody::setCCD(CCDType newCCD)
601{
602 if (m_CCD == newCCD)
603 return;
604
605 m_CCD = newCCD;
606 auto world = QPhysicsWorld::getWorld(this);
607 m_commandQueue.enqueue(new QPhysicsCommandSetCCD(m_CCD, world && world->enableCCD()));
608 emit ccdChanged();
609}
610
611void QDynamicRigidBody::setGravityEnabled(bool gravityEnabled)
612{
613 if (m_gravityEnabled == gravityEnabled)
614 return;
615
616 m_gravityEnabled = gravityEnabled;
617 m_commandQueue.enqueue(new QPhysicsCommandSetGravityEnabled(m_gravityEnabled));
618 emit gravityEnabledChanged();
619}
620
621void QDynamicRigidBody::setAngularVelocity(const QVector3D &angularVelocity)
622{
623 if (!QPhysicsUtils::isFinite(angularVelocity)) {
624 qWarning() << "DynamicRigidBody: angularVelocity must be finite, ignoring"
625 << angularVelocity;
626 return;
627 }
628 m_commandQueue.enqueue(new QPhysicsCommandSetAngularVelocity(angularVelocity));
629}
630
631QDynamicRigidBody::AxisLock QDynamicRigidBody::linearAxisLock() const
632{
633 return m_linearAxisLock;
634}
635
636void QDynamicRigidBody::setLinearAxisLock(AxisLock newAxisLockLinear)
637{
638 if (m_linearAxisLock == newAxisLockLinear)
639 return;
640 m_linearAxisLock = newAxisLockLinear;
641 emit linearAxisLockChanged();
642}
643
644QDynamicRigidBody::AxisLock QDynamicRigidBody::angularAxisLock() const
645{
646 return m_angularAxisLock;
647}
648
649void QDynamicRigidBody::setAngularAxisLock(AxisLock newAxisLockAngular)
650{
651 if (m_angularAxisLock == newAxisLockAngular)
652 return;
653 m_angularAxisLock = newAxisLockAngular;
654 emit angularAxisLockChanged();
655}
656
657QQueue<QPhysicsCommand *> &QDynamicRigidBody::commandQueue()
658{
659 return m_commandQueue;
660}
661
662void QDynamicRigidBody::updateDefaultDensity(float defaultDensity)
663{
664 if (m_massMode == MassMode::DefaultDensity)
665 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(defaultDensity));
666}
667
668void QDynamicRigidBody::applyCentralForce(const QVector3D &force)
669{
670 if (!QPhysicsUtils::isFinite(force)) {
671 qWarning() << "DynamicRigidBody: applyCentralForce() force must be finite, ignoring"
672 << force;
673 return;
674 }
675 m_commandQueue.enqueue(new QPhysicsCommandApplyCentralForce(force));
676}
677
678void QDynamicRigidBody::applyForce(const QVector3D &force, const QVector3D &position)
679{
680 if (!QPhysicsUtils::isFinite(force) || !QPhysicsUtils::isFinite(position)) {
681 qWarning() << "DynamicRigidBody: applyForce() force/position must be finite, ignoring"
682 << force << position;
683 return;
684 }
685 m_commandQueue.enqueue(new QPhysicsCommandApplyForce(force, position));
686}
687
688void QDynamicRigidBody::applyTorque(const QVector3D &torque)
689{
690 if (!QPhysicsUtils::isFinite(torque)) {
691 qWarning() << "DynamicRigidBody: applyTorque() torque must be finite, ignoring" << torque;
692 return;
693 }
694 m_commandQueue.enqueue(new QPhysicsCommandApplyTorque(torque));
695}
696
697void QDynamicRigidBody::applyCentralImpulse(const QVector3D &impulse)
698{
699 if (!QPhysicsUtils::isFinite(impulse)) {
700 qWarning() << "DynamicRigidBody: applyCentralImpulse() impulse must be finite, ignoring"
701 << impulse;
702 return;
703 }
704 m_commandQueue.enqueue(new QPhysicsCommandApplyCentralImpulse(impulse));
705}
706
707void QDynamicRigidBody::applyImpulse(const QVector3D &impulse, const QVector3D &position)
708{
709 if (!QPhysicsUtils::isFinite(impulse) || !QPhysicsUtils::isFinite(position)) {
710 qWarning() << "DynamicRigidBody: applyImpulse() impulse/position must be finite, ignoring"
711 << impulse << position;
712 return;
713 }
714 m_commandQueue.enqueue(new QPhysicsCommandApplyImpulse(impulse, position));
715}
716
717void QDynamicRigidBody::applyTorqueImpulse(const QVector3D &impulse)
718{
719 if (!QPhysicsUtils::isFinite(impulse)) {
720 qWarning() << "DynamicRigidBody: applyTorqueImpulse() impulse must be finite, ignoring"
721 << impulse;
722 return;
723 }
724 m_commandQueue.enqueue(new QPhysicsCommandApplyTorqueImpulse(impulse));
725}
726
727void QDynamicRigidBody::setLinearVelocity(const QVector3D &linearVelocity)
728{
729 if (!QPhysicsUtils::isFinite(linearVelocity)) {
730 qWarning() << "DynamicRigidBody: linearVelocity must be finite, ignoring"
731 << linearVelocity;
732 return;
733 }
734 m_commandQueue.enqueue(new QPhysicsCommandSetLinearVelocity(linearVelocity));
735}
736
737void QDynamicRigidBody::reset(const QVector3D &position, const QVector3D &eulerRotation)
738{
739 if (!QPhysicsUtils::isFinite(position) || !QPhysicsUtils::isFinite(eulerRotation)) {
740 qWarning() << "DynamicRigidBody: reset() position/eulerRotation must be finite, ignoring"
741 << position << eulerRotation;
742 return;
743 }
744 m_commandQueue.enqueue(new QPhysicsCommandReset(position, eulerRotation));
745}
746
747void QDynamicRigidBody::setKinematicRotation(const QQuaternion &rotation)
748{
749 if (!QPhysicsUtils::isFinite(rotation)) {
750 qWarning() << "DynamicRigidBody: kinematicRotation must be finite, ignoring" << rotation;
751 return;
752 }
753 if (m_kinematicRotation == rotation)
754 return;
755
756 m_kinematicRotation = rotation;
757 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
758 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
759}
760
761QQuaternion QDynamicRigidBody::kinematicRotation() const
762{
763 return m_kinematicRotation.toQuaternion();
764}
765
766void QDynamicRigidBody::setKinematicEulerRotation(const QVector3D &rotation)
767{
768 if (!QPhysicsUtils::isFinite(rotation)) {
769 qWarning() << "DynamicRigidBody: kinematicEulerRotation must be finite, ignoring"
770 << rotation;
771 return;
772 }
773 if (m_kinematicRotation == rotation)
774 return;
775
776 m_kinematicRotation = rotation;
777 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
778 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
779}
780
781QVector3D QDynamicRigidBody::kinematicEulerRotation() const
782{
783 return m_kinematicRotation.toEulerAngles();
784}
785
786void QDynamicRigidBody::setKinematicPivot(const QVector3D &pivot)
787{
788 if (!QPhysicsUtils::isFinite(pivot)) {
789 qWarning() << "DynamicRigidBody: kinematicPivot must be finite, ignoring" << pivot;
790 return;
791 }
792
793 m_kinematicPivot = pivot;
794 emit kinematicPivotChanged(m_kinematicPivot);
795}
796
797QVector3D QDynamicRigidBody::kinematicPivot() const
798{
799 return m_kinematicPivot;
800}
801
802bool QDynamicRigidBody::isSleeping() const
803{
804 return m_isSleeping;
805}
806
807void QDynamicRigidBody::setIsSleeping(bool newIsSleeping)
808{
809 if (m_isSleeping == newIsSleeping)
810 return;
811
812 m_isSleeping = newIsSleeping;
813 emit isSleepingChanged(newIsSleeping);
814}
815
816QAbstractPhysXNode *QDynamicRigidBody::createPhysXBackend()
817{
818 return new QPhysXDynamicBody(this);
819}
820
821void QDynamicRigidBody::setKinematicPosition(const QVector3D &position)
822{
823 if (!QPhysicsUtils::isFinite(position)) {
824 qWarning() << "DynamicRigidBody: kinematicPosition must be finite, ignoring" << position;
825 return;
826 }
827
828 m_kinematicPosition = position;
829 emit kinematicPositionChanged(m_kinematicPosition);
830}
831
832QVector3D QDynamicRigidBody::kinematicPosition() const
833{
834 return m_kinematicPosition;
835}
836
static bool fuzzyEquals(const QList< float > &a, const QList< float > &b)
#define QT_BEGIN_NAMESPACE
#define QT_END_NAMESPACE