Finding a node that an object collided with?

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
thesmileman
Posts: 360
Joined: Tue Feb 10, 2004 2:20 am
Location: Lubbock, TX

Finding a node that an object collided with?

Post by thesmileman »

I have the below code to handle collision of a ball that bonces off of walls and to set its new velocity. But now I need to find out what node it collided with. The only way I can think of is to have each object as its own triangle selector(Right now I am using a metaTriangle selector). I am not sure how I can uses several triangle selectors for my ball to colide with as it requires only one when setting up collsion detection for the ball. Any ideas or better yet code!!! Thanks!

Code: Select all

ps4->setPosition(newLoc);
newLoc = irrSceneMgr->getSceneCollisionManager()->getCollisionResultPosition(metaSelector, 
oldLoc, core::vector3df(6,6,6), velocity,     // position, radius, move vector 
triout, outFalling, 0.5f, core::vector3df(0, 0, 0));   // gravity 

if (triorg != triout)  {	
// Collision Detected Wahoo now handle that mother 
core::vector3df n = triout.getNormal().normalize(); 
velocity = (velocity - n * 2.0 * (velocity.dotProduct( n))).normalize() * velocity.getLength(); 
thesmileman
Posts: 360
Joined: Tue Feb 10, 2004 2:20 am
Location: Lubbock, TX

Post by thesmileman »

Anyone got any ideas? I really would appreciate them. :D
Mercior
Posts: 100
Joined: Tue Feb 24, 2004 1:53 am
Location: UK
Contact:

Post by Mercior »

The only way is tho give each object a triangle selector then design your game in such a way that all objects derive from this class with the triangle selector so that you can collide things with every object in your world. This way you can make specifica callbacks for collisions between various objects (like a fireball hitting a player).

A nice feature for 0.7 might be an AddTriangles(ISceneNode *) member for the ITriangleSelector so we group multiple nodes into 1 selector.
Guest

A very important question!

Post by Guest »

I do _not_ really have THE IDEA how to solve that problem. So what do we have? We have a triangle (we collided with),a MetaTriangleSelector and a lot of ISceneNodes (we could have collided with).

So, what do we need to know MORE? Well, it is probably quite useful to know what TYPE of node collided with what TYPE of node. (sorry, bad english) But in fact if you fire a rocket on a wall, the wall keeps on staying but if you hit a little rabbit... you can imagine :-).

So one way of doing something like handling the collision detection is:

Derive a ICollSceneNode from ISceneNode and add a virtual method called somthing like

Code: Select all

virtual const ICollSceneNode* ICollSceneNode::OnCollision( const irr::ITriangle& _tri, const ICollSceneNode* _node) const;
and a method returning the type of an object. Something like:

Code: Select all

// we need an attribute to safe the typeinfo
class ICollISceneNode : public ISceneNode
{ 
...
const irr::s32 TypeID;
...
};
// here is the method
const irr::s32 ICollSceneNode::getTypeId() const { return TypeID; };
If you now build a new interface for an object (maybe a little rabbit :-)), do it like that.

Code: Select all

