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 \qmlproperty vector3d DynamicRigidBody::linearVelocity
295 \readonly
296 \since 6.13
297
298 The linear velocity of the body in scene units per second. The value is updated after each
299 physics frame, making the simulated velocity directly available to physics calculations in
300 QML.
301
302 The value is computed by the simulation, so it changes in response to gravity, contacts and
303 joints as well as to any applied force or impulse.
304 \l setLinearVelocity() overrides it directly, but like the other imperative calls it is
305 queued and applied on the next physics frame, so this property keeps its old value
306 until then.
307
308 For a kinematic body this is the velocity implied by its kinematic target. It is zero
309 while the body is sleeping, and a body whose \l {PhysicsBody::}{simulationEnabled} is
310 \c false counts as sleeping.
311
312 \sa setLinearVelocity(), applyCentralForce(), applyCentralImpulse(), angularVelocity
313*/
314
315/*!
316 \qmlproperty vector3d DynamicRigidBody::angularVelocity
317 \readonly
318 \since 6.13
319
320 The angular velocity of the body in radians per second. The value is updated after each
321 physics frame, making the simulated velocity directly available to physics calculations
322 in QML.
323
324 The value is computed by the simulation, so it changes in response to contacts, joints
325 and damping as well as to any applied torque or impulse.
326 \l setAngularVelocity() overrides it directly, but like the other imperative calls it
327 is queued and applied on the next physics frame, so this property keeps its old value
328 until then. Note that the underlying engine damps angular motion by default, so a
329 freely spinning body slows down even without contacts.
330
331 For a kinematic body this is the velocity implied by its kinematic target. It is zero
332 while the body is sleeping, and a body whose \l {PhysicsBody::}{simulationEnabled} is
333 \c false counts as sleeping.
334
335 \sa setAngularVelocity(), applyTorque(), applyTorqueImpulse(), linearVelocity
336*/
337
338/*!
339 \qmlmethod void DynamicRigidBody::applyCentralForce(vector3d force)
340
341 Applies a \a force on the center of the body.
342*/
343
344/*!
345 \qmlmethod void DynamicRigidBody::applyForce(vector3d force, vector3d position)
346
347 Applies a \a force at a \a position on the body.
348*/
349
350/*!
351 \qmlmethod void DynamicRigidBody::applyTorque(vector3d torque)
352
353 Applies a \a torque on the body.
354*/
355
356/*!
357 \qmlmethod void DynamicRigidBody::applyCentralImpulse(vector3d impulse)
358
359 Applies an \a impulse on the center of the body.
360*/
361
362/*!
363 \qmlmethod void DynamicRigidBody::applyImpulse(vector3d impulse, vector3d position)
364
365 Applies an \a impulse at a \a position on the body.
366*/
367
368/*!
369 \qmlmethod void DynamicRigidBody::applyTorqueImpulse(vector3d impulse)
370
371 Applies a torque \a impulse on the body.
372*/
373
374/*!
375 \qmlmethod void DynamicRigidBody::setAngularVelocity(vector3d angularVelocity)
376
377 Sets the \a angularVelocity of the body.
378
379 \sa angularVelocity
380*/
381
382/*!
383 \qmlmethod void DynamicRigidBody::setLinearVelocity(vector3d linearVelocity)
384
385 Sets the \a linearVelocity of the body.
386
387 \sa linearVelocity
388*/
389
390/*!
391 \qmlmethod void DynamicRigidBody::reset(vector3d position, vector3d eulerRotation)
392
393 Resets the body's \a position and \a eulerRotation.
394*/
395
396QDynamicRigidBody::QDynamicRigidBody() = default;
397
398QDynamicRigidBody::~QDynamicRigidBody()
399{
400 qDeleteAll(m_commandQueue);
401 m_commandQueue.clear();
402}
403
404const QQuaternion &QDynamicRigidBody::centerOfMassRotation() const
405{
406 return m_centerOfMassRotation;
407}
408
409void QDynamicRigidBody::setCenterOfMassRotation(const QQuaternion &newCenterOfMassRotation)
410{
411 if (!QPhysicsUtils::isFinite(newCenterOfMassRotation)) {
412 qWarning() << "DynamicRigidBody: centerOfMassRotation must be finite, ignoring"
413 << newCenterOfMassRotation;
414 return;
415 }
416
417 if (qFuzzyCompare(m_centerOfMassRotation, newCenterOfMassRotation))
418 return;
419 m_centerOfMassRotation = newCenterOfMassRotation;
420
421 // Only inertia tensor is using rotation
422 if (m_massMode == MassMode::MassAndInertiaTensor)
423 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
424
425 emit centerOfMassRotationChanged();
426}
427
428const QVector3D &QDynamicRigidBody::centerOfMassPosition() const
429{
430 return m_centerOfMassPosition;
431}
432
433void QDynamicRigidBody::setCenterOfMassPosition(const QVector3D &newCenterOfMassPosition)
434{
435 if (!QPhysicsUtils::isFinite(newCenterOfMassPosition)) {
436 qWarning() << "DynamicRigidBody: centerOfMassPosition must be finite, ignoring"
437 << newCenterOfMassPosition;
438 return;
439 }
440
441 if (qFuzzyCompare(m_centerOfMassPosition, newCenterOfMassPosition))
442 return;
443
444 switch (m_massMode) {
445 case MassMode::MassAndInertiaTensor: {
446 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
447 break;
448 }
449 case MassMode::MassAndInertiaMatrix: {
450 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
451 break;
452 }
453 case MassMode::DefaultDensity:
454 case MassMode::CustomDensity:
455 case MassMode::Mass:
456 break;
457 }
458
459 m_centerOfMassPosition = newCenterOfMassPosition;
460 emit centerOfMassPositionChanged();
461}
462
463QDynamicRigidBody::MassMode QDynamicRigidBody::massMode() const
464{
465 return m_massMode;
466}
467
468void QDynamicRigidBody::setMassMode(const MassMode newMassMode)
469{
470 if (m_massMode == newMassMode)
471 return;
472
473 switch (newMassMode) {
474 case MassMode::DefaultDensity: {
475 auto world = QPhysicsWorld::getWorld(this);
476 if (world) {
477 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(world->defaultDensity()));
478 } else {
479 qWarning() << "No physics world found, cannot set default density.";
480 }
481 break;
482 }
483 case MassMode::CustomDensity: {
484 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(m_density));
485 break;
486 }
487 case MassMode::Mass: {
488 m_commandQueue.enqueue(new QPhysicsCommandSetMass(m_mass));
489 break;
490 }
491 case MassMode::MassAndInertiaTensor: {
492 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
493 break;
494 }
495 case MassMode::MassAndInertiaMatrix: {
496 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
497 break;
498 }
499 }
500
501 m_massMode = newMassMode;
502 emit massModeChanged();
503}
504
505const QVector3D &QDynamicRigidBody::inertiaTensor() const
506{
507 return m_inertiaTensor;
508}
509
510void QDynamicRigidBody::setInertiaTensor(const QVector3D &newInertiaTensor)
511{
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.";
516 return;
517 }
518
519 if (qFuzzyCompare(m_inertiaTensor, newInertiaTensor))
520 return;
521 m_inertiaTensor = newInertiaTensor;
522
523 if (m_massMode == MassMode::MassAndInertiaTensor)
524 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
525
526 emit inertiaTensorChanged();
527}
528
529const QList<float> &QDynamicRigidBody::readInertiaMatrix() const
530{
531 return m_inertiaMatrixList;
532}
533
534static bool fuzzyEquals(const QList<float> &a, const QList<float> &b)
535{
536 if (a.length() != b.length())
537 return false;
538
539 const int length = a.length();
540 for (int i = 0; i < length; i++)
541 if (!qFuzzyCompare(a[i], b[i]))
542 return false;
543
544 return true;
545}
546
547void QDynamicRigidBody::setInertiaMatrix(const QList<float> &newInertiaMatrix)
548{
549 if (fuzzyEquals(m_inertiaMatrixList, newInertiaMatrix))
550 return;
551
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));
556
557 if (m_massMode == MassMode::MassAndInertiaMatrix)
558 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
559
560 emit inertiaMatrixChanged();
561}
562
563const QMatrix3x3 &QDynamicRigidBody::inertiaMatrix() const
564{
565 return m_inertiaMatrix;
566}
567
568float QDynamicRigidBody::mass() const
569{
570 return m_mass;
571}
572
573bool QDynamicRigidBody::isKinematic() const
574{
575 return m_isKinematic;
576}
577
578QDynamicRigidBody::CCDType QDynamicRigidBody::ccd() const
579{
580 return m_CCD;
581}
582
583bool QDynamicRigidBody::gravityEnabled() const
584{
585 return m_gravityEnabled;
586}
587
588void QDynamicRigidBody::setMass(float mass)
589{
590 if (!qIsFinite(mass) || mass < 0.f || qFuzzyCompare(m_mass, mass))
591 return;
592
593 switch (m_massMode) {
594 case QDynamicRigidBody::MassMode::Mass:
595 m_commandQueue.enqueue(new QPhysicsCommandSetMass(mass));
596 break;
597 case QDynamicRigidBody::MassMode::MassAndInertiaTensor:
598 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(mass, m_inertiaTensor));
599 break;
600 case QDynamicRigidBody::MassMode::MassAndInertiaMatrix:
601 m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(mass, m_inertiaMatrix));
602 break;
603 case QDynamicRigidBody::MassMode::DefaultDensity:
604 case QDynamicRigidBody::MassMode::CustomDensity:
605 break;
606 }
607
608 m_mass = mass;
609 emit massChanged(m_mass);
610}
611
612float QDynamicRigidBody::density() const
613{
614 return m_density;
615}
616
617void QDynamicRigidBody::setDensity(float density)
618{
619 density = qBound(0.0000001f, density, PX_MAX_F32);
620
621 if (qFuzzyCompare(m_density, density))
622 return;
623
624 if (m_massMode == MassMode::CustomDensity)
625 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(density));
626
627 m_density = density;
628 emit densityChanged(m_density);
629}
630
631void QDynamicRigidBody::setIsKinematic(bool isKinematic)
632{
633 if (m_isKinematic == isKinematic)
634 return;
635
636 if (hasStaticShapes() && !isKinematic) {
637 qWarning()
638 << "Cannot make body containing trimesh/heightfield/plane non-kinematic, ignoring.";
639 return;
640 }
641
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);
647}
648
649void QDynamicRigidBody::setCCD(CCDType newCCD)
650{
651 if (m_CCD == newCCD)
652 return;
653
654 m_CCD = newCCD;
655 auto world = QPhysicsWorld::getWorld(this);
656 m_commandQueue.enqueue(new QPhysicsCommandSetCCD(m_CCD, world && world->enableCCD()));
657 emit ccdChanged();
658}
659
660void QDynamicRigidBody::setGravityEnabled(bool gravityEnabled)
661{
662 if (m_gravityEnabled == gravityEnabled)
663 return;
664
665 m_gravityEnabled = gravityEnabled;
666 m_commandQueue.enqueue(new QPhysicsCommandSetGravityEnabled(m_gravityEnabled));
667 emit gravityEnabledChanged();
668}
669
670void QDynamicRigidBody::setAngularVelocity(const QVector3D &angularVelocity)
671{
672 if (!QPhysicsUtils::isFinite(angularVelocity)) {
673 qWarning() << "DynamicRigidBody: angularVelocity must be finite, ignoring"
674 << angularVelocity;
675 return;
676 }
677 m_commandQueue.enqueue(new QPhysicsCommandSetAngularVelocity(angularVelocity));
678}
679
680QDynamicRigidBody::AxisLock QDynamicRigidBody::linearAxisLock() const
681{
682 return m_linearAxisLock;
683}
684
685void QDynamicRigidBody::setLinearAxisLock(AxisLock newAxisLockLinear)
686{
687 if (m_linearAxisLock == newAxisLockLinear)
688 return;
689 m_linearAxisLock = newAxisLockLinear;
690 emit linearAxisLockChanged();
691}
692
693QDynamicRigidBody::AxisLock QDynamicRigidBody::angularAxisLock() const
694{
695 return m_angularAxisLock;
696}
697
698void QDynamicRigidBody::setAngularAxisLock(AxisLock newAxisLockAngular)
699{
700 if (m_angularAxisLock == newAxisLockAngular)
701 return;
702 m_angularAxisLock = newAxisLockAngular;
703 emit angularAxisLockChanged();
704}
705
706QQueue<QPhysicsCommand *> &QDynamicRigidBody::commandQueue()
707{
708 return m_commandQueue;
709}
710
711void QDynamicRigidBody::updateDefaultDensity(float defaultDensity)
712{
713 if (m_massMode == MassMode::DefaultDensity)
714 m_commandQueue.enqueue(new QPhysicsCommandSetDensity(defaultDensity));
715}
716
717void QDynamicRigidBody::applyCentralForce(const QVector3D &force)
718{
719 if (!QPhysicsUtils::isFinite(force)) {
720 qWarning() << "DynamicRigidBody: applyCentralForce() force must be finite, ignoring"
721 << force;
722 return;
723 }
724 m_commandQueue.enqueue(new QPhysicsCommandApplyCentralForce(force));
725}
726
727void QDynamicRigidBody::applyForce(const QVector3D &force, const QVector3D &position)
728{
729 if (!QPhysicsUtils::isFinite(force) || !QPhysicsUtils::isFinite(position)) {
730 qWarning() << "DynamicRigidBody: applyForce() force/position must be finite, ignoring"
731 << force << position;
732 return;
733 }
734 m_commandQueue.enqueue(new QPhysicsCommandApplyForce(force, position));
735}
736
737void QDynamicRigidBody::applyTorque(const QVector3D &torque)
738{
739 if (!QPhysicsUtils::isFinite(torque)) {
740 qWarning() << "DynamicRigidBody: applyTorque() torque must be finite, ignoring" << torque;
741 return;
742 }
743 m_commandQueue.enqueue(new QPhysicsCommandApplyTorque(torque));
744}
745
746void QDynamicRigidBody::applyCentralImpulse(const QVector3D &impulse)
747{
748 if (!QPhysicsUtils::isFinite(impulse)) {
749 qWarning() << "DynamicRigidBody: applyCentralImpulse() impulse must be finite, ignoring"
750 << impulse;
751 return;
752 }
753 m_commandQueue.enqueue(new QPhysicsCommandApplyCentralImpulse(impulse));
754}
755
756void QDynamicRigidBody::applyImpulse(const QVector3D &impulse, const QVector3D &position)
757{
758 if (!QPhysicsUtils::isFinite(impulse) || !QPhysicsUtils::isFinite(position)) {
759 qWarning() << "DynamicRigidBody: applyImpulse() impulse/position must be finite, ignoring"
760 << impulse << position;
761 return;
762 }
763 m_commandQueue.enqueue(new QPhysicsCommandApplyImpulse(impulse, position));
764}
765
766void QDynamicRigidBody::applyTorqueImpulse(const QVector3D &impulse)
767{
768 if (!QPhysicsUtils::isFinite(impulse)) {
769 qWarning() << "DynamicRigidBody: applyTorqueImpulse() impulse must be finite, ignoring"
770 << impulse;
771 return;
772 }
773 m_commandQueue.enqueue(new QPhysicsCommandApplyTorqueImpulse(impulse));
774}
775
776void QDynamicRigidBody::setLinearVelocity(const QVector3D &linearVelocity)
777{
778 if (!QPhysicsUtils::isFinite(linearVelocity)) {
779 qWarning() << "DynamicRigidBody: linearVelocity must be finite, ignoring"
780 << linearVelocity;
781 return;
782 }
783 m_commandQueue.enqueue(new QPhysicsCommandSetLinearVelocity(linearVelocity));
784}
785
786void QDynamicRigidBody::reset(const QVector3D &position, const QVector3D &eulerRotation)
787{
788 if (!QPhysicsUtils::isFinite(position) || !QPhysicsUtils::isFinite(eulerRotation)) {
789 qWarning() << "DynamicRigidBody: reset() position/eulerRotation must be finite, ignoring"
790 << position << eulerRotation;
791 return;
792 }
793 m_commandQueue.enqueue(new QPhysicsCommandReset(position, eulerRotation));
794}
795
796void QDynamicRigidBody::setKinematicRotation(const QQuaternion &rotation)
797{
798 if (!QPhysicsUtils::isFinite(rotation)) {
799 qWarning() << "DynamicRigidBody: kinematicRotation must be finite, ignoring" << rotation;
800 return;
801 }
802 if (m_kinematicRotation == rotation)
803 return;
804
805 m_kinematicRotation = rotation;
806 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
807 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
808}
809
810QQuaternion QDynamicRigidBody::kinematicRotation() const
811{
812 return m_kinematicRotation.toQuaternion();
813}
814
815void QDynamicRigidBody::setKinematicEulerRotation(const QVector3D &rotation)
816{
817 if (!QPhysicsUtils::isFinite(rotation)) {
818 qWarning() << "DynamicRigidBody: kinematicEulerRotation must be finite, ignoring"
819 << rotation;
820 return;
821 }
822 if (m_kinematicRotation == rotation)
823 return;
824
825 m_kinematicRotation = rotation;
826 emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
827 emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
828}
829
830QVector3D QDynamicRigidBody::kinematicEulerRotation() const
831{
832 return m_kinematicRotation.toEulerAngles();
833}
834
835void QDynamicRigidBody::setKinematicPivot(const QVector3D &pivot)
836{
837 if (!QPhysicsUtils::isFinite(pivot)) {
838 qWarning() << "DynamicRigidBody: kinematicPivot must be finite, ignoring" << pivot;
839 return;
840 }
841
842 m_kinematicPivot = pivot;
843 emit kinematicPivotChanged(m_kinematicPivot);
844}
845
846QVector3D QDynamicRigidBody::kinematicPivot() const
847{
848 return m_kinematicPivot;
849}
850
851bool QDynamicRigidBody::isSleeping() const
852{
853 return m_isSleeping;
854}
855
856QVector3D QDynamicRigidBody::linearVelocity() const
857{
858 return m_linearVelocity;
859}
860
861QVector3D QDynamicRigidBody::angularVelocity() const
862{
863 return m_angularVelocity;
864}
865
866void QDynamicRigidBody::updateLinearVelocity(const QVector3D &velocity)
867{
868 if (m_linearVelocity == velocity)
869 return;
870 m_linearVelocity = velocity;
871 emit linearVelocityChanged(m_linearVelocity);
872}
873
874void QDynamicRigidBody::updateAngularVelocity(const QVector3D &velocity)
875{
876 if (m_angularVelocity == velocity)
877 return;
878 m_angularVelocity = velocity;
879 emit angularVelocityChanged(m_angularVelocity);
880}
881
882void QDynamicRigidBody::setIsSleeping(bool newIsSleeping)
883{
884 if (m_isSleeping == newIsSleeping)
885 return;
886
887 m_isSleeping = newIsSleeping;
888 emit isSleepingChanged(newIsSleeping);
889}
890
891QAbstractPhysXNode *QDynamicRigidBody::createPhysXBackend()
892{
893 return new QPhysXDynamicBody(this);
894}
895
896void QDynamicRigidBody::setKinematicPosition(const QVector3D &position)
897{
898 if (!QPhysicsUtils::isFinite(position)) {
899 qWarning() << "DynamicRigidBody: kinematicPosition must be finite, ignoring" << position;
900 return;
901 }
902
903 m_kinematicPosition = position;
904 emit kinematicPositionChanged(m_kinematicPosition);
905}
906
907QVector3D QDynamicRigidBody::kinematicPosition() const
908{
909 return m_kinematicPosition;
910}
911
static bool fuzzyEquals(const QList< float > &a, const QList< float > &b)
#define QT_BEGIN_NAMESPACE
#define QT_END_NAMESPACE