22 const QDynamicRigidBody &rigidBody,
physx::PxRigidDynamic &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);
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());
148 auto *dynamicActor =
static_cast<physx::PxRigidDynamic *>(actor);
149 processCommandQueue(dynamicRigidBody->commandQueue(), *dynamicRigidBody, *dynamicActor);
151 const bool disabledPrevious = actor->getActorFlags() & physx::PxActorFlag::eDISABLE_SIMULATION;
152 const bool disabled = !dynamicRigidBody->simulationEnabled();
158 if (dynamicRigidBody->isKinematic() && !disabled && !disabledPrevious) {
162 QMatrix4x4 transform = calculateKinematicNodeTransform(dynamicRigidBody, transformCache);
163 const physx::
PxTransform worldTransform = getPhysXWorldTransform(transform);
164 if (worldTransform.isSane()) {
165 dynamicActor->setKinematicTarget(worldTransform);
167 qWarning() <<
"DynamicRigidBody: kinematic transform is not finite, keeping "
170 }
else if (!dynamicRigidBody->isKinematic()) {
171 dynamicActor->setRigidDynamicLockFlags(getLockFlags(dynamicRigidBody));
174 if (disabled != disabledPrevious) {
175 actor->setActorFlag(physx::PxActorFlag::eDISABLE_SIMULATION, disabled);
176 if (!disabled && !dynamicRigidBody->isKinematic())
177 dynamicActor->wakeUp();
183 dynamicRigidBody->updateLinearVelocity(
184 QPhysicsUtils::toQtType(dynamicActor->getLinearVelocity()));
185 dynamicRigidBody->updateAngularVelocity(
186 QPhysicsUtils::toQtType(dynamicActor->getAngularVelocity()));
187 dynamicRigidBody->setIsSleeping(dynamicActor->isSleeping());
193 QPhysXActorBody::sync(deltaTime, transformCache);
201 QDynamicRigidBody *drb =
static_cast<QDynamicRigidBody *>(frontendNode);
205 if (drb->hasStaticShapes() && !drb->isKinematic()) {
207 qWarning() <<
"Cannot make body containing trimesh/heightfield/plane non-kinematic, "
208 "forcing kinematic.";
209 drb->setIsKinematic(
true);
214 const bool isKinematic = drb->isKinematic();
215 auto *dynamicBody =
static_cast<physx::PxRigidDynamic *>(actor);
220 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD,
false);
221 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD,
false);
228 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC,
true);
237 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eKINEMATIC,
false);
240 if (!drb->hasStaticShapes()) {
243 switch (drb->massMode()) {
244 case QDynamicRigidBody::MassMode::DefaultDensity: {
248 case QDynamicRigidBody::MassMode::CustomDensity: {
252 case QDynamicRigidBody::MassMode::Mass: {
253 const float mass = qMax(drb->mass(), 0.f);
257 case QDynamicRigidBody::MassMode::MassAndInertiaTensor: {
258 const float mass = qMax(drb->mass(), 0.f);
262 case QDynamicRigidBody::MassMode::MassAndInertiaMatrix: {
263 const float mass = qMax(drb->mass(), 0.f);
269 drb->commandQueue().enqueue(command);
272 QDynamicRigidBody::CCDType ccd = drb->ccd();
275 case QDynamicRigidBody::CCDType::SweepBasedCCD: {
277 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD,
279 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD, isKinematic);
283 case QDynamicRigidBody::CCDType::SpeculativeCCD: {
284 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD,
true);
288 case QDynamicRigidBody::CCDType::None: {
289 if (world->enableCCD()) {
291 dynamicBody->setRigidBodyFlag(physx::PxRigidBodyFlag::eENABLE_CCD,
293 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::PxRigidDynamic &body)