aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick3dphysics/qdynamicrigidbody.cpp
blob: 76cb0ed765693f51c98b181887f227c1fa02c731 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include "qdynamicrigidbody_p.h"
#include "qphysicscommands_p.h"
#include "qphysicsworld_p.h"
#include "physxnode/qphysxdynamicbody_p.h"

QT_BEGIN_NAMESPACE

/*!
    \qmltype DynamicRigidBody
    \inqmlmodule QtQuick3D.Physics
    \inherits PhysicsBody
    \since 6.4
    \brief A physical body that can move or be moved.

    This type defines a dynamic rigid body: an object that is part of the physics
    scene and behaves like a physical object with mass and velocity.

    \note \l{TriangleMeshShape}{triangle mesh}, \l{HeightFieldShape}{height field} and
    \l{PlaneShape}{plane} geometry shapes are not allowed as collision shapes when
    \l isKinematic is \c false.
*/

/*!
    \qmlproperty real DynamicRigidBody::mass

    This property defines the mass of the body. Note that this is only used when massMode is not
    \c {DynamicRigidBody.CustomDensity} or \c {DynamicRigidBody.DefaultDensity}. Also note that
    a value of 0 is interpreted as infinite mass and that negative numbers are not allowed.

    Default value: \c 1

    Range: \c{[0, inf]}

    \sa massMode
*/

/*!
    \qmlproperty real DynamicRigidBody::density

    This property defines the density of the body. This is only used when massMode is set to \c
    {DynamicRigidBody.CustomDensity}.

    Default value: \c{0.001}

    Range: \c{(0, inf]}
    \sa massMode
*/

/*!
    \qmlproperty AxisLock DynamicRigidBody::linearAxisLock

    This property locks the linear velocity of the body along the axes defined by the
    DynamicRigidBody.AxisLock enum. To lock several axes just bitwise-or their enum values.

    Available options:

    \value  DynamicRigidBody.None
            No axis lock.

    \value  DynamicRigidBody.LockX
            Lock X axis.

    \value  DynamicRigidBody.LockY
            Lock Y axis.

    \value  DynamicRigidBody.LockZ
            Lock Z axis.

    Default value: \c{DynamicRigidBody.None}
*/

/*!
    \qmlproperty AxisLock DynamicRigidBody::angularAxisLock

    This property locks the angular velocity of the body along the axes defined by the
    DynamicRigidBody.AxisLock enum. To lock several axes just bitwise-or their enum values.

    Available options:

    \value  DynamicRigidBody.None
            No axis lock.

    \value  DynamicRigidBody.LockX
            Lock X axis.

    \value  DynamicRigidBody.LockY
            Lock Y axis.

    \value  DynamicRigidBody.LockZ
            Lock Z axis.

    Default value: \c{DynamicRigidBody.None}
*/

/*!
    \qmlproperty bool DynamicRigidBody::isKinematic
    This property defines whether the object is kinematic or not. A kinematic object does not get
    influenced by external forces and can be seen as an object of infinite mass. If this property is
    set then in every simulation frame the physical object will be moved to its target position
    regardless of external forces. Note that to move and rotate the kinematic object you need to use
    the kinematicPosition, kinematicRotation, kinematicEulerRotation and kinematicPivot properties.

    Default value: \c{false}

    \sa kinematicPosition, kinematicRotation, kinematicEulerRotation, kinematicPivot
*/

/*!
    \qmlproperty bool DynamicRigidBody::gravityEnabled
    This property defines whether the object is going to be affected by gravity or not.

    Default value: \c{true}
*/

/*!
    \qmlproperty MassMode DynamicRigidBody::massMode

    This property holds the enum which describes how mass and inertia are calculated for this body.

    Available options:

    \value  DynamicRigidBody.DefaultDensity
            Use the density specified in the \l {PhysicsWorld::}{defaultDensity} property in
            PhysicsWorld to calculate mass and inertia assuming a uniform density.

    \value  DynamicRigidBody.CustomDensity
            Use specified density in the specified in the \l {DynamicRigidBody::}{density} to
            calculate mass and inertia assuming a uniform density.

    \value  DynamicRigidBody.Mass
            Use the specified mass to calculate inertia assuming a uniform density.

    \value  DynamicRigidBody.MassAndInertiaTensor
            Use the specified mass value and inertia tensor.

    \value  DynamicRigidBody.MassAndInertiaMatrix
            Use the specified mass value and calculate inertia from the specified inertia
            matrix.

    Default value: \c{DynamicRigidBody.DefaultDensity}
*/

