39 void onTrigger(physx::PxTriggerPair *pairs, physx::PxU32 count)
override
48 const auto replacesLostOverlap = [pairs, count](physx::PxU32 i) {
49 if (pairs[i].status != physx::PxPairFlag::eNOTIFY_TOUCH_FOUND)
51 for (physx::PxU32 j = 0; j < count; j++) {
52 if (pairs[j].status == physx::PxPairFlag::eNOTIFY_TOUCH_LOST
53 && pairs[j].triggerActor == pairs[i].triggerActor
54 && pairs[j].otherActor == pairs[i].otherActor) {
64 enum Pass { ReplacedOverlaps, EveryPair };
65 for (
const Pass pass : { ReplacedOverlaps, EveryPair }) {
66 for (physx::PxU32 i = 0; i < count; i++) {
67 if (pass == ReplacedOverlaps && !replacesLostOverlap(i))
72 & (physx::PxTriggerPairFlag::eREMOVED_SHAPE_TRIGGER
73 | physx::PxTriggerPairFlag::eREMOVED_SHAPE_OTHER))
76 QTriggerBody *triggerNode =
77 static_cast<QTriggerBody *>(pairs[i].triggerActor->userData);
79 QAbstractPhysicsNode *otherNode =
80 static_cast<QAbstractPhysicsNode *>(pairs[i].otherActor->userData);
82 if (!triggerNode || !otherNode) {
83 qWarning() <<
"QtQuick3DPhysics internal error: null pointer in trigger "
92 if (world->isNodeRemoved(triggerNode) || world->isNodeRemoved(otherNode))
99 const QTriggerBody::ShapePair shapes { frontendShape(pairs[i].triggerShape),
100 frontendShape(pairs[i].otherShape) };
106 if (pairs[i].status == physx::PxPairFlag::eNOTIFY_TOUCH_FOUND)
107 triggerNode->registerCollision(otherNode, shapes);
108 else if (pairs[i].status == physx::PxPairFlag::eNOTIFY_TOUCH_LOST)
109 triggerNode->deregisterCollision(otherNode, shapes);
118 void onContact(
const physx::PxContactPairHeader &pairHeader,
const physx::PxContactPair *pairs,
119 physx::PxU32 nbPairs)
override
121 constexpr physx::PxU32 bufferSize = 64;
122 physx::PxContactPairPoint contacts[bufferSize];
124 for (physx::PxU32 i = 0; i < nbPairs; i++) {
125 const physx::PxContactPair &contactPair = pairs[i];
127 if (contactPair.events & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) {
128 QAbstractPhysicsNode *trigger =
129 static_cast<QAbstractPhysicsNode *>(pairHeader.actors[0]->userData);
130 QAbstractPhysicsNode *other =
131 static_cast<QAbstractPhysicsNode *>(pairHeader.actors[1]->userData);
133 if (!trigger || !other || world->isNodeRemoved(trigger)
134 || world->isNodeRemoved(other) || !trigger->m_backendObject
135 || !other->m_backendObject)
138 const bool triggerReceive =
139 trigger->receiveContactReports() && other->sendContactReports();
140 const bool otherReceive =
141 other->receiveContactReports() && trigger->sendContactReports();
143 if (!triggerReceive && !otherReceive)
146 physx::PxU32 nbContacts = pairs[i].extractContacts(contacts, bufferSize);
148 QList<QVector3D> positions;
149 QList<QVector3D> impulses;
150 QList<QVector3D> normals;
152 positions.reserve(nbContacts);
153 impulses.reserve(nbContacts);
154 normals.reserve(nbContacts);
156 for (physx::PxU32 j = 0; j < nbContacts; j++) {
157 physx::PxVec3 position = contacts[j].position;
158 physx::PxVec3 impulse = contacts[j].impulse;
159 physx::PxVec3 normal = contacts[j].normal;
161 positions.push_back(QPhysicsUtils::toQtType(position));
162 impulses.push_back(QPhysicsUtils::toQtType(impulse));
163 normals.push_back(QPhysicsUtils::toQtType(normal));
166 QList<QVector3D> normalsInverted;
167 normalsInverted.reserve(normals.size());
168 for (
const QVector3D &v : std::as_const(normals)) {
169 normalsInverted.push_back(QVector3D(-v.x(), -v.y(), -v.z()));
173 world->registerContact(other, trigger, positions, impulses, normals);
175 world->registerContact(trigger, other, positions, impulses, normalsInverted);