Aligning actor to surfaces

Hi, I’m making a racing game in Panda3d, and I’m using the CollisionHandlerGravity() to keep my actor on the ground in a bumpy terrain. The car is a rigid-body, and it seems unnatural that it would always keep its horizontal orientation, even when driving up and down hills. Is there some easy way of setting the car’s Hpr-values according to the terrain it is on?

I tried using the getContactNormal()-function from the CollisionHandlerGravity class, but I can’t grasp how the vector it returns relates to the car’s Hpr-values that are represented in degrees. I spent a lot of time trying to do the math required, and just wanted to ask if I’m trying the right thing, or if there’s some other easy way of doing this?

Thanks in advance,

Try using nodePath.headsUp(Point3(0, 1, 0), normal) to rotate your car so that it is facing forward–Point3(0, 1, 0)–with its “up” vector aligned with your normal.


Hi David,

thank you for your reply.

I am a relative beginner at Panda3D and have a hard time implementing your reply. I wonder how you get the Normal value from your terrain.

I use the PhysicsCollisionHandler.


Didn’t you just say that you tried using the getContactNormal() from CollisionHandlerGravity? Or was that a different person?

In any case, in order to get the normal from just the floor (and not from any walls that you happen to bump into), you will need a special collider that only detects collisions with the ground. The best way to do this is to assign a special bit in the CollideMask for the floor polygons, then create a CollisionRay that is parented to your vehicle, pointing straight down, and give it only that special floor bit. Then you can attach an appropriate handler to it, say the CollisionHandlerGravity, which handles falling nicely and also incidentally stores the normal of the floor polygons for you.

Another way to get the normal is to listen for the collision event that is generated from the above ray. The first parameter of the collision event will be a CollisionEntry, which describes the details of the detected intersection; you call call getSurfaceNormal() on this object to get the normal.

Or, you can be clever in other ways; you can build up a grid in memory of the normals at each (x, y) position of your terrain, and then just look it up as you are driving around. Of course, you have to decide how coarse your grid should be, and you have to write the code to generate this table (presumably you’d do this offline and store it in a file).


Oops, I didn’t realize I wasn’t logged in. The above post was from me.