Any input on PhysX collision callbacks?

Expanding and utilizing the engine via C++.
10 posts Page 1 of 1
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Mon Mar 12, 2018 6:56 am
(Looking at you @ Timmy)

I just implemented some rocket PhysicsShapes for my attack helicopter, and have got them exploding on a destroy() timer, but would really prefer a collision callback. Started digging into it, first hoping I could just do a Torque onCollision, but found that to be a ShapeBase function which doesn't work for GameBase.

Then found this old thread:

https://www.garagegames.com/community/f ... ead/130395

But after poking around a bit, that thread looked pretty outdated, and I thought I should really ask Timmy about this before I burn any more brain cells. :-) My use case is: I have rockets with physx primitives attached, I would like to collide them with the ground plane or other physics shapes, and on collision call destroy() and blow some shit up.
Timmy
Posts: 366
Joined: Thu Feb 05, 2015 3:20 am
by Timmy » Mon Mar 12, 2018 7:25 am
Check out here @ chriscalef http://docs.nvidia.com/gameworks/conten ... ction.html, the PxSimulationEventCallback is what you want. Works along the lines of that old physx 2.x method in that thread you posted
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Mon Mar 12, 2018 7:50 am
Ah, very interesting ^^^ thank you.
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Tue Mar 13, 2018 6:15 pm
Right, now this is starting to ring some bells... I had collision callbacks working fine in PhysX 2.x, but do remember taking one look at the new system in 3.x and deciding to come back to that later. :-)

But "later" is now, so... gave it a pretty good try last night. It seems like I did all the things I should have to do, but am still failing to get a call to my onContact() function.

What I did:

1) Added inheritance from PxSimulationEventCallback to my Px3World class, like so:

Code: Select all

class Px3World : public PhysicsWorld, public physx::PxSimulationEventCallback
2) Added the following function definitions/declarations to keep up with the virtuals:

Code: Select all

virtual void onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs); virtual void onTrigger(physx::PxTriggerPair* pairs, physx::PxU32 count) {} virtual void onConstraintBreak(physx::PxConstraintInfo*, physx::PxU32) {} virtual void onWake(physx::PxActor**, physx::PxU32) {} virtual void onSleep(physx::PxActor**, physx::PxU32) {}
3) Defined a new filterShader function, like so:

Code: Select all

static physx::PxFilterFlags MegamotionFilterShader( physx::PxFilterObjectAttributes attributes0, physx::PxFilterData filterData0, physx::PxFilterObjectAttributes attributes1, physx::PxFilterData filterData1, physx::PxPairFlags& pairFlags, const void* constantBlock, physx::PxU32 constantBlockSize) { pairFlags = physx::PxPairFlag::eCONTACT_DEFAULT; // trigger the contact callback for pairs (A,B) where // the filtermask of A contains the ID of B and vice versa. if ((filterData0.word0 & filterData1.word1) || (filterData1.word0 & filterData0.word1)) { pairFlags |= physx::PxPairFlag::eNOTIFY_TOUCH_FOUND; return physx::PxFilterFlag::eNOTIFY; } return physx::PxFilterFlag::eDEFAULT; }
You may note that I changed the SampleSubmarine version of this from a && to a || when it comes to the word0/word1 bit, because I am only telling my rockets to respond to the rest of the world, but not bothering to tell the rest of the world they have to respond to rockets. That seemed a little silly, and it seemed like right here was the only place it mattered... but I also tried just setting the filterShader up to send an eNOTIFY every damn time no matter what, and still didn't get any response.

4) Attached that filterShader to my sceneDesc object, like so:

Code: Select all

sceneDesc.filterShader = MegamotionFilterShader;
5) Added a new category to the Px3CollisionGroup enum, to cover my explosive objects:

Code: Select all

enum Px3CollisionGroup { PX3_DEFAULT = BIT(0), PX3_PLAYER = BIT(1), PX3_DEBRIS = BIT(2), PX3_TRIGGER = BIT(3), PX3_EXPLOSIVE = BIT(4), };
6) Assigned my rocket shapes to have that collision group as word0, and PX3_DEFAULT as word1.

7) Defined my onContact function in Px3World.cpp, for starters just to try to kick out a console message to let me know we're getting anything:

Code: Select all

