How to add CollisionSolid

After reading the documentation about CollisionSolid,I still can not understand it. Could someone give me some code examples?
There are three models that I load into the game. I want the animal can not walk through the wall, and when the animal touch the orangeball, the model of the ball disapear. All three models need to create CollisionSolids interactively in program code.
I really need help. Thank you very much.

self.orangeball = loader.loadModel("models/orangeball") 
self.orangeball.reparentTo(render)
self.orangeball.setPos(20,20,0)

self.wall = loader.loadModel("models/wall") 
self.wall.reparentTo(render)
self.wall.setPos(-10,-10,0)

self.animal = Actor("models/animal",
{"run":"models/animal-run",
"walk":"models/animal-walk"})
self.animal.reparentTo(render)
self.animal.setScale(.2)
selfanimal.setPos(ralphStartPos)

I believe that there is in fact a full, heavily-commented example a little further on in the manual.

A quick note about the code that you posted: You create an object named “self.animal”–and then go on to attempt to operate on an object named “self.ralph”, without ever creating the latter. Should “self.ralph” not be “self.animal”?

Thank you. That’s an error. But how to avoid the animal to walk through the wall? Because I only see method that add a polygon to the model. How to use the own shape of the model?
Could you help me please.

Where are you looking? At the SDK page for NodePath?

Look again at what the manual says on the “Collision Solids” page. To quote the manual:

First we create a collision solid; then we create a collision node, and attach it to our NodePath; finally, we add the solid to the node (note! Not to the NodePath!).

For that, look to the manual page that covers Collision Handlers, and at the CollisionPusher example given later in the manual.

You want to use the model’s geometry? Ah, that’s a little more complex. For one, I’m not sure of whether it works with animated models (Actors)–at the least I’m pretty confident that it won’t follow the animations of the model. Further than that, however, I’ll defer to others for the most part: I’ve only done this as part of the process of exporting a model (and only successfully with a static–that is, non-animated–model), as far as I recall.

Yes, I want to use the model’s geometry. And the model is static, I want to get the shape of the buildings. Could you tell me how to do that?

Thank you very much.

The easy and modeling-software-agnostic method would be to open the egg file in any text editor and add to a topmost group the magic line:
object { polyset keep descend }

So if your model looks something like this:

<CoordinateSystem> { Z-Up }

