collisions

Hi, my name is Leandro.
My friends and I are developing a 3D game using Panda 3D. We are having some problems with the collisions. We use a sphere around our main character and activate the collision with geometry. The problem is that the main character is also a geometry, so the sphere collides with him and ruins everything.
Does anybody know how to fix it, or another way to detect collisions?
By the way, how many triangles has the panda model that we use at the tutorial? How many polygons the engine can handle with?

I really appreciate any help

Thanks a lot

Leandro

Panda does support collision tests against visible geometry, but this is only supported halfheartedly. The preferred way to test collisions is to use special collision solids modeled into the scene for this purpose. The artist who lays out the scene is then responsible for laying out the main walls of each room and putting spheres and tubes around smaller objects.

I don’t know whether the MAX converter supports Panda’s tags to identify collision geometry, but it is fully supported by the Maya and MultiGen converters.

If you still decide you’d rather test collisions against visible geometry, one trick is to put all the collidable geometry under a common node that is parented to render, and write your own collisionloop task (replacing the one in ShowBase.py) that starts the traversal at that node, rather than at render.

David[/img]

Can you give me an example of how to use de Collide Mask in collision detection?
I think this can solve my problems.

Thanks a lot

Leandro

The CollideMask can only be used when you are using the CollisionNode interface to use collisions; it is ignored when you have set_collide_geom(true).

CollisionNode *anode, *bnode;

anode->set_collide_mask(CollideMask::bit(1));
bnode->set_collide_mask(CollideMask::bit(2));

Now anode and bnode will not detect a collision with each other, since they have no bits in common. In Python, the equivalent statements will be:

anode.setCollideMask(BitMask32.bit(1))
bnode.setCollideMask(BitMask32.bit(2))

David

David,

I’m still having troubles with collisions. I’ve tried to use the masks, but it isn’t working. Here is the code: there are two models, panda and panda2. I’ve created the collisions spheres and the collision nodes. Then, i’ve created the masks and applied to the nodes. Finally, i’ve created the pusher and the traverser. I’m not using the collision against all geometry.

Am I doing something wrong? Did i miss something?

Thanks for your help

Leandro

##code##

self.csPanda = CollisionSphere(0, -1, 0, 9)
self.cnPanda = CollisionNode(“chPanda”)
self.cnPanda.addSolid(self.csPanda)
self.cnPandaAtachado = self.panda.attachNewNode(self.cnPanda)
self.cnPandaAtachado.show()
self.cnPanda.setIntoCollideMask(BitMask32().allOff())
self.cnPanda.setFromCollideMask(BitMask32().allOff())
self.cnPanda.setCollideMask(BitMask32().bit(2))

self.csPanda2 = CollisionSphere(0, -1, 0, 9)
self.cnPanda2 = CollisionNode(“chPanda2”)
self.cnPanda2.addSolid(self.csPanda2)
self.cnPanda2Atachado = self.panda2.attachNewNode(self.cnPanda2)
self.cnPanda2Atachado.show()
self.cnPanda2.setIntoCollideMask(BitMask32().allOff())
self.cnPanda2.setFromCollideMask(BitMask32().allOff())
self.cnPanda2.setCollideMask(BitMask32().bit(2))

self.pusher = CollisionHandlerPusher()
self.pusher.setInPattern(‘enter%in’)
self.pusher.setOutPattern(‘exit%in’)

cTrav = CollisionTraverser()
base.cTrav = cTrav
cTrav.addCollider(self.cnPanda2, self.pusher)
cTrav.addCollider(self.cnPanda, self.pusher)

##end##

Hi Leandro,

You have to tell your pusher which node it should push back on when the panda tries to walk through a wall. You can do something like this:

self.pusher.addCollider(self.cnPanda2Atachado, self.panda2)
self.pusher.addCollider(self.cnPandaAtachado, self.panda)

It should have given you a warning message, something like:

:collide(error): CollisionHandlerPusher doesn’t know about render/panda2/chPanda2, disabling.

Note that the above solution may not do what you want–I’m not sure exactly what it is that you do want. The addCollider() calls above will set up the pusher so that if one of the pandas tries to walk into something, e.g. the other panda, it will set the position of self.panda to a place outside of that something. But if you have another task resetting the position every frame (e.g. a LerpInterval), you may not see the pusher having any effect, since its efforts will be undone by your other task.

To play nicely with the collision handler, you need to set up a callback event handler on the collision event, and stop whatever it is that’s trying to move the panda in the case when a collision is detected and do something else instead. Or, you can write a custom task that moves the panda by a certain delta each frame, instead of using something like a LerpInterval.

You can call messenger.toggleVerbose() to watch all the messages go by; some of them will be about the detected collisions, so you can see the sorts of events you can listen for if you need to.

David

Another comment: if you are using the driveInterface to move the panda around directly from user inputs, the addCollider call would be something like this:

self.pusher.addCollider(self.cnPandaAtachado, self.panda, base.drive.node())

Note that if only one of your Pandas is moved around by user inputs and the other one just walks around under program control, you don’t need to add the second one to the collision traverser or create a pusher for it–any CollisionNode in the scene graph can serve as an obstacle for the object that’s actively responding to collisions.

David

1 Like

David,

First of all, thank you so much for your help. The collisions are working!

