chriscalef Posted March 12, 2018 Share Posted March 12, 2018 (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/forums/viewthread/130395But 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. Quote Link to comment Share on other sites More sharing options...
Timmy Posted March 12, 2018 Share Posted March 12, 2018 Check out here @chriscalef http://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/guide/Manual/AdvancedCollisionDetection.html, the PxSimulationEventCallback is what you want. Works along the lines of that old physx 2.x method in that thread you posted Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 12, 2018 Author Share Posted March 12, 2018 Ah, very interesting ^^^ thank you. Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 13, 2018 Author Share Posted March 13, 2018 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: class Px3World : public PhysicsWorld, public physx::PxSimulationEventCallback 2) Added the following function definitions/declarations to keep up with the virtuals: 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: 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: sceneDesc.filterShader = MegamotionFilterShader; 5) Added a new category to the Px3CollisionGroup enum, to cover my explosive objects: 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: 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? Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 13, 2018 Author Share Posted March 13, 2018 AHA! Hehe, google is my friend. Turns out the missing ingredient was this: 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 Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 14, 2018 Author Share Posted March 14, 2018 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. Quote Link to comment Share on other sites More sharing options...
Timmy Posted March 14, 2018 Share Posted March 14, 2018 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. Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 15, 2018 Author Share Posted March 15, 2018 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. Quote Link to comment Share on other sites More sharing options...
Timmy Posted March 15, 2018 Share Posted March 15, 2018 What ya want to do is to tie it into using this https://github.com/GarageGames/Torque3D/blob/development/Engine/source/T3D/physics/physicsUserData.h Quote Link to comment Share on other sites More sharing options...
chriscalef Posted March 16, 2018 Author Share Posted March 16, 2018 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. 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(); } } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.