/*!
    \qmlproperty vector3d DynamicRigidBody::inertiaTensor

    Defines the inertia tensor vector, using a parameter specified in mass space coordinates.

    This is the diagonal vector of a 3x3 diagonal matrix, if you have a non diagonal world/actor
    space inertia tensor then you should use \l{DynamicRigidBody::inertiaMatrix}{inertiaMatrix}
    instead.

    The inertia tensor components must be positive and a value of 0 in any component is
    interpreted as infinite inertia along that axis. Note that this is only used when
    massMode is set to \c DynamicRigidBody.MassAndInertiaTensor.

    Default value: \c{(1, 1, 1)}

    \sa massMode, inertiaMatrix
*/

/*!
    \qmlproperty vector3d DynamicRigidBody::centerOfMassPosition

    Defines the position of the center of mass relative to the body. Note that this is only used
    when massMode is set to \c DynamicRigidBody.MassAndInertiaTensor.

    Default value: \c{(0, 0, 0)}

    \sa massMode, inertiaTensor
*/

/*!
    \qmlproperty quaternion DynamicRigidBody::centerOfMassRotation

    Defines the rotation of the center of mass pose, i.e. it specifies the orientation of the body's
    principal inertia axes relative to the body. Note that this is only used when massMode is set to
    \c DynamicRigidBody.MassAndInertiaTensor.

    Default value: \c{(1, 0, 0, 0)}

    \sa massMode, inertiaTensor
*/

/*!
    \qmlproperty list<real> DynamicRigidBody::inertiaMatrix

    Defines the inertia tensor matrix. This is a 3x3 matrix in column-major order. Note that this
    matrix is expected to be diagonalizable. Note that this is only used when massMode is set to
    \c DynamicRigidBody.MassAndInertiaMatrix.

    Default value: A 3x3 identity matrix

    \sa massMode, inertiaTensor
*/

/*!
    \qmlproperty vector3d DynamicRigidBody::kinematicPosition
    \since 6.5

    Defines the position of the object when it is kinematic, i.e. when \l isKinematic is set to \c
    true. On each iteration of the simulation the physical object will be updated according to this
    value.

    Default value: \c{(0, 0, 0)}

    \sa isKinematic, kinematicRotation, kinematicEulerRotation, kinematicPivot
*/

/*!
    \qmlproperty quaternion DynamicRigidBody::kinematicRotation
    \since 6.5

    Defines the rotation of the object when it is kinematic, i.e. when \l isKinematic is set to \c
    true. On each iteration of the simulation the physical object will be updated according to this
    value.

    Default value: \c{(1, 0, 0, 0)}

    \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicPivot
*/

/*!
    \qmlproperty vector3d DynamicRigidBody::kinematicEulerRotation
    \since 6.5

    Defines the euler rotation of the object when it is kinematic, i.e. when \l isKinematic is set to \c
    true. On each iteration of the simulation the physical object will be updated according to this
    value.

    Default value: \c{(0, 0, 0)}

    \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicPivot
*/

/*!
    \qmlproperty vector3d DynamicRigidBody::kinematicPivot
    \since 6.5

    Defines the pivot of the object when it is kinematic, i.e. when \l isKinematic is set to \c
    true. On each iteration of the simulation the physical object will be updated according to this
    value.

    Default value: \c{(0, 0, 0)}

    \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicRotation
*/

/*!
    \qmlproperty bool DynamicRigidBody::isSleeping
    \since 6.9

    Is set to \c{true} if the body is sleeping. While it is technically possible to set this property
    it should be seen as a read-only property that is set on every frame the physics simulation is
    running.
*/

/*!
    \qmlmethod DynamicRigidBody::applyCentralForce(vector3d force)

    Applies  a \a force on the center of the body.
*/

/*!
    \qmlmethod DynamicRigidBody::applyForce(vector3d force, vector3d position)

    Applies a \a force at a \a position on the body.
*/

/*!
    \qmlmethod DynamicRigidBody::applyTorque(vector3d torque)

    Applies a \a torque on the body.
*/