I have another question for you, but first I will explain exactly what I’m trying to do. I’m developing a RPG with PANDA3D. I will put the characters into a map, or dungeon and I want them to collide with the scenario and characters. First I’ve tried the collision with all geometry but
the character was colliding with his own collide sphere. Then I’ve tried the bitMask and now it’s working.
The question is:
The “pusher” makes the target to go back but I don’t want it. I just want to keep the target in place and stop the characters movement so they cannot pass through the target. I don’t want my characters pushing the walls, right? How can I do this?

Thanks for your help, again…

Leandro

Hello David,
my name is mauro and I’m one of Leandro’s friend that are developing the 3D RPG using PANDA3D.
I’ll try to explain a little better what we are trying to do:
we’re developing this game with a 3rd person view, so that you can see the character you control.
We need to have this main character colliding with all the geometry(like when we use setCollideGeom(1)).
but whe we try to use this, the colision solid collides with the main character too. so we need to have the sphere to collide with everything except the main character model.
Thanks a lot for your help
Mauro

The CollisionHandlerPusher is probably the right choice in this case. It pushes back on the thing which is registered with the CollisionTraverser, which in this case would be your character. By “pushing back” I mean that it pushes back in the right amount to cancel your character’s forward motion, thus stopping your character from going through walls.

Used properly, the pusher will not push the walls out of their proper place. If you are observing the walls being moved, it means that you must have created a CollisionHandlerPusher for the walls themselves, which you don’t need to do–you only need the pusher for the object which is actually moving.

It sounds like you are doing the right thing with the CollideMask–attempting to use collide-with-geometry to detect the walls is probably a bad idea.

David

does it means that we need to put colision solids all over the enviroment?
since we’re making an engine, it’ll be very unreasonable…
sorry to keep bothering you, it’s just that this is the last point we need to do in our RPG engine.
could you give us an exemplo (python) how we do that?
anothe question, why whe the collide with geometry is on, the shpere doesn’t collide with the floor?

Thanks
Mauro

Hi Mauro,

You should be putting collision solids all over the environment. It’s not any more work than putting in visible polygons, which you are already doing.

Even if you did not have this requirement in Panda, it is almost always a good idea to create separate geometry, different from the geometry that is to be rendered, for the purposes of testing collisions. This is because the needs of collision tests are inherently different than the needs of rendering. Collision tests are generally performed against a much lower-resolution model than the one that you create for rendering.

You would normally create collision polygons in the modeling package, at the same time you create the visible polygons. What program are you using to define your levels?

I don’t know why you’re not colliding with the floor when you have visible geometry collisions on.

David

Hi David,
I’m not sure if I understood that part… , see if we are making it right:
We’re making the 3D Models on 3D MAX, nothing special, only some movements (I don’t know about the visible/collidable geometry stuff you said)
Then we have 2 option :

  1. make a collision sphere on the main character to make it collide with the other collisions spheres (by the way, the sphere is the only solid that actually collides). In this I should put the collision solids all over the place, on the building of the scenary, on the objects like trees and rocks…

2)make a collision sphere near the main character adn turn collide with geometry on. the only problem is that in this mode we can’t put the sphere “around” the main character, or he’ll “collide with himself”, so we had to put o the front of him. but then he would collide with the other member of the party (who he wasn’t supposed to collide).

so the best choice, would be the first, since we can decide which object will collide with tha main character. but it will demand a lot more work to put the collision solid all around the scenario (to make things worse, the only collision solid working is the sphere).

is that right? we don’t have anyway to “disable” collide with some of the objects in the collide with geometry mode?

by the way, do you have any idea why the collisionplan or the collision tube don’t work like the sphere?

Thanks
Mauro

Hi Mauro,

Sorry for the long delay in replying.

I think your analysis is correct. Between options (1) and (2) I recommend option (1) as the more efficient choice. However, to make option (2) easier I have just checked in changes to Panda to support using the CollideMask on GeomNodes, so you can now have collide-with-geom enabled and only collide with some geometry, not all geometry. (It will be some time until the changes I have made are available in the CMU distribution; you will need to get the latest code from CVS and build Panda from source if you want this change sooner.)

To generate collision solids in the modeling package, you need to be able to insert the code { barrier } within a entry that is intended to represent invisible collision polygons, rather than visible polygons. I don’t know if there is a way to do this with the 3DSMax converter; I suspect there is not (but our CMU friends may be able to tell me otherwise). If there is not, you may need to edit the egg file and do this by hand. You can also use { sphere } to create a CollisionSphere.

It is true that the only CollisionSolid type that actually collides with other CollisionSolids is the CollisionSphere, so you can only put a sphere around your avatar. This is because we have implemented only the sphere-polygon, sphere-plane, sphere-sphere, and sphere-tube intersection tests. If you want to put (say) a CollisionTube around your avatar, you would need the tube-polygon, tube-plane, tube-sphere, and tube-tube intersection tests as well. If you’d like to implement these, I’d be happy to incorporate your work into Panda. :slight_smile: But for the most part, we have found that a sphere around the avatar is sufficient.

David

does adding the < objectType > { barrier } code to an object automatically make it a collision solid or would i have to set a specific bitmask if i want to collide with it?

The < objectType > { barrier } flag makes an object a CollisionSolid–specifically, it turns it into a series of CollisionPolygons. There are also other object types that make it into a sphere or a tube or whatever.

You might still need to set a particular bitmask on it if you don’t want it to have the default bitmask (and you can also do this in the egg file with, e.g., collide-mask { 0x01 }), but you don’t need to do this in order to collide with it.

David