1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qdynamicrigidbody_p.h" |
5 | #include "qphysicscommands_p.h" |
6 | #include "qphysicsworld_p.h" |
7 | #include "physxnode/qphysxdynamicbody_p.h" |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | /*! |
12 | \qmltype DynamicRigidBody |
13 | \inqmlmodule QtQuick3D.Physics |
14 | \inherits PhysicsBody |
15 | \since 6.4 |
16 | \brief A physical body that can move or be moved. |
17 | |
18 | This type defines a dynamic rigid body: an object that is part of the physics |
19 | scene and behaves like a physical object with mass and velocity. |
20 | |
21 | \note \l{TriangleMeshShape}{triangle mesh}, \l{HeightFieldShape}{height field} and |
22 | \l{PlaneShape}{plane} geometry shapes are not allowed as collision shapes when |
23 | \l isKinematic is \c false. |
24 | */ |
25 | |
26 | /*! |
27 | \qmlproperty float DynamicRigidBody::mass |
28 | |
29 | This property defines the mass of the body. Note that this is only used when massMode is not |
30 | \c {DynamicRigidBody.CustomDensity} or \c {DynamicRigidBody.DefaultDensity}. Also note that |
31 | a value of 0 is interpreted as infinite mass and that negative numbers are not allowed. |
32 | |
33 | Default value: \c 1 |
34 | |
35 | Range: \c{[0, inf]} |
36 | |
37 | \sa massMode |
38 | */ |
39 | |
40 | /*! |
41 | \qmlproperty float DynamicRigidBody::density |
42 | |
43 | This property defines the density of the body. This is only used when massMode is set to \c |
44 | {DynamicRigidBody.CustomDensity}. |
45 | |
46 | Default value: \c{0.001} |
47 | |
48 | Range: \c{(0, inf]} |
49 | \sa massMode |
50 | */ |
51 | |
52 | /*! |
53 | \qmlproperty AxisLock DynamicRigidBody::linearAxisLock |
54 | |
55 | This property locks the linear velocity of the body along the axes defined by the |
56 | DynamicRigidBody.AxisLock enum. To lock several axes just bitwise-or their enum values. |
57 | |
58 | Available options: |
59 | |
60 | \value DynamicRigidBody.None |
61 | No axis lock. |
62 | |
63 | \value DynamicRigidBody.LockX |
64 | Lock X axis. |
65 | |
66 | \value DynamicRigidBody.LockY |
67 | Lock Y axis. |
68 | |
69 | \value DynamicRigidBody.LockZ |
70 | Lock Z axis. |
71 | |
72 | Default value: \c{DynamicRigidBody.None} |
73 | */ |
74 | |
75 | /*! |
76 | \qmlproperty AxisLock DynamicRigidBody::angularAxisLock |
77 | |
78 | This property locks the angular velocity of the body along the axes defined by the |
79 | DynamicRigidBody.AxisLock enum. To lock several axes just bitwise-or their enum values. |
80 | |
81 | Available options: |
82 | |
83 | \value DynamicRigidBody.None |
84 | No axis lock. |
85 | |
86 | \value DynamicRigidBody.LockX |
87 | Lock X axis. |
88 | |
89 | \value DynamicRigidBody.LockY |
90 | Lock Y axis. |
91 | |
92 | \value DynamicRigidBody.LockZ |
93 | Lock Z axis. |
94 | |
95 | Default value: \c{DynamicRigidBody.None} |
96 | */ |
97 | |
98 | /*! |
99 | \qmlproperty bool DynamicRigidBody::isKinematic |
100 | This property defines whether the object is kinematic or not. A kinematic object does not get |
101 | influenced by external forces and can be seen as an object of infinite mass. If this property is |
102 | set then in every simulation frame the physical object will be moved to its target position |
103 | regardless of external forces. Note that to move and rotate the kinematic object you need to use |
104 | the kinematicPosition, kinematicRotation, kinematicEulerRotation and kinematicPivot properties. |
105 | |
106 | Default value: \c{false} |
107 | |
108 | \sa kinematicPosition, kinematicRotation, kinematicEulerRotation, kinematicPivot |
109 | */ |
110 | |
111 | /*! |
112 | \qmlproperty bool DynamicRigidBody::gravityEnabled |
113 | This property defines whether the object is going to be affected by gravity or not. |
114 | |
115 | Default value: \c{true} |
116 | */ |
117 | |
118 | /*! |
119 | \qmlproperty MassMode DynamicRigidBody::massMode |
120 | |
121 | This property holds the enum which describes how mass and inertia are calculated for this body. |
122 | |
123 | Available options: |
124 | |
125 | \value DynamicRigidBody.DefaultDensity |
126 | Use the density specified in the \l {PhysicsWorld::}{defaultDensity} property in |
127 | PhysicsWorld to calculate mass and inertia assuming a uniform density. |
128 | |
129 | \value DynamicRigidBody.CustomDensity |
130 | Use specified density in the specified in the \l {DynamicRigidBody::}{density} to |
131 | calculate mass and inertia assuming a uniform density. |
132 | |
133 | \value DynamicRigidBody.Mass |
134 | Use the specified mass to calculate inertia assuming a uniform density. |
135 | |
136 | \value DynamicRigidBody.MassAndInertiaTensor |
137 | Use the specified mass value and inertia tensor. |
138 | |
139 | \value DynamicRigidBody.MassAndInertiaMatrix |
140 | Use the specified mass value and calculate inertia from the specified inertia |
141 | matrix. |
142 | |
143 | Default value: \c{DynamicRigidBody.DefaultDensity} |
144 | */ |
145 | |
146 | /*! |
147 | \qmlproperty vector3d DynamicRigidBody::inertiaTensor |
148 | |
149 | Defines the inertia tensor vector, using a parameter specified in mass space coordinates. |
150 | |
151 | This is the diagonal vector of a 3x3 diagonal matrix, if you have a non diagonal world/actor |
152 | space inertia tensor then you should use \l{DynamicRigidBody::inertiaMatrix}{inertiaMatrix} |
153 | instead. |
154 | |
155 | The inertia tensor components must be positive and a value of 0 in any component is |
156 | interpreted as infinite inertia along that axis. Note that this is only used when |
157 | massMode is set to \c DynamicRigidBody.MassAndInertiaTensor. |
158 | |
159 | Default value: \c{(1, 1, 1)} |
160 | |
161 | \sa massMode, inertiaMatrix |
162 | */ |
163 | |
164 | /*! |
165 | \qmlproperty vector3d DynamicRigidBody::centerOfMassPosition |
166 | |
167 | Defines the position of the center of mass relative to the body. Note that this is only used |
168 | when massMode is set to \c DynamicRigidBody.MassAndInertiaTensor. |
169 | |
170 | Default value: \c{(0, 0, 0)} |
171 | |
172 | \sa massMode, inertiaTensor |
173 | */ |
174 | |
175 | /*! |
176 | \qmlproperty quaternion DynamicRigidBody::centerOfMassRotation |
177 | |
178 | Defines the rotation of the center of mass pose, i.e. it specifies the orientation of the body's |
179 | principal inertia axes relative to the body. Note that this is only used when massMode is set to |
180 | \c DynamicRigidBody.MassAndInertiaTensor. |
181 | |
182 | Default value: \c{(1, 0, 0, 0)} |
183 | |
184 | \sa massMode, inertiaTensor |
185 | */ |
186 | |
187 | /*! |
188 | \qmlproperty list<float> DynamicRigidBody::inertiaMatrix |
189 | |
190 | Defines the inertia tensor matrix. This is a 3x3 matrix in column-major order. Note that this |
191 | matrix is expected to be diagonalizable. Note that this is only used when massMode is set to |
192 | \c DynamicRigidBody.MassAndInertiaMatrix. |
193 | |
194 | Default value: A 3x3 identity matrix |
195 | |
196 | \sa massMode, inertiaTensor |
197 | */ |
198 | |
199 | /*! |
200 | \qmlproperty vector3d DynamicRigidBody::kinematicPosition |
201 | \since 6.5 |
202 | |
203 | Defines the position of the object when it is kinematic, i.e. when \l isKinematic is set to \c |
204 | true. On each iteration of the simulation the physical object will be updated according to this |
205 | value. |
206 | |
207 | Default value: \c{(0, 0, 0)} |
208 | |
209 | \sa isKinematic, kinematicRotation, kinematicEulerRotation, kinematicPivot |
210 | */ |
211 | |
212 | /*! |
213 | \qmlproperty vector3d DynamicRigidBody::kinematicRotation |
214 | \since 6.5 |
215 | |
216 | Defines the rotation of the object when it is kinematic, i.e. when \l isKinematic is set to \c |
217 | true. On each iteration of the simulation the physical object will be updated according to this |
218 | value. |
219 | |
220 | Default value: \c{(0, 0, 0)} |
221 | |
222 | \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicPivot |
223 | */ |
224 | |
225 | /*! |
226 | \qmlproperty vector4d DynamicRigidBody::kinematicEulerRotation |
227 | \since 6.5 |
228 | |
229 | Defines the euler rotation of the object when it is kinematic, i.e. when \l isKinematic is set to \c |
230 | true. On each iteration of the simulation the physical object will be updated according to this |
231 | value. |
232 | |
233 | Default value: \c{(1, 0, 0, 0)} |
234 | |
235 | \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicPivot |
236 | */ |
237 | |
238 | /*! |
239 | \qmlproperty vector3d DynamicRigidBody::kinematicPivot |
240 | \since 6.5 |
241 | |
242 | Defines the pivot of the object when it is kinematic, i.e. when \l isKinematic is set to \c |
243 | true. On each iteration of the simulation the physical object will be updated according to this |
244 | value. |
245 | |
246 | Default value: \c{(0, 0, 0)} |
247 | |
248 | \sa isKinematic, kinematicPosition, kinematicEulerRotation, kinematicRotation |
249 | */ |
250 | |
251 | /*! |
252 | \qmlmethod DynamicRigidBody::applyCentralForce(vector3d force) |
253 | |
254 | Applies a \a force on the center of the body. |
255 | */ |
256 | |
257 | /*! |
258 | \qmlmethod DynamicRigidBody::applyForce(vector3d force, vector3d position) |
259 | |
260 | Applies a \a force at a \a position on the body. |
261 | */ |
262 | |
263 | /*! |
264 | \qmlmethod DynamicRigidBody::applyTorque(vector3d torque) |
265 | |
266 | Applies a \a torque on the body. |
267 | */ |
268 | |
269 | /*! |
270 | \qmlmethod DynamicRigidBody::applyCentralImpulse(vector3d impulse) |
271 | |
272 | Applies an \a impulse on the center of the body. |
273 | */ |
274 | |
275 | /*! |
276 | \qmlmethod DynamicRigidBody::applyImpulse(vector3d impulse, vector3d position) |
277 | |
278 | Applies an \a impulse at a \a position on the body. |
279 | */ |
280 | |
281 | /*! |
282 | \qmlmethod DynamicRigidBody::applyTorqueImpulse(vector3d impulse) |
283 | |
284 | Applies a torque \a impulse on the body. |
285 | */ |
286 | |
287 | /*! |
288 | \qmlmethod DynamicRigidBody::setAngularVelocity(vector3d angularVelocity) |
289 | |
290 | Sets the \a angularVelocity of the body. |
291 | */ |
292 | |
293 | /*! |
294 | \qmlmethod DynamicRigidBody::setLinearVelocity(vector3d linearVelocity) |
295 | |
296 | Sets the \a linearVelocity of the body. |
297 | */ |
298 | |
299 | /*! |
300 | \qmlmethod DynamicRigidBody::reset(vector3d position, vector3d eulerRotation) |
301 | |
302 | Resets the body's \a position and \a eulerRotation. |
303 | */ |
304 | |
305 | QDynamicRigidBody::QDynamicRigidBody() = default; |
306 | |
307 | QDynamicRigidBody::~QDynamicRigidBody() |
308 | { |
309 | qDeleteAll(c: m_commandQueue); |
310 | m_commandQueue.clear(); |
311 | } |
312 | |
313 | const QQuaternion &QDynamicRigidBody::centerOfMassRotation() const |
314 | { |
315 | return m_centerOfMassRotation; |
316 | } |
317 | |
318 | void QDynamicRigidBody::setCenterOfMassRotation(const QQuaternion &newCenterOfMassRotation) |
319 | { |
320 | if (qFuzzyCompare(q1: m_centerOfMassRotation, q2: newCenterOfMassRotation)) |
321 | return; |
322 | m_centerOfMassRotation = newCenterOfMassRotation; |
323 | |
324 | // Only inertia tensor is using rotation |
325 | if (m_massMode == MassMode::MassAndInertiaTensor) |
326 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor)); |
327 | |
328 | emit centerOfMassRotationChanged(); |
329 | } |
330 | |
331 | const QVector3D &QDynamicRigidBody::centerOfMassPosition() const |
332 | { |
333 | return m_centerOfMassPosition; |
334 | } |
335 | |
336 | void QDynamicRigidBody::setCenterOfMassPosition(const QVector3D &newCenterOfMassPosition) |
337 | { |
338 | if (qFuzzyCompare(v1: m_centerOfMassPosition, v2: newCenterOfMassPosition)) |
339 | return; |
340 | |
341 | switch (m_massMode) { |
342 | case MassMode::MassAndInertiaTensor: { |
343 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor)); |
344 | break; |
345 | } |
346 | case MassMode::MassAndInertiaMatrix: { |
347 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix)); |
348 | break; |
349 | } |
350 | case MassMode::DefaultDensity: |
351 | case MassMode::CustomDensity: |
352 | case MassMode::Mass: |
353 | break; |
354 | } |
355 | |
356 | m_centerOfMassPosition = newCenterOfMassPosition; |
357 | emit centerOfMassPositionChanged(); |
358 | } |
359 | |
360 | QDynamicRigidBody::MassMode QDynamicRigidBody::massMode() const |
361 | { |
362 | return m_massMode; |
363 | } |
364 | |
365 | void QDynamicRigidBody::setMassMode(const MassMode newMassMode) |
366 | { |
367 | if (m_massMode == newMassMode) |
368 | return; |
369 | |
370 | switch (newMassMode) { |
371 | case MassMode::DefaultDensity: { |
372 | auto world = QPhysicsWorld::getWorld(node: this); |
373 | if (world) { |
374 | m_commandQueue.enqueue(t: new QPhysicsCommandSetDensity(world->defaultDensity())); |
375 | } else { |
376 | qWarning() << "No physics world found, cannot set default density." ; |
377 | } |
378 | break; |
379 | } |
380 | case MassMode::CustomDensity: { |
381 | m_commandQueue.enqueue(t: new QPhysicsCommandSetDensity(m_density)); |
382 | break; |
383 | } |
384 | case MassMode::Mass: { |
385 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMass(m_mass)); |
386 | break; |
387 | } |
388 | case MassMode::MassAndInertiaTensor: { |
389 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor)); |
390 | break; |
391 | } |
392 | case MassMode::MassAndInertiaMatrix: { |
393 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix)); |
394 | break; |
395 | } |
396 | } |
397 | |
398 | m_massMode = newMassMode; |
399 | emit massModeChanged(); |
400 | } |
401 | |
402 | const QVector3D &QDynamicRigidBody::inertiaTensor() const |
403 | { |
404 | return m_inertiaTensor; |
405 | } |
406 | |
407 | void QDynamicRigidBody::setInertiaTensor(const QVector3D &newInertiaTensor) |
408 | { |
409 | if (qFuzzyCompare(v1: m_inertiaTensor, v2: newInertiaTensor)) |
410 | return; |
411 | m_inertiaTensor = newInertiaTensor; |
412 | |
413 | if (m_massMode == MassMode::MassAndInertiaTensor) |
414 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaTensor(m_mass, m_inertiaTensor)); |
415 | |
416 | emit inertiaTensorChanged(); |
417 | } |
418 | |
419 | const QList<float> &QDynamicRigidBody::readInertiaMatrix() const |
420 | { |
421 | return m_inertiaMatrixList; |
422 | } |
423 | |
424 | static bool fuzzyEquals(const QList<float> &a, const QList<float> &b) |
425 | { |
426 | if (a.length() != b.length()) |
427 | return false; |
428 | |
429 | const int length = a.length(); |
430 | for (int i = 0; i < length; i++) |
431 | if (!qFuzzyCompare(p1: a[i], p2: b[i])) |
432 | return false; |
433 | |
434 | return true; |
435 | } |
436 | |
437 | void QDynamicRigidBody::setInertiaMatrix(const QList<float> &newInertiaMatrix) |
438 | { |
439 | if (fuzzyEquals(a: m_inertiaMatrixList, b: newInertiaMatrix)) |
440 | return; |
441 | |
442 | m_inertiaMatrixList = newInertiaMatrix; |
443 | const int elemsToCopy = qMin(a: m_inertiaMatrixList.length(), b: 9); |
444 | memcpy(dest: m_inertiaMatrix.data(), src: m_inertiaMatrixList.data(), n: elemsToCopy * sizeof(float)); |
445 | memset(s: m_inertiaMatrix.data() + elemsToCopy, c: 0, n: (9 - elemsToCopy) * sizeof(float)); |
446 | |
447 | if (m_massMode == MassMode::MassAndInertiaMatrix) |
448 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaMatrix(m_mass, m_inertiaMatrix)); |
449 | |
450 | emit inertiaMatrixChanged(); |
451 | } |
452 | |
453 | const QMatrix3x3 &QDynamicRigidBody::inertiaMatrix() const |
454 | { |
455 | return m_inertiaMatrix; |
456 | } |
457 | |
458 | float QDynamicRigidBody::mass() const |
459 | { |
460 | return m_mass; |
461 | } |
462 | |
463 | bool QDynamicRigidBody::isKinematic() const |
464 | { |
465 | return m_isKinematic; |
466 | } |
467 | |
468 | bool QDynamicRigidBody::gravityEnabled() const |
469 | { |
470 | return m_gravityEnabled; |
471 | } |
472 | |
473 | void QDynamicRigidBody::setMass(float mass) |
474 | { |
475 | if (mass < 0.f || qFuzzyCompare(p1: m_mass, p2: mass)) |
476 | return; |
477 | |
478 | switch (m_massMode) { |
479 | case QDynamicRigidBody::MassMode::Mass: |
480 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMass(mass)); |
481 | break; |
482 | case QDynamicRigidBody::MassMode::MassAndInertiaTensor: |
483 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaTensor(mass, m_inertiaTensor)); |
484 | break; |
485 | case QDynamicRigidBody::MassMode::MassAndInertiaMatrix: |
486 | m_commandQueue.enqueue(t: new QPhysicsCommandSetMassAndInertiaMatrix(mass, m_inertiaMatrix)); |
487 | break; |
488 | case QDynamicRigidBody::MassMode::DefaultDensity: |
489 | case QDynamicRigidBody::MassMode::CustomDensity: |
490 | break; |
491 | } |
492 | |
493 | m_mass = mass; |
494 | emit massChanged(mass: m_mass); |
495 | } |
496 | |
497 | float QDynamicRigidBody::density() const |
498 | { |
499 | return m_density; |
500 | } |
501 | |
502 | void QDynamicRigidBody::setDensity(float density) |
503 | { |
504 | if (qFuzzyCompare(p1: m_density, p2: density)) |
505 | return; |
506 | |
507 | if (m_massMode == MassMode::CustomDensity) |
508 | m_commandQueue.enqueue(t: new QPhysicsCommandSetDensity(density)); |
509 | |
510 | m_density = density; |
511 | emit densityChanged(density: m_density); |
512 | } |
513 | |
514 | void QDynamicRigidBody::setIsKinematic(bool isKinematic) |
515 | { |
516 | if (m_isKinematic == isKinematic) |
517 | return; |
518 | |
519 | if (hasStaticShapes() && !isKinematic) { |
520 | qWarning() |
521 | << "Cannot make body containing trimesh/heightfield/plane non-kinematic, ignoring." ; |
522 | return; |
523 | } |
524 | |
525 | m_isKinematic = isKinematic; |
526 | m_commandQueue.enqueue(t: new QPhysicsCommandSetIsKinematic(m_isKinematic)); |
527 | emit isKinematicChanged(isKinematic: m_isKinematic); |
528 | } |
529 | |
530 | void QDynamicRigidBody::setGravityEnabled(bool gravityEnabled) |
531 | { |
532 | if (m_gravityEnabled == gravityEnabled) |
533 | return; |
534 | |
535 | m_gravityEnabled = gravityEnabled; |
536 | m_commandQueue.enqueue(t: new QPhysicsCommandSetGravityEnabled(m_gravityEnabled)); |
537 | emit gravityEnabledChanged(); |
538 | } |
539 | |
540 | void QDynamicRigidBody::setAngularVelocity(const QVector3D &angularVelocity) |
541 | { |
542 | m_commandQueue.enqueue(t: new QPhysicsCommandSetAngularVelocity(angularVelocity)); |
543 | } |
544 | |
545 | QDynamicRigidBody::AxisLock QDynamicRigidBody::linearAxisLock() const |
546 | { |
547 | return m_linearAxisLock; |
548 | } |
549 | |
550 | void QDynamicRigidBody::setLinearAxisLock(AxisLock newAxisLockLinear) |
551 | { |
552 | if (m_linearAxisLock == newAxisLockLinear) |
553 | return; |
554 | m_linearAxisLock = newAxisLockLinear; |
555 | emit linearAxisLockChanged(); |
556 | } |
557 | |
558 | QDynamicRigidBody::AxisLock QDynamicRigidBody::angularAxisLock() const |
559 | { |
560 | return m_angularAxisLock; |
561 | } |
562 | |
563 | void QDynamicRigidBody::setAngularAxisLock(AxisLock newAxisLockAngular) |
564 | { |
565 | if (m_angularAxisLock == newAxisLockAngular) |
566 | return; |
567 | m_angularAxisLock = newAxisLockAngular; |
568 | emit angularAxisLockChanged(); |
569 | } |
570 | |
571 | QQueue<QPhysicsCommand *> &QDynamicRigidBody::commandQueue() |
572 | { |
573 | return m_commandQueue; |
574 | } |
575 | |
576 | void QDynamicRigidBody::updateDefaultDensity(float defaultDensity) |
577 | { |
578 | if (m_massMode == MassMode::DefaultDensity) |
579 | m_commandQueue.enqueue(t: new QPhysicsCommandSetDensity(defaultDensity)); |
580 | } |
581 | |
582 | void QDynamicRigidBody::applyCentralForce(const QVector3D &force) |
583 | { |
584 | m_commandQueue.enqueue(t: new QPhysicsCommandApplyCentralForce(force)); |
585 | } |
586 | |
587 | void QDynamicRigidBody::applyForce(const QVector3D &force, const QVector3D &position) |
588 | { |
589 | m_commandQueue.enqueue(t: new QPhysicsCommandApplyForce(force, position)); |
590 | } |
591 | |
592 | void QDynamicRigidBody::applyTorque(const QVector3D &torque) |
593 | { |
594 | m_commandQueue.enqueue(t: new QPhysicsCommandApplyTorque(torque)); |
595 | } |
596 | |
597 | void QDynamicRigidBody::applyCentralImpulse(const QVector3D &impulse) |
598 | { |
599 | m_commandQueue.enqueue(t: new QPhysicsCommandApplyCentralImpulse(impulse)); |
600 | } |
601 | |
602 | void QDynamicRigidBody::applyImpulse(const QVector3D &impulse, const QVector3D &position) |
603 | { |
604 | m_commandQueue.enqueue(t: new QPhysicsCommandApplyImpulse(impulse, position)); |
605 | } |
606 | |
607 | void QDynamicRigidBody::applyTorqueImpulse(const QVector3D &impulse) |
608 | { |
609 | m_commandQueue.enqueue(t: new QPhysicsCommandApplyTorqueImpulse(impulse)); |
610 | } |
611 | |
612 | void QDynamicRigidBody::setLinearVelocity(const QVector3D &linearVelocity) |
613 | { |
614 | m_commandQueue.enqueue(t: new QPhysicsCommandSetLinearVelocity(linearVelocity)); |
615 | } |
616 | |
617 | void QDynamicRigidBody::reset(const QVector3D &position, const QVector3D &eulerRotation) |
618 | { |
619 | m_commandQueue.enqueue(t: new QPhysicsCommandReset(position, eulerRotation)); |
620 | } |
621 | |
622 | void QDynamicRigidBody::setKinematicRotation(const QQuaternion &rotation) |
623 | { |
624 | if (m_kinematicRotation == rotation) |
625 | return; |
626 | |
627 | m_kinematicRotation = rotation; |
628 | emit kinematicRotationChanged(kinematicRotation: m_kinematicRotation); |
629 | emit kinematicEulerRotationChanged(kinematicEulerRotation: m_kinematicRotation.getEulerRotation()); |
630 | } |
631 | |
632 | QQuaternion QDynamicRigidBody::kinematicRotation() const |
633 | { |
634 | return m_kinematicRotation.getQuaternionRotation(); |
635 | } |
636 | |
637 | void QDynamicRigidBody::setKinematicEulerRotation(const QVector3D &rotation) |
638 | { |
639 | if (m_kinematicRotation == rotation) |
640 | return; |
641 | |
642 | m_kinematicRotation = rotation; |
643 | emit kinematicEulerRotationChanged(kinematicEulerRotation: m_kinematicRotation); |
644 | emit kinematicRotationChanged(kinematicRotation: m_kinematicRotation.getQuaternionRotation()); |
645 | } |
646 | |
647 | QVector3D QDynamicRigidBody::kinematicEulerRotation() const |
648 | { |
649 | return m_kinematicRotation.getEulerRotation(); |
650 | } |
651 | |
652 | void QDynamicRigidBody::setKinematicPivot(const QVector3D &pivot) |
653 | { |
654 | m_kinematicPivot = pivot; |
655 | emit kinematicPivotChanged(kinematicPivot: m_kinematicPivot); |
656 | } |
657 | |
658 | QVector3D QDynamicRigidBody::kinematicPivot() const |
659 | { |
660 | return m_kinematicPivot; |
661 | } |
662 | |
663 | QAbstractPhysXNode *QDynamicRigidBody::createPhysXBackend() |
664 | { |
665 | return new QPhysXDynamicBody(this); |
666 | } |
667 | |
668 | void QDynamicRigidBody::setKinematicPosition(const QVector3D &position) |
669 | { |
670 | m_kinematicPosition = position; |
671 | emit kinematicPositionChanged(kinematicPosition: m_kinematicPosition); |
672 | } |
673 | |
674 | QVector3D QDynamicRigidBody::kinematicPosition() const |
675 | { |
676 | return m_kinematicPosition; |
677 | } |
678 | |
679 | QT_END_NAMESPACE |
680 | |