/*!
    \qmlmethod DynamicRigidBody::applyCentralImpulse(vector3d impulse)

    Applies an \a impulse on the center of the body.
*/

/*!
    \qmlmethod DynamicRigidBody::applyImpulse(vector3d impulse, vector3d position)

    Applies an \a impulse at a \a position on the body.
*/

/*!
    \qmlmethod DynamicRigidBody::applyTorqueImpulse(vector3d impulse)

    Applies a torque \a impulse on the body.
*/

/*!
    \qmlmethod DynamicRigidBody::setAngularVelocity(vector3d angularVelocity)

    Sets the \a angularVelocity of the body.
*/

/*!
    \qmlmethod DynamicRigidBody::setLinearVelocity(vector3d linearVelocity)

    Sets the \a linearVelocity of the body.
*/

/*!
    \qmlmethod DynamicRigidBody::reset(vector3d position, vector3d eulerRotation)

    Resets the body's \a position and \a eulerRotation.
*/

QDynamicRigidBody::QDynamicRigidBody() = default;

QDynamicRigidBody::~QDynamicRigidBody()
{
    qDeleteAll(m_commandQueue);
    m_commandQueue.clear();
}

const QQuaternion &QDynamicRigidBody::centerOfMassRotation() const
{
    return m_centerOfMassRotation;
}

void QDynamicRigidBody::setCenterOfMassRotation(const QQuaternion &newCenterOfMassRotation)
{
    if (qFuzzyCompare(m_centerOfMassRotation, newCenterOfMassRotation))
        return;
    m_centerOfMassRotation = newCenterOfMassRotation;

    // Only inertia tensor is using rotation
    if (m_massMode == MassMode::MassAndInertiaTensor)
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));

    emit centerOfMassRotationChanged();
}

const QVector3D &QDynamicRigidBody::centerOfMassPosition() const
{
    return m_centerOfMassPosition;
}

void QDynamicRigidBody::setCenterOfMassPosition(const QVector3D &newCenterOfMassPosition)
{
    if (qFuzzyCompare(m_centerOfMassPosition, newCenterOfMassPosition))
        return;

    switch (m_massMode) {
    case MassMode::MassAndInertiaTensor: {
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
        break;
    }
    case MassMode::MassAndInertiaMatrix: {
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
        break;
    }
    case MassMode::DefaultDensity:
    case MassMode::CustomDensity:
    case MassMode::Mass:
        break;
    }

    m_centerOfMassPosition = newCenterOfMassPosition;
    emit centerOfMassPositionChanged();
}

QDynamicRigidBody::MassMode QDynamicRigidBody::massMode() const
{
    return m_massMode;
}

void QDynamicRigidBody::setMassMode(const MassMode newMassMode)
{
    if (m_massMode == newMassMode)
        return;

    switch (newMassMode) {
    case MassMode::DefaultDensity: {
        auto world = QPhysicsWorld::getWorld(this);
        if (world) {
            m_commandQueue.enqueue(new QPhysicsCommandSetDensity(world->defaultDensity()));
        } else {
            qWarning() << "No physics world found, cannot set default density.";
        }
        break;
    }
    case MassMode::CustomDensity: {
        m_commandQueue.enqueue(new QPhysicsCommandSetDensity(m_density));
        break;
    }
    case MassMode::Mass: {
        m_commandQueue.enqueue(new QPhysicsCommandSetMass(m_mass));
        break;
    }
    case MassMode::MassAndInertiaTensor: {
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));
        break;
    }
    case MassMode::MassAndInertiaMatrix: {
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));
        break;
    }
    }

    m_massMode = newMassMode;
    emit massModeChanged();
}

const QVector3D &QDynamicRigidBody::inertiaTensor() const
{
    return m_inertiaTensor;
}

void QDynamicRigidBody::setInertiaTensor(const QVector3D &newInertiaTensor)
{
    if (qFuzzyCompare(m_inertiaTensor, newInertiaTensor))
        return;
    m_inertiaTensor = newInertiaTensor;

    if (m_massMode == MassMode::MassAndInertiaTensor)
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor));

    emit inertiaTensorChanged();
}

const QList<float> &QDynamicRigidBody::readInertiaMatrix() const
{
    return m_inertiaMatrixList;
}