<Texture> Tex1 {
  arch.png
  <Scalar> format { rgba }
  <Scalar> wrapu { repeat }
  <Scalar> wrapv { repeat }
  <Scalar> minfilter { linear_mipmap_linear }
  <Scalar> magfilter { linear }
  <Scalar> envtype { modulate }
}
<Group> house1 {
  <VertexPool> house1.verts {
    <Vertex> 0 {
      -23.7565 -24.4991 30.4252
      <UV> {
        0.0835191 1.00008
        <Tangent> { 0 1 0 }
        <Binormal> { -0.707105 0 -0.707108 }
      }
      <Normal> { -0.707108 0 0.707105 }
      <RGBA> { 1 1 1 1 }
    }
    <Vertex> 1 {
      -23.7565 -24.4991 30.4252
      <UV> {
        0.29289 0.519082
        <Tangent> { 0 1 0 }
        <Binormal> { 0.707106 0 -0.707108 }
      }
.
.
.
.
.

then change it to:

<CoordinateSystem> { Z-Up }

<Texture> Tex1 {
  arch.png
  <Scalar> format { rgba }
  <Scalar> wrapu { repeat }
  <Scalar> wrapv { repeat }
  <Scalar> minfilter { linear_mipmap_linear }
  <Scalar> magfilter { linear }
  <Scalar> envtype { modulate }
}
<Group> house1 {
<Collide> object { polyset keep descend }
  <VertexPool> house1.verts {
    <Vertex> 0 {
      -23.7565 -24.4991 30.4252
      <UV> {
        0.0835191 1.00008
        <Tangent> { 0 1 0 }
        <Binormal> { -0.707105 0 -0.707108 }
      }
      <Normal> { -0.707108 0 0.707105 }
      <RGBA> { 1 1 1 1 }
    }
    <Vertex> 1 {
      -23.7565 -24.4991 30.4252
      <UV> {
        0.29289 0.519082
        <Tangent> { 0 1 0 }
        <Binormal> { 0.707106 0 -0.707108 }
      }
.
.
.
.
.

You don’t have to name the node ‘object’, anything will do.

Thanks. But I don’t know how to use the node. I try the follow code but it does not work.

base.cTrav = CollisionTraverser()
        pusher = CollisionHandlerPusher()
        cNode = CollisionNode('self.cat')
        cNode.addSolid(CollisionSphere(0, 0, 0, 1.1))
        catC = self.cat.attachNewNode(cNode)
        catC.show()
        
        self.walls = self.environ.find("**/house_1")
        self.walls.node().setIntoCollideMask(BitMask32.bit(0))
        self.walls.show()
 
        # Add the Pusher collision handler to the collision traverser.
        base.cTrav.addCollider(self.walls, pusher)
        # Add the 'frowney' collision node to the Pusher collision handler.
        pusher.addCollider(self.walls, self.environ, base.drive.node())

That error means that the result of find() failed. Try calling .ls() to see a graph of all the nodes printed out, so that you can be sure to pass the correct name to find().


Isn’t that node call ‘house_1’? Which one should I use?

The CollisionNode. For some reason it seems to be called “house_1:House002:Object__0”.

21888 polygons could be a wee bit much for the collision detection system :wink:

I create a new shape to use it. But when I let the cat walk, it went through the wall. And then an error printed out.

My code is

base.cTrav = CollisionTraverser()
        pusher = CollisionHandlerPusher()
        
        self.walls = self.environ.find("**/pCylinder1")
        
        self.walls.node().setIntoCollideMask(BitMask32.bit(0))
        self.walls.show()
 
        # Add the Pusher collision handler to the collision traverser.
        base.cTrav.addCollider(self.walls, pusher)
        # Add the 'frowney' collision node to the Pusher collision handler.
        pusher.addCollider(self.walls, self.environ, base.drive.node())

It looks as though the problem is that you’re treating the walls as an “active”/“from” object–and object that should be tested against other objects–rather than as a “static”/“into” object–and object that other objects collide with.

Aside from being potentially inefficient, the Panda collision system only allows collisions from a small sub-set of its solids–just rays, lines, segments and spheres, if I recall correctly–that is, it only allows objects using those shapes as “from”/“active” objects, while allowing any shape as a “static”/“into” object.

In short, add your active object–your cat, I think that you mentioned–to the collision -traverser and -handler, not the walls. (And use a sphere, or some arrangement of rays, segments or lines, (more likely the sphere) for the cat’s collision shape.)

Thank you very much. I add cat to the collision and it does not walk through that model. But I’m not sure about “static”/“into” object. Doesn’t the below code mean “self.wall” is a “static”/“into” type?

self.walls.node().setIntoCollideMask(BitMask32.bit(0))

At first it works well. But after a few seconds, the cat went into the floor.

And why the texture have so many white points? Is there something could avoid this problem?

I’m glad that you’re making progress. :slight_smile:

No; the code that you posted there just sets the mask to be used when the object is collided with/into.

I was mistaken above when I identified “static” objects with “into” objects and “active” ones with “from” objects–my apologies for this! A better description would be to say that “static” objects can only be “into” objects, while “active” objects may act as both “into” and “from” objects.

For example, a static wall won’t be tested against other objects. An active ball, however, will be tested against all other objects–including the aforementioned wall–as long as the relevant masks match up; this means that if there are two active balls, they may be tested against each other.

In short (and slightly simplified), if I have it correct myself, the objects that you tell the CollisionTraverser to handle are “active” objects, to be tested against all other objects according to their masks; objects not added to a traverser are “static” objects.

As for the masks, if I recall correctly an “active” object is tested against another object (whether “active” or “static”) if the “from” mask of the “active” object being tested matches the “into” mask of the other object–again, regardless of whether the other object is “active” or “static”.

How are you handling gravity and character movement?

That just looks like z-fighting between the standard visible geometry and the representations of the collision geometry; it should go away when you make the collision geometry invisible again.

Thank you very much. Now I solve these two problems.