CollisionHandlerPusher Problems

I’m attempting to use CollisionHandlerPusher for my collisions. I’m manually moving the camera around, and have a sphere solid attached to the camera. The camera sphere has a pusher and traverser connected with it, which is in turn connected to base.cTrav.

self.node = base.camera.attachNewNode( CollisionNode( 'player' ) )
self.node.node().addSolid( CollisionSphere( 0, 0, 0, 5 ) )
self.node.node().setFromCollideMask( CollisionNode.getDefaultCollideMask() )
self.parentNode = base.camera;
self.pusher = CollisionHandlerPusher()
self.pusher.addCollider( self.node, parentNode )
self.traverser = CollisionTraverser()
self.traverser.addCollider( self.node, self.pusher )
self.traverser.setRespectPrevTransform( True )
base.cTrav = self.traverser

I am moving the camera manually each frame with a task:


base.camera.setFluidPos( self.position )

I have tried to use this collision setup against a plain sphere and the raw geometry of environment.egg. In both cases, the camera initially stops when it collides with the solid. But it slowly begins pushing into it and then just pops through.

I thought it might just be pushing itself around the spheres and geometry in the model, so I tried it with a plane, and the same thing occured. It just popped through the plane.

I also saw this same behavior with the CollisionHandlerPusher example from the manual.

Is there something else I should be doing to prevent this from happening? Is CollisionHandlerPusher usable for normal FPS type movement where a player can push up against a wall continuously?

The CollisionHandlerPusher is appropriate for applications in which the user can continually push up against a wall, but there are things you have to take into consideration.

First, you have to accept that users will occasionally get through walls, despite your best efforts. No collision system is perfect, not even the one that comes with the $50,000 commercial physics engine you might buy. As collision systems go, Panda’s is merely adequate.

Still, a pop through a wall should be very rare. It is easier to pop through polygons than CollisionSpheres and CollisionPlanes. In fact, it is impossible to pop through a CollisionPlane, so I infer that by “plane” you really meant a big polygon.

One thing that can make it more likely to pop through a wall is if you allow your system to keep tunneling the object deeper and deeper into the wall. Once you are, say, 1,000 feet into the wall, it’s hard for the collision system to resist.

In your example, do you re-update self.position from your node’s position as updated by the CollisionHandlerPusher? If you don’t, and self.position keeps growing without respect to the walls, then you will eventually pop through. Usually, the easiest way to fix this is to do something like self.position = node.getPos() every frame.

David

Thanks for the response. This makes me want to laugh because I was running into this identical problem when I was writing a BSP engine a few years ago. I think it’s my curse. :frowning:

I don’t think I’m using a really big polygon, unless CollisionPlane is doing that behind the scenes.

worldCollision = render.attachNewNode( CollisionNode( "worldCollision" ) )
worldCollision.show()
worldCollision.node().addSolid( CollisionPlane( Plane( Vec3( 0, 0, 1 ), Point3( 0, 0, -10 ) ) ) )
#worldCollision.node().addSolid( CollisionSphere( 0, 50, 0, 50 ) )

My heart jumped when you pointed out applying the position to my internal variable after the collision. This really makes sense – that’s what it feels like it’s doing. But, applying this change doesn’t seem to have had any effect.

self.keyboard.update()
self.setVelocityBySpeed( self.keyboard.getSpeed() )

self.mouse.update()
self.rotateBy( self.mouse.getRotation() )

self.position += self.velocity

base.camera.setHpr( self.rotation )
print self.position
base.camera.setFluidPos( self.position )
self.position = base.camera.getPos()
print self.position
print "---"

When I print out my target position, and the position of the node after setFluidPos, they’re identical.

I can tell that the node is reacting to the collision because my speed of movement decreases dramatically when I start bumping up against the plane. But, it just keeps pushing at a very slow rate until it eventually pops through.

Maybe I’m using the wrong method for moving my character?

Well, this sequence:

base.camera.setFluidPos( self.position )
self.position = base.camera.getPos() 

doesn’t actually help anything, because the collision traversal hasn’t run between the two commands. So the camera’s getPos() value is still exactly the same value you just set it to, which is self.position! You need to do it something like this instead:

self.position = base.camera.getPos() 
self.position += self.velocity

base.camera.setHpr( self.rotation )
print self.position
base.camera.setFluidPos( self.position )

With the above sequence, presumably the collision traversal has run since the last time the task has executed, so it gets the latest position, after being updated by collisions.

Now, that still leaves the mystery of your object “popping through” a CollisionPlane. I assure you that’s not possible. It’s not possible because a CollisionPlane is defined to be a solid object that fills the space of half the universe. The CollisionHandlerPusher will never tolerate leaving an object on the back side of a CollisionPlane, no matter how far back it is.

So, if you are observing your object on the back side of the CollisionPlane, it means that you must have moved it there after the collision traversal has run (but before the frame has rendered). Check your task priorities, by printing taskMgr. It is important that the task that runs your collision traversal (by default, the task named “collisionLoop”) be given a priority greater than the task that moves your object around, so that the collision fixup will occur after you have moved the object. (It is also important that collisionLoop has a priority less than igloop, which renders the frame. The order should be your task, collisionLoop, igloop.)

David

Whoops! My apologies. I was thinking that setFluidPos was sweeping the node through the collision tree at the moment it was called.

Resetting the position before applying the velocity fixed it completely.

Thanks for the help.