static bool fuzzyEquals(const QList<float> &a, const QList<float> &b)
{
    if (a.length() != b.length())
        return false;

    const int length = a.length();
    for (int i = 0; i < length; i++)
        if (!qFuzzyCompare(a[i], b[i]))
            return false;

    return true;
}

void QDynamicRigidBody::setInertiaMatrix(const QList<float> &newInertiaMatrix)
{
    if (fuzzyEquals(m_inertiaMatrixList, newInertiaMatrix))
        return;

    m_inertiaMatrixList = newInertiaMatrix;
    const int elemsToCopy = qMin(m_inertiaMatrixList.length(), 9);
    memcpy(m_inertiaMatrix.data(), m_inertiaMatrixList.data(), elemsToCopy * sizeof(float));
    memset(m_inertiaMatrix.data() + elemsToCopy, 0, (9 - elemsToCopy) * sizeof(float));

    if (m_massMode == MassMode::MassAndInertiaMatrix)
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix));

    emit inertiaMatrixChanged();
}

const QMatrix3x3 &QDynamicRigidBody::inertiaMatrix() const
{
    return m_inertiaMatrix;
}

float QDynamicRigidBody::mass() const
{
    return m_mass;
}

bool QDynamicRigidBody::isKinematic() const
{
    return m_isKinematic;
}

bool QDynamicRigidBody::gravityEnabled() const
{
    return m_gravityEnabled;
}

void QDynamicRigidBody::setMass(float mass)
{
    if (mass < 0.f || qFuzzyCompare(m_mass, mass))
        return;

    switch (m_massMode) {
    case QDynamicRigidBody::MassMode::Mass:
        m_commandQueue.enqueue(new QPhysicsCommandSetMass(mass));
        break;
    case QDynamicRigidBody::MassMode::MassAndInertiaTensor:
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaTensor(mass, m_inertiaTensor));
        break;
    case QDynamicRigidBody::MassMode::MassAndInertiaMatrix:
        m_commandQueue.enqueue(new QPhysicsCommandSetMassAndInertiaMatrix(mass, m_inertiaMatrix));
        break;
    case QDynamicRigidBody::MassMode::DefaultDensity:
    case QDynamicRigidBody::MassMode::CustomDensity:
        break;
    }

    m_mass = mass;
    emit massChanged(m_mass);
}

float QDynamicRigidBody::density() const
{
    return m_density;
}

void QDynamicRigidBody::setDensity(float density)
{
    if (qFuzzyCompare(m_density, density))
        return;

    if (m_massMode == MassMode::CustomDensity)
        m_commandQueue.enqueue(new QPhysicsCommandSetDensity(density));

    m_density = density;
    emit densityChanged(m_density);
}

void QDynamicRigidBody::setIsKinematic(bool isKinematic)
{
    if (m_isKinematic == isKinematic)
        return;

    if (hasStaticShapes() && !isKinematic) {
        qWarning()
                << "Cannot make body containing trimesh/heightfield/plane non-kinematic, ignoring.";
        return;
    }

    m_isKinematic = isKinematic;
    m_commandQueue.enqueue(new QPhysicsCommandSetIsKinematic(m_isKinematic));
    emit isKinematicChanged(m_isKinematic);
}

void QDynamicRigidBody::setGravityEnabled(bool gravityEnabled)
{
    if (m_gravityEnabled == gravityEnabled)
        return;

    m_gravityEnabled = gravityEnabled;
    m_commandQueue.enqueue(new QPhysicsCommandSetGravityEnabled(m_gravityEnabled));
    emit gravityEnabledChanged();
}

void QDynamicRigidBody::setAngularVelocity(const QVector3D &angularVelocity)
{
    m_commandQueue.enqueue(new QPhysicsCommandSetAngularVelocity(angularVelocity));
}

QDynamicRigidBody::AxisLock QDynamicRigidBody::linearAxisLock() const
{
    return m_linearAxisLock;
}

void QDynamicRigidBody::setLinearAxisLock(AxisLock newAxisLockLinear)
{
    if (m_linearAxisLock == newAxisLockLinear)
        return;
    m_linearAxisLock = newAxisLockLinear;
    emit linearAxisLockChanged();
}

QDynamicRigidBody::AxisLock QDynamicRigidBody::angularAxisLock() const
{
    return m_angularAxisLock;
}