IKillableRabbit : public ICollSceneNode
{
//... like in the ISceneNode tutorial you have to overload some abstract functions
// pseudo code in a header, dopple bad :-(
const ICollSceneNode* OnCollision( const irr::ITriangle& _tri, const ICollSceneNode* _node) const
{
  if( _tri in TriangleSelector)
  {
  switch( _node->getTypeID())
  // ... case
  case TheCruelRocket: // blow the rabbit
  // ...so far so good
  return this;
  }
} // IKillableRabbit

const IKillableRabbit::TypeID = KillAbleRabbitID; // so we have a hardcoded id of each rabbit
// somewhere of your probject should be a enumaration of all objects
enum ECollObj
{
  KillABleRabbitID = 1,
  TheWall = 2
}

So how does it the collision look like. Well, Irrlicht tells you that a collision has happend, your code _on top_. Now, we go through each object in a list of ICollSceneNodes, everyone needs to have a its TriangleSelector attached to it if it can collide. If the triangle we collided with is one of the objects triangles in the selector... we react, see switch and return a pointer to the object so we can handle the collision.

Code: Select all

void yourfunction()
{
  //collision has happened

  // loop through all ICollSceneNodes
  for(..)
  {
     if ( ICollisionNode* _coll = node->OnCollision( triout, this))
     {
        // here we go...
        switch (_coll->getTypeID)
        case KillableRabbitID: 
        // blow, reflect do whatever you like
      }
   }
}
PS: sorry, about the rabbit
Guest

hmmm...

Post by Guest »

I cannot edit my post. Well, you have to return NULL in the OnCollision method if the triangle was not found in the triangleselector.

Have phun
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

hehe

Post by schick »

ok, now i know why i couldnt edit it. I wasn't logged in.
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

Thinking...

Post by schick »

another method would be to add an OnEvent() method to each ISceneNode and add a Collision event.

...
struct CollEvent
{
// have i forgotten anything?
irr::ITriangle tri;
irr::s32 ID; // which sent the event
};

So if a collision has happend you push up the event and go through all nodes. And the node which has a triangle colliding with that triangle (see Irrlicht docu) reacts on the collision, if it is not the node which was sending the event and sends back a CollisionEvent with the the triangel it has collided with and its ID.

You can get the node you have collided with by calling getSceneNodebyID().
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

more thinking...

Post by schick »

Hmmm, as far as i see, i like my 2nd method much more. So what you have to do:

Every scenenode has its ITriangleSeletor of all nodes which it can collide with. Every gameloop we update the position of the scenenode and check if a collision has happened. If so we post an event. The event goes through all scenenodes... if the node was found (do some cool collision stuff) which we have collided with, be careful that we do not collided with ourselves. The node will send back a collision event back to the original node. You can receive a pointer by calling mgr->getSceneNodeByID().

+:
- easy to use and clear
- collision with a known object (event.ID)
-:
- slow we have to go through all scenenodes and check for collision
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

maybe...

Post by schick »

I still think the 2nd method is quite good. Since everything is managed through the scenemanager its easy to implement new stuff just from deriving a new scenenode and adding some events.


But in fact i would add some more information to the collision event.

Code: Select all

struct CollEvent
{
  irr::s32 ID; // id of the node
  irr::s32 TypeID // type of the node
  irr::ITriangle Triangle; // collision triangle
};

+:
- every nodes knows whats going on but do not need to react
- ability to filter through types, faster...

So what to do? Well you have to change the postEvent() method in the ISceneManager class (just go thorugh all scenenodes and call OnEvent()). You have to add a virtual function to all scenenodes called void OnEvent() which does not do anything and a const TypeID attribut. The attribute needs to have a default value for all nodes which do not care about collisions.You can see the code above how to give a const value to a class.
Liamx

Re: maybe...

Post by Liamx »

schick wrote:So what to do? Well you have to change the postEvent() method in the ISceneManager class (just go thorugh all scenenodes and call OnEvent()). You have to add a virtual function to all scenenodes called void OnEvent() which does not do anything and a const TypeID attribut. The attribute needs to have a default value for all nodes which do not care about collisions.You can see the code above how to give a const value to a class.
Hi.
I think I'm interested in doing that event stuff but I couldn't understand what to do.
When you say "to change the postEvent() method in the ISceneManager class", does it mean to change the Irrlicht source or some kind of subclass? I don't get it. I would appreciate if you can explain the process with a little bit of details. Thanks.
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

Post by schick »

I just dont have enough time to make a much more detail description. But i was rethinking and the best way is probably to use something like a physics manager and let it make all collision collbacks.

So you got a physics manager and some nodes (i may call them collision nodes). If a event happens may it be something like node moved or node collided you call the node->OnMove() or node->OnCollision() methods. The irrlicht collision engine was not designed to be as great as those from the physics engines so why not use them. I hope to get some code working that day... maybe at evening.

I hope to make it that easy that you only have to overload some functions to get a fully collision event system working.[/code]
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

time is running out...

Post by schick »

The core system should be ready but i do not have enough time to test it. So it will take about 3 hours more to get the first version working.

The system looks like:

A physics manager:

handles events:
OnPrepare(): called before each update
OnTransform(): if a node position has changed
OnLeaveWorld(): node left the world
OnCollision(): collision has taken place
OnContactProcess(): Collision is being calculated
OnContactEnd(): Collision was calculated

A physics node:

handles events (as above):
virtual void OnCollision()
virtual void OnTransform()
virtual void OnPrepare()
virtual void OnLeaveWorld()

If you now want to make a scenenode (from irrlicht) be a physic node you only have to:

1. derive a custom node from iscenenode (ianimatedmesh...) and physics node
2. overload registerNode()
tell the physics manager how the node looks like and make it collideable
3. overload OnPrepare()
update the position of the scenennode the same as the physics node

and every gameloop you have to physicsmanager->step( deltatime)

if you want a scenenode to be deleted just call node->unregister()

Thats it :-) thats how it should be...
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

:-(

Post by schick »

Somewhere are some bugs, well it isnt working yet, but i hope to get some free time next week to finish the code.

If you like to debug the code or just have a look at it here you go:

http://jens.schick.bei.t-online.de/file ... Physic.rar

There is a example scenenode which is supposed to fall down... but it keeps on staying :-(. But its easy to see how simple the code looks like to add real physic bahaviour to a scenenode.

To compile the code yourself you need irrlicht sdk :-) and the newton sdk http://www.physicsengine.com/ . The functions are commented, the code aint very good.

Very much thanks to Mercior for his great tutorial about the newton sdk.
Liamx

Post by Liamx »

It would be great if this code could be finished. It is what I'm looking for. Thanks a lot.
schick
Posts: 230
Joined: Tue Oct 07, 2003 3:55 pm
Location: Germany
Contact:

woohoo

Post by schick »

The very first version is out now!!!. Well, there are only 2 nodes available CCollisionOctTreeSceneNode, CTestNode. But it is not a big task to add all other scenenodes this week. Furthermore, ill add some helper methods to make controlling the physic engine easier.

Thanks to Mercior, i used his map and his great tutorial.

Here are the files:

The binary demo (you have to "fly" to the middle of the map because spawing the cubes is hard coded, then press left mouse key as often you want to):

http://www.bluffel.de.vu/files/NewtonPhysic_bin.rar

The src (keep in mind you need to have newton sdk and the irrlicht sdk installed):

http://www.bluffel.de.vu/files/NewtonPhysic_src.rar
Post Reply