void Px3World::onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) { Con::printf("WE HAVE A CONTACT!!!"); for (physx::PxU32 i = 0; i < nbPairs; i++) { const physx::PxContactPair& cp = pairs[i]; if (cp.events & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) { Con::printf("WE HAVE A ROCKET CONTACT!!!"); } } }
Now, given all of the above, I would presume that whenever my filter shader sets a pair flag to eNOTIFY_TOUCH_FOUND, and/or (?) returns a value of eNOTIFY, that my onContact function should get a callback.

So far, no dice. Anything you can see that I might have missed?
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Tue Mar 13, 2018 6:38 pm
AHA!

Hehe, google is my friend. Turns out the missing ingredient was this:

Code: Select all

sceneDesc.simulationEventCallback = this;
(With "this" being my Px3World object.)

Still many details to resolve, but the function is getting called, so we got a foot in the door anyway. :D
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Wed Mar 14, 2018 8:30 am
Well, just to follow up, I got my rockets to explode on contact, but no thanks to all the fancy PhysX FilterShader logic, so far. The only useful output I've been able to get out of my custom filter is to always report all collisions to my callback function, at which point I can make sense of them in Torque.

While I did manage to construct a case where a rocket intersection with ground found a word0/word1 match and actually reported to me based on that, it was only in an empty world where I dropped my rocket onto the groundplane with no forward velocity. This could probably be debugged on the PhysX side, but time is precious, so for now I'm just setting things up to always notify. I'm not running a giant world simulation, so I don't think performance at this layer is going to be a major factor.

But anyway, back in my onContact function, it is possible to convert the PhysX actors' userData pointers back into sceneObjects and then PhysicsShapes, and from there get my shape IDs from my database and decide if we are rockets or not, and then destroy and cause ragdolls in nearby humanoids if yes. So fundamental objective has been met.
Timmy
Posts: 366
Joined: Thu Feb 05, 2015 3:20 am
by Timmy » Wed Mar 14, 2018 12:58 pm
This weekend i'll try and set aside a few hours to do up a demo for ya showing usage of the filter system and callback stuff, can't promise but will try ;) . If you don't already use it you will need this PR though https://github.com/GarageGames/Torque3D/pull/2186 (i'm sure it will get accepted one day into the main repo). Will let ya know how i get on.
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Thu Mar 15, 2018 2:44 am
Cool, thanks Timmy! No worries if you can't get to it, for my limited performance needs I think my callback-heavy solution is going to be fine, but it would still be nice to know how to do it the right way.
Timmy
Posts: 366
Joined: Thu Feb 05, 2015 3:20 am
by Timmy » Thu Mar 15, 2018 9:21 am
What ya want to do is to tie it into using this https://github.com/GarageGames/Torque3D ... UserData.h
chriscalef
Posts: 381
Joined: Mon Feb 09, 2015 7:48 pm
by chriscalef » Fri Mar 16, 2018 3:19 am
Huh, yeah I found that class and figured out how to use it to get back to my sceneObject in my onContact function. I don't understand what to do with the Signal type, however.

Here is my current attempt at an onContact class. I also got confused re: the failure of dynamic_cast to cast my void userData pointer into a PhysicsUserData pointer, but static_cast seemed to work so I went with that.

As you can see, all I'm doing for now is testing to see if either of the shapes in the collision is using my rocket shapeID, and if so destroying it.

Code: Select all

void Px3World::onContact(const physx::PxContactPairHeader& pairHeader, const physx::PxContactPair* pairs, physx::PxU32 nbPairs) { PhysicsShape *shape0=NULL, *shape1=NULL; PhysicsUserData *user0, *user1; physx::PxActor *actor0, *actor1; actor0 = pairHeader.actors[0]; actor1 = pairHeader.actors[1]; void *userData0 = actor0->userData; void *userData1 = actor1->userData; user0 = static_cast<PhysicsUserData *>(userData0); user1 = static_cast<PhysicsUserData *>(userData1); shape0 = dynamic_cast<PhysicsShape *>(user0->getObject()); shape1 = dynamic_cast<PhysicsShape *>(user1->getObject()); if (shape0) { if (shape0->mShapeID == 23) shape0->destroy(); } if (shape1) { if (shape1->mShapeID == 23) shape1->destroy(); } }
10 posts Page 1 of 1

Who is online

Users browsing this forum: No registered users and 3 guests