void QDynamicRigidBody::setAngularAxisLock(AxisLock newAxisLockAngular)
{
    if (m_angularAxisLock == newAxisLockAngular)
        return;
    m_angularAxisLock = newAxisLockAngular;
    emit angularAxisLockChanged();
}

QQueue<QPhysicsCommand *> &QDynamicRigidBody::commandQueue()
{
    return m_commandQueue;
}

void QDynamicRigidBody::updateDefaultDensity(float defaultDensity)
{
    if (m_massMode == MassMode::DefaultDensity)
        m_commandQueue.enqueue(new QPhysicsCommandSetDensity(defaultDensity));
}

void QDynamicRigidBody::applyCentralForce(const QVector3D &force)
{
    m_commandQueue.enqueue(new QPhysicsCommandApplyCentralForce(force));
}

void QDynamicRigidBody::applyForce(const QVector3D &force, const QVector3D &position)
{
    m_commandQueue.enqueue(new QPhysicsCommandApplyForce(force, position));
}

void QDynamicRigidBody::applyTorque(const QVector3D &torque)
{
    m_commandQueue.enqueue(new QPhysicsCommandApplyTorque(torque));
}

void QDynamicRigidBody::applyCentralImpulse(const QVector3D &impulse)
{
    m_commandQueue.enqueue(new QPhysicsCommandApplyCentralImpulse(impulse));
}

void QDynamicRigidBody::applyImpulse(const QVector3D &impulse, const QVector3D &position)
{
    m_commandQueue.enqueue(new QPhysicsCommandApplyImpulse(impulse, position));
}

void QDynamicRigidBody::applyTorqueImpulse(const QVector3D &impulse)
{
    m_commandQueue.enqueue(new QPhysicsCommandApplyTorqueImpulse(impulse));
}

void QDynamicRigidBody::setLinearVelocity(const QVector3D &linearVelocity)
{
    m_commandQueue.enqueue(new QPhysicsCommandSetLinearVelocity(linearVelocity));
}

void QDynamicRigidBody::reset(const QVector3D &position, const QVector3D &eulerRotation)
{
    m_commandQueue.enqueue(new QPhysicsCommandReset(position, eulerRotation));
}

void QDynamicRigidBody::setKinematicRotation(const QQuaternion &rotation)
{
    if (m_kinematicRotation == rotation)
        return;

    m_kinematicRotation = rotation;
    emit kinematicRotationChanged(m_kinematicRotation);
    emit kinematicEulerRotationChanged(m_kinematicRotation.getEulerRotation());
}

QQuaternion QDynamicRigidBody::kinematicRotation() const
{
    return m_kinematicRotation.getQuaternionRotation();
}

void QDynamicRigidBody::setKinematicEulerRotation(const QVector3D &rotation)
{
    if (m_kinematicRotation == rotation)
        return;

    m_kinematicRotation = rotation;
    emit kinematicEulerRotationChanged(m_kinematicRotation);
    emit kinematicRotationChanged(m_kinematicRotation.getQuaternionRotation());
}

QVector3D QDynamicRigidBody::kinematicEulerRotation() const
{
    return m_kinematicRotation.getEulerRotation();
}

void QDynamicRigidBody::setKinematicPivot(const QVector3D &pivot)
{
    m_kinematicPivot = pivot;
    emit kinematicPivotChanged(m_kinematicPivot);
}

QVector3D QDynamicRigidBody::kinematicPivot() const
{
    return m_kinematicPivot;
}

bool QDynamicRigidBody::isSleeping() const
{
    return m_isSleeping;
}

void QDynamicRigidBody::setIsSleeping(bool newIsSleeping)
{
    if (m_isSleeping == newIsSleeping)
        return;

    m_isSleeping = newIsSleeping;
    emit isSleepingChanged(newIsSleeping);
}

QAbstractPhysXNode *QDynamicRigidBody::createPhysXBackend()
{
    return new QPhysXDynamicBody(this);
}

void QDynamicRigidBody::setKinematicPosition(const QVector3D &position)
{
    m_kinematicPosition = position;
    emit kinematicPositionChanged(m_kinematicPosition);
}

QVector3D QDynamicRigidBody::kinematicPosition() const
{
    return m_kinematicPosition;
}

QT_END_NAMESPACE