Sign in to follow this  

PhysX collision detection

This topic is 3572 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I was wondering if anyone knows how to check which 2 entities are colliding against each other with ageia PhysX. I want to know this in order to play a specific sound when it happens. I couldn't find anything in the documentation. But then again, the English language isn't my native language so i wouldn't know how ageia called it. I'd really appreciate it if someone told me how this is done. I've been looking for days.. Thanks in advance!

Share this post


Link to post
Share on other sites
It's a piece of cake. What you need to do is define a class that derives from NxUserContactReport, and that over-rides the function "void onContactNotify (NxContactPair& pair, NxU32 events)". Then at runtime after you've created your scene, you call NxScene::setUserContactReport and pass it a pointer to an instance of the class you created. After this, you must specify for which actors you want to receive contact reports. You can either explicitly set pairs of actors with NxScene::setActorPairFlags, or set pairs of actor groups using NxScene::setActorGroupPairFlags. You'll need to also specify one or more flags to set when you'd like to be notified of a collision, these include NX_NOTIFY_ON_START_TOUCH, NX_NOTIFY_ON_END_TOUCH, and NX_NOTIFY_ON_TOUCH. This is all documented in the page called "Contact Reports", which you can find in Guide->Collision Detection.

Once you've set this up, the onContactNotify method of your contact report class will be called whenever a collision between a marked pair of actors or two actors belonging to a pair of marked groups. What you do at this point is up to you...I like to route contact reports to other member functions using boost::function and boost::bind. You could simply place the report in a queue, or call member functions on the classes that "own" the actors (typically you store a pointer to the owning class in the actor's userData member).

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
It's a piece of cake. What you need to do is define a class that derives from NxUserContactReport, and that over-rides the function "void onContactNotify (NxContactPair& pair, NxU32 events)". Then at runtime after you've created your scene, you call NxScene::setUserContactReport and pass it a pointer to an instance of the class you created. After this, you must specify for which actors you want to receive contact reports. You can either explicitly set pairs of actors with NxScene::setActorPairFlags, or set pairs of actor groups using NxScene::setActorGroupPairFlags. You'll need to also specify one or more flags to set when you'd like to be notified of a collision, these include NX_NOTIFY_ON_START_TOUCH, NX_NOTIFY_ON_END_TOUCH, and NX_NOTIFY_ON_TOUCH. This is all documented in the page called "Contact Reports", which you can find in Guide->Collision Detection.

Once you've set this up, the onContactNotify method of your contact report class will be called whenever a collision between a marked pair of actors or two actors belonging to a pair of marked groups. What you do at this point is up to you...I like to route contact reports to other member functions using boost::function and boost::bind. You could simply place the report in a queue, or call member functions on the classes that "own" the actors (typically you store a pointer to the owning class in the actor's userData member).



Hi MJP,

Thank you very much for your reply!

I didn't quit understood your pseudo code explanation. So I was googeling up "contact report physx" and found this sample code:


class NxAgeiaContactReport : public NxUserContactReport
{
public:
virtual void onContactNotify(NxContactPair& pair, NxU32 events)
{
ContactReport contactReport;
NxAgeiaPhysicsHelper* ActorOne = NULL;
NxAgeiaPhysicsHelper* ActorTwo = NULL;

if (pair.actors[0] != NULL && pair.actors[1] != NULL)
{
// Iterate through contact points
NxContactStreamIterator i(pair.stream);
//user can call getNumPairs() here
while(i.goNextPair())
{
//user can also call getShape() and getNumPatches() here
while(i.goNextPatch())
{
//user can also call getPatchNormal() and getNumPoints() here
contactReport.nxVec3crContactNormal = i.getPatchNormal();
while(i.goNextPoint())
{
//user can also call getShape() and getNumPatches() here
contactReport.lsContactPoints.push_back(i.getPoint());
contactReport.nxVec3crContactNormalForce = pair.sumNormalForce;
contactReport.nxVec3crContactFrictionForce = pair.sumFrictionForce;
}// end while(i.goNextPoint())
}// end while(i.goNextPatch())
}// end while(i.goNextPair())

ActorOne = (NxAgeiaPhysicsHelper*)(pair.actors[0]->userData);
ActorTwo = (NxAgeiaPhysicsHelper*)(pair.actors[1]->userData);

if(ActorOne)
{
if(ActorOne->GetAgeiaFlags() & AGEIA_FLAGS_GET_COLLISION_REPORT )
{
ActorOne->CallCollisionCallback(contactReport, *pair.actors[0], *pair.actors[1]);
}
}

if(ActorTwo)
{
if(ActorTwo->GetAgeiaFlags() & AGEIA_FLAGS_GET_COLLISION_REPORT )
{
ActorTwo->CallCollisionCallback(contactReport, *pair.actors[1], *pair.actors[0]);
}
}
}
} // end function
}; // end class


Is this what you mean?

Thanks in advance!

Share this post


Link to post
Share on other sites
Yes, that's one possible of way of doing what I was talking about. It also does some other things that wouldn't be relevent for just making a sound, but the important parts are this:

