Revision control

Copy as Markdown

// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qdynamicrigidbody_p.h"
#include "qphysicscommands_p.h"
#include "qphysicsutils_p.h"
#include "qphysicsworld_p.h"
#include "physxnode/qphysxdynamicbody_p.h"
#include <foundation/PxSimpleTypes.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 enumeration DynamicRigidBody::ccd
\since 6.13
This property determines the continuous collision detection (CCD) mode
used for this body. Enabling CCD reduces the risk of fast-moving objects passing
through geometry between physics frames (tunnelling). The following values
are available:
\value DynamicRigidBody.None
CCD is disabled for this body unless enabled globally by \l PhysicsWorld::enableCCD.
\value DynamicRigidBody.SpeculativeCCD
Uses speculative continuous collision detection. Supported for both dynamic and
kinematic bodies.
\value DynamicRigidBody.SweepBasedCCD
Uses sweep-based continuous collision detection. This mode is supported only
for non-kinematic dynamic bodies. If applied to a kinematic body, it automatically
falls back to \c SpeculativeCCD.
\default DynamicRigidBody.None
\note CCD processing can significantly impact simulation performance. Enable it only for
objects moving at high velocities or having small bounds relative to their speed.
\sa PhysicsWorld::enableCCD
*/
/*!
\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.
*/
/*!
\qmlproperty vector3d DynamicRigidBody::linearVelocity
\readonly
\since 6.13
The linear velocity of the body in scene units per second. The value is updated after each
physics frame, making the simulated velocity directly available to physics calculations in
QML.
The value is computed by the simulation, so it changes in response to gravity, contacts and
joints as well as to any applied force or impulse.
\l setLinearVelocity() overrides it directly, but like the other imperative calls it is
queued and applied on the next physics frame, so this property keeps its old value
until then.
For a kinematic body this is the velocity implied by its kinematic target. It is zero
while the body is sleeping, and a body whose \l {PhysicsBody::}{simulationEnabled} is
\c false counts as sleeping.
\sa setLinearVelocity(), applyCentralForce(), applyCentralImpulse(), angularVelocity
*/
/*!
\qmlproperty vector3d DynamicRigidBody::angularVelocity
\readonly
\since 6.13
The angular velocity of the body in radians per second. The value is updated after each
physics frame, making the simulated velocity directly available to physics calculations
in QML.
The value is computed by the simulation, so it changes in response to contacts, joints
and damping as well as to any applied torque or impulse.
\l setAngularVelocity() overrides it directly, but like the other imperative calls it
is queued and applied on the next physics frame, so this property keeps its old value
until then. Note that the underlying engine damps angular motion by default, so a
freely spinning body slows down even without contacts.
For a kinematic body this is the velocity implied by its kinematic target. It is zero
while the body is sleeping, and a body whose \l {PhysicsBody::}{simulationEnabled} is
\c false counts as sleeping.
\sa setAngularVelocity(), applyTorque(), applyTorqueImpulse(), linearVelocity
*/
/*!
\qmlmethod void DynamicRigidBody::applyCentralForce(vector3d force)
Applies a \a force on the center of the body.
*/
/*!
\qmlmethod void DynamicRigidBody::applyForce(vector3d force, vector3d position)
Applies a \a force at a \a position on the body.
*/
/*!
\qmlmethod void DynamicRigidBody::applyTorque(vector3d torque)
Applies a \a torque on the body.
*/
/*!
\qmlmethod void DynamicRigidBody::applyCentralImpulse(vector3d impulse)
Applies an \a impulse on the center of the body.
*/
/*!
\qmlmethod void DynamicRigidBody::applyImpulse(vector3d impulse, vector3d position)
Applies an \a impulse at a \a position on the body.
*/
/*!
\qmlmethod void DynamicRigidBody::applyTorqueImpulse(vector3d impulse)
Applies a torque \a impulse on the body.
*/
/*!
\qmlmethod void DynamicRigidBody::setAngularVelocity(vector3d angularVelocity)
Sets the \a angularVelocity of the body.
\sa angularVelocity
*/
/*!
\qmlmethod void DynamicRigidBody::setLinearVelocity(vector3d linearVelocity)
Sets the \a linearVelocity of the body.
\sa linearVelocity
*/
/*!
\qmlmethod void 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 (!QPhysicsUtils::isFinite(newCenterOfMassRotation)) {
qWarning() << "DynamicRigidBody: centerOfMassRotation must be finite, ignoring"
<< newCenterOfMassRotation;
return;
}
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 (!QPhysicsUtils::isFinite(newCenterOfMassPosition)) {
qWarning() << "DynamicRigidBody: centerOfMassPosition must be finite, ignoring"
<< newCenterOfMassPosition;
return;
}
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 (!QPhysicsUtils::isFinite(newInertiaTensor) || newInertiaTensor.x() < 0.f
|| newInertiaTensor.y() < 0.f || newInertiaTensor.z() < 0.f) {
qWarning() << "DynamicRigidBody: inertiaTensor" << newInertiaTensor
<< "must be finite and non-negative, ignoring.";
return;
}
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;
}
QDynamicRigidBody::CCDType QDynamicRigidBody::ccd() const
{
return m_CCD;
}
bool QDynamicRigidBody::gravityEnabled() const
{
return m_gravityEnabled;
}
void QDynamicRigidBody::setMass(float mass)
{
if (!qIsFinite(mass) || 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)
{
density = qBound(0.0000001f, density, PX_MAX_F32);
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;
auto world = QPhysicsWorld::getWorld(this);
m_commandQueue.enqueue(
new QPhysicsCommandSetIsKinematic(m_isKinematic, world && world->enableCCD()));
emit isKinematicChanged(m_isKinematic);
}
void QDynamicRigidBody::setCCD(CCDType newCCD)
{
if (m_CCD == newCCD)
return;
m_CCD = newCCD;
auto world = QPhysicsWorld::getWorld(this);
m_commandQueue.enqueue(new QPhysicsCommandSetCCD(m_CCD, world && world->enableCCD()));
emit ccdChanged();
}
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)
{
if (!QPhysicsUtils::isFinite(angularVelocity)) {
qWarning() << "DynamicRigidBody: angularVelocity must be finite, ignoring"
<< angularVelocity;
return;
}
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)
{
if (!QPhysicsUtils::isFinite(force)) {
qWarning() << "DynamicRigidBody: applyCentralForce() force must be finite, ignoring"
<< force;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandApplyCentralForce(force));
}
void QDynamicRigidBody::applyForce(const QVector3D &force, const QVector3D &position)
{
if (!QPhysicsUtils::isFinite(force) || !QPhysicsUtils::isFinite(position)) {
qWarning() << "DynamicRigidBody: applyForce() force/position must be finite, ignoring"
<< force << position;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandApplyForce(force, position));
}
void QDynamicRigidBody::applyTorque(const QVector3D &torque)
{
if (!QPhysicsUtils::isFinite(torque)) {
qWarning() << "DynamicRigidBody: applyTorque() torque must be finite, ignoring" << torque;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandApplyTorque(torque));
}
void QDynamicRigidBody::applyCentralImpulse(const QVector3D &impulse)
{
if (!QPhysicsUtils::isFinite(impulse)) {
qWarning() << "DynamicRigidBody: applyCentralImpulse() impulse must be finite, ignoring"
<< impulse;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandApplyCentralImpulse(impulse));
}
void QDynamicRigidBody::applyImpulse(const QVector3D &impulse, const QVector3D &position)
{
if (!QPhysicsUtils::isFinite(impulse) || !QPhysicsUtils::isFinite(position)) {
qWarning() << "DynamicRigidBody: applyImpulse() impulse/position must be finite, ignoring"
<< impulse << position;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandApplyImpulse(impulse, position));
}
void QDynamicRigidBody::applyTorqueImpulse(const QVector3D &impulse)
{
if (!QPhysicsUtils::isFinite(impulse)) {
qWarning() << "DynamicRigidBody: applyTorqueImpulse() impulse must be finite, ignoring"
<< impulse;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandApplyTorqueImpulse(impulse));
}
void QDynamicRigidBody::setLinearVelocity(const QVector3D &linearVelocity)
{
if (!QPhysicsUtils::isFinite(linearVelocity)) {
qWarning() << "DynamicRigidBody: linearVelocity must be finite, ignoring"
<< linearVelocity;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandSetLinearVelocity(linearVelocity));
}
void QDynamicRigidBody::reset(const QVector3D &position, const QVector3D &eulerRotation)
{
if (!QPhysicsUtils::isFinite(position) || !QPhysicsUtils::isFinite(eulerRotation)) {
qWarning() << "DynamicRigidBody: reset() position/eulerRotation must be finite, ignoring"
<< position << eulerRotation;
return;
}
m_commandQueue.enqueue(new QPhysicsCommandReset(position, eulerRotation));
}
void QDynamicRigidBody::setKinematicRotation(const QQuaternion &rotation)
{
if (!QPhysicsUtils::isFinite(rotation)) {
qWarning() << "DynamicRigidBody: kinematicRotation must be finite, ignoring" << rotation;
return;
}
if (m_kinematicRotation == rotation)
return;
m_kinematicRotation = rotation;
emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
}
QQuaternion QDynamicRigidBody::kinematicRotation() const
{
return m_kinematicRotation.toQuaternion();
}
void QDynamicRigidBody::setKinematicEulerRotation(const QVector3D &rotation)
{
if (!QPhysicsUtils::isFinite(rotation)) {
qWarning() << "DynamicRigidBody: kinematicEulerRotation must be finite, ignoring"
<< rotation;
return;
}
if (m_kinematicRotation == rotation)
return;
m_kinematicRotation = rotation;
emit kinematicEulerRotationChanged(m_kinematicRotation.toEulerAngles());
emit kinematicRotationChanged(m_kinematicRotation.toQuaternion());
}
QVector3D QDynamicRigidBody::kinematicEulerRotation() const
{
return m_kinematicRotation.toEulerAngles();
}
void QDynamicRigidBody::setKinematicPivot(const QVector3D &pivot)
{
if (!QPhysicsUtils::isFinite(pivot)) {
qWarning() << "DynamicRigidBody: kinematicPivot must be finite, ignoring" << pivot;
return;
}
m_kinematicPivot = pivot;
emit kinematicPivotChanged(m_kinematicPivot);
}
QVector3D QDynamicRigidBody::kinematicPivot() const
{
return m_kinematicPivot;
}
bool QDynamicRigidBody::isSleeping() const
{
return m_isSleeping;
}
QVector3D QDynamicRigidBody::linearVelocity() const
{
return m_linearVelocity;
}
QVector3D QDynamicRigidBody::angularVelocity() const
{
return m_angularVelocity;
}
void QDynamicRigidBody::updateLinearVelocity(const QVector3D &velocity)
{
if (m_linearVelocity == velocity)
return;
m_linearVelocity = velocity;
emit linearVelocityChanged(m_linearVelocity);
}
void QDynamicRigidBody::updateAngularVelocity(const QVector3D &velocity)
{
if (m_angularVelocity == velocity)
return;
m_angularVelocity = velocity;
emit angularVelocityChanged(m_angularVelocity);
}
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)
{
if (!QPhysicsUtils::isFinite(position)) {
qWarning() << "DynamicRigidBody: kinematicPosition must be finite, ignoring" << position;
return;
}
m_kinematicPosition = position;
emit kinematicPositionChanged(m_kinematicPosition);
}
QVector3D QDynamicRigidBody::kinematicPosition() const
{
return m_kinematicPosition;
}
QT_END_NAMESPACE