22 const QDynamicRigidBody &rigidBody,
physx::PxRigidBody &body)
24 for (
auto command : std::as_const(commandQueue)) {
25 command->execute(rigidBody, body);
33 QHash<QQuick3DNode *, QMatrix4x4> &transformCache)
36 if (transformCache.contains(node))
37 return transformCache[node];
39 QMatrix4x4 localTransform;
42 if (
auto drb = qobject_cast<
const QDynamicRigidBody *>(node); drb !=
nullptr) {
43 if (!drb->isKinematic()) {
44 qWarning() <<
"Non-kinematic body as a parent of a kinematic body is unsupported";
46 localTransform = QSSGRenderNode::calculateTransformMatrix(
47 drb->kinematicPosition(), drb->scale(), drb->kinematicPivot(),
48 drb->kinematicRotation());
50 localTransform = QSSGRenderNode::calculateTransformMatrix(node->position(), node->scale(),
51 node->pivot(), node->rotation());
54 QQuick3DNode *parent = node->parentNode();
56 return localTransform;
59 QMatrix4x4 parentTransform = calculateKinematicNodeTransform(parent, transformCache);
60 QMatrix4x4 sceneTransform = parentTransform * localTransform;
62 transformCache[node] = sceneTransform;
63 return sceneTransform;
68 const auto lockAngular = body->angularAxisLock();
69 const auto lockLinear = body->linearAxisLock();
70 const int flags = (lockAngular & QDynamicRigidBody::AxisLock::LockX
71 ? physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_X
73 | (lockAngular & QDynamicRigidBody::AxisLock::LockY
74 ? physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y
76 | (lockAngular & QDynamicRigidBody::AxisLock::LockZ
77 ? physx::PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z
79 | (lockLinear & QDynamicRigidBody::AxisLock::LockX
80 ? physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_X
82 | (lockLinear & QDynamicRigidBody::AxisLock::LockY
83 ? physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Y
85 | (lockLinear & QDynamicRigidBody::AxisLock::LockZ
86 ? physx::PxRigidDynamicLockFlag::eLOCK_LINEAR_Z
88 return static_cast<physx::PxRigidDynamicLockFlags>(flags);
93 auto rotationMatrix = transform;
94 QSSGUtils::mat44::normalize(rotationMatrix);
96 QQuaternion::fromRotationMatrix(QSSGUtils::mat44::getUpper3x3(rotationMatrix)).normalized();
97 const QVector3D worldPosition = QSSGUtils::mat44::getPosition(transform);
98 return physx::PxTransform(QPhysicsUtils::toPhysXType(worldPosition),
99 QPhysicsUtils::toPhysXType(rotation));
106 auto *dynamicRigidBody =
static_cast<QDynamicRigidBody *>(frontendNode);
107 if (!dynamicRigidBody->isKinematic()) {
118 QHash<QQuick3DNode *, QMatrix4x4> transformCache;
119 const QMatrix4x4 transform = calculateKinematicNodeTransform(dynamicRigidBody, transformCache);
120 physx::PxTransform trf = getPhysXWorldTransform(transform);
122 qWarning() <<
"DynamicRigidBody: kinematic position/rotation is not finite, using "
124 trf = physx::PxTransform(physx::PxIdentity);
127 actor = s_physx.physics->createRigidDynamic(trf);
139 auto *dynamicRigidBody =
static_cast<QDynamicRigidBody *>(frontendNode);
141 dynamicRigidBody->updateFromPhysicsTransform(actor->getGlobalPose());
143 auto *dynamicActor =
static_cast<physx::PxRigidDynamic *>(actor);
144 processCommandQueue(dynamicRigidBody->commandQueue(), *dynamicRigidBody, *dynamicActor);
145 if (dynamicRigidBody->isKinematic()) {
149 QMatrix4x4 transform = calculateKinematicNodeTransform(dynamicRigidBody, transformCache);
150 const physx::PxTransform worldTransform = getPhysXWorldTransform(transform);
151 if (worldTransform.isSane()) {
152 dynamicActor->setKinematicTarget(worldTransform);
154 qWarning() <<
"DynamicRigidBody: kinematic transform is not finite, keeping "
158 dynamicActor->setRigidDynamicLockFlags(getLockFlags(dynamicRigidBody));
161 const bool disabledPrevious = actor->getActorFlags() & physx::PxActorFlag::eDISABLE_SIMULATION;
162 const bool disabled = !dynamicRigidBody->simulationEnabled();
163 if (disabled != disabledPrevious) {
164 actor->setActorFlag(physx::PxActorFlag::eDISABLE_SIMULATION, disabled);
165 if (!disabled && !dynamicRigidBody->isKinematic())
166 dynamicActor->wakeUp();
169 dynamicRigidBody->setIsSleeping(dynamicActor->isSleeping());
171 QPhysXActorBody::sync(deltaTime, transformCache);
181 QDynamicRigidBody *drb =
static_cast<QDynamicRigidBody *>(frontendNode);
184 if (!drb->hasStaticShapes()) {
187 switch (drb->massMode()) {
188 case QDynamicRigidBody::MassMode::DefaultDensity: {
192 case QDynamicRigidBody::MassMode::CustomDensity: {
196 case QDynamicRigidBody::MassMode::Mass: {
197 const float mass = qMax(drb->mass(), 0.f);
201 case QDynamicRigidBody::MassMode::MassAndInertiaTensor: {
202 const float mass = qMax(drb->mass(), 0.f);
206 case QDynamicRigidBody::MassMode::MassAndInertiaMatrix: {
207 const float mass = qMax(drb->mass(), 0.f);
213 drb->commandQueue().enqueue(command);
214 }
else if (!drb->isKinematic()) {
216 qWarning() <<
"Cannot make body containing trimesh/heightfield/plane non-kinematic, "
217 "forcing kinematic.";
218 drb->setIsKinematic(
true);
221 const bool isKinematic = drb->isKinematic();
222 QDynamicRigidBody::CCDType ccd = drb->ccd();
224 auto *dynamicBody =
static_cast<physx::PxRigidDynamic *>(actor);
229 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD,
false);
230 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD,
false);
231 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC, isKinematic);
234 case QDynamicRigidBody::CCDType::SweepBasedCCD: {
236 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD,
238 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD, isKinematic);
242 case QDynamicRigidBody::CCDType::SpeculativeCCD: {
243 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD,
true);
247 case QDynamicRigidBody::CCDType::None: {
248 if (world->enableCCD()) {
250 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD,
252 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD,
void buildShapes(QPhysXWorld *physX)
virtual void createActor(QPhysXWorld *physX)
void updateDefaultDensity(float density) override
QPhysXDynamicBody(QDynamicRigidBody *frontEnd)
DebugDrawBodyType getDebugDrawBodyType() override
void sync(float deltaTime, QHash< QQuick3DNode *, QMatrix4x4 > &transformCache) override
void rebuildDirtyShapes(QPhysicsWorld *world, QPhysXWorld *physX) override
void createActor(QPhysXWorld *physX) override
static QMatrix4x4 calculateKinematicNodeTransform(QQuick3DNode *node, QHash< QQuick3DNode *, QMatrix4x4 > &transformCache)
static physx::PxTransform getPhysXWorldTransform(const QMatrix4x4 transform)
static physx::PxRigidDynamicLockFlags getLockFlags(QDynamicRigidBody *body)
static QT_BEGIN_NAMESPACE void processCommandQueue(QQueue< QPhysicsCommand * > &commandQueue, const QDynamicRigidBody &rigidBody, physx::PxRigidBody &body)