-The class "NxAgeiaContactReport" here derives from "NxUserContactReport", and overrides "onContactNotify".
-When "onContactNotify" gets called, the function pulls out the two actors that have collided by referencing pair.actors[0] and pair.actors[1].
-The function casts the "userData" member of the two NxActor objects to the type "NxAgeiaPhysicsHelper", and calls their CallCollisionCallback method

The first two steps are relatively simple. I'm sure you know how to derive a class from another, and override the function. The third part you'll may have to change up a bit, depending on the actual classes you're using on your game. In your case you'll probably want to set the "userData" member of each NxActor to point to whatever class you use for in-game objects that have physics data. So let's say you have in your game a base class CPhysicsObject, and from that you derive a class CSpaceship. Your CPhysicsObject class would have a member function, similar to CallCollisionCallback, that you would call every time that object is involved in a physics collision. So in your "onContactNotify" function, you would cast the userData member (using reinterpret_cast of course, since you're a smart C++ programmer) to type "CPhysicsObject", and then call it's "OnCollision" method (or whatever you decide to call it). Then if the CPhysicsObject happens to be a CSpaceship type and you use virtual functions, you could have the CSpaceship object emit some kind of sound in response to the collision, and you could have it depend on the type of object it collided with too.

The only part not mentioned in that code you posted is registering your collision types. Like I said in my first post, you have to either register groups or specific pairs of NxActor's that you want to receive collision reports for.

Hope this helps you get started...let me know if you need more help.

Share this post


Link to post
Share on other sites
Quote:
Original post by MJP
Yes, that's one possible of way of doing what I was talking about. It also does some other things that wouldn't be relevent for just making a sound, but the important parts are this:

-The class "NxAgeiaContactReport" here derives from "NxUserContactReport", and overrides "onContactNotify".
-When "onContactNotify" gets called, the function pulls out the two actors that have collided by referencing pair.actors[0] and pair.actors[1].
-The function casts the "userData" member of the two NxActor objects to the type "NxAgeiaPhysicsHelper", and calls their CallCollisionCallback method

The first two steps are relatively simple. I'm sure you know how to derive a class from another, and override the function. The third part you'll may have to change up a bit, depending on the actual classes you're using on your game. In your case you'll probably want to set the "userData" member of each NxActor to point to whatever class you use for in-game objects that have physics data. So let's say you have in your game a base class CPhysicsObject, and from that you derive a class CSpaceship. Your CPhysicsObject class would have a member function, similar to CallCollisionCallback, that you would call every time that object is involved in a physics collision. So in your "onContactNotify" function, you would cast the userData member (using reinterpret_cast of course, since you're a smart C++ programmer) to type "CPhysicsObject", and then call it's "OnCollision" method (or whatever you decide to call it). Then if the CPhysicsObject happens to be a CSpaceship type and you use virtual functions, you could have the CSpaceship object emit some kind of sound in response to the collision, and you could have it depend on the type of object it collided with too.

The only part not mentioned in that code you posted is registering your collision types. Like I said in my first post, you have to either register groups or specific pairs of NxActor's that you want to receive collision reports for.

Hope this helps you get started...let me know if you need more help.



Hi MJP,

Thanks for your reply!

I made a base class CPhysicsObject and from that class i derived the class Alien from.

At the moment i know the CPhysicsObject has to have the function CallCollisionCallback. Wondering what it's return type should be of this callback function.

Also, i am not sure what else those 2 classes need to have and where to set the contact flag. My guess for putting the flag is in the NxAgeiaContactReport class at the start this function:

gScene->setActorPairFlags(*ActorOne, *ActorTwo, NX_NOTIFY_ON_TOUCH);

Do you have a sample code for doing this i could have a look at?

Thanks in advance!

Share this post


Link to post
Share on other sites
Quote:
Original post by Yustme

At the moment i know the CPhysicsObject has to have the function CallCollisionCallback. Wondering what it's return type should be of this callback function.



Make it whatever you need it to be. This has nothing to do with PhysX or anything, so you can just make it void if you'd like.

Quote:
Original post by Yustme
Also, i am not sure what else those 2 classes need to have and where to set the contact flag. My guess for putting the flag is in the NxAgeiaContactReport class at the start this function:

gScene->setActorPairFlags(*ActorOne, *ActorTwo, NX_NOTIFY_ON_TOUCH);


You should put that code wherever it makes sense to do it. I would guess you'd want to put it somewhere in a "level" class perhaps, since setting the collision pairs requires global knowledge of all of the actors that are going to be in your scene. This might even be a good thing to build into your map file (if you use one).

Personally I like to use groups instead, with each group having a set meaning across the entire game. I'll usually make a little table for myself that looks like this:



Then what I'll do is I'll have objects add themselves to the groups that they fit into.


Quote:
Original post by Yustme

Do you have a sample code for doing this i could have a look at?



Sorry, not at the moment. When I have access to my code I'll see if I can dig something up.

Share this post


Link to post
Share on other sites

This topic is 3572 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this