Hello. I’ve been exploring Panda3D collision system lately and noticed that running a collision handler against a Polyset from an egg file (as an “into” object, of course) tests only one polygon at a time. This yields incorrect results, especially with the CollisionHandlerPusher, such as jittering around corners, sticking to a nearest corner instead of sliding, pushing the “from” object up/down on the z axis by the value of the collider height, etc. These are all known bugs.
I understand that it happens because in the single iteration the collision traverser doesn’t know anything about other polygons. It doesn’t happen with other collision solids as “from” objects, only with collision polygons. Even if it’s the same shape, a box, for an instance.
I am looking for advice to solve this problem. My current options are:
Code a new CollisionPolyMesh solid and write collision tests against it. Run some checks to ensure that the mesh is convex and disallow concave meshes. (I guess this kind of collision solid wasn’t introduced in the original Panda3D code because the collision code was written in 2000, and back then it could be too heavy on the CPU).
Run several iterations inside my custom CollisionHandlerPusher. Store object position, compute net shove (the “pushing” vector), move object, run collision traversal, repeat for the next N number of frames, move object to the original position, add the net shoves, move the object.
Solution 2 seems easier to code but I am not sure it will give excpected results. Also, if I unerstans correctly, the CollisionHandler class shouldn’t know about the ColllisionTraverser object and shouldn’t call traverse by design.
Solution 1 looks like the right thing to do, but I currently have no idea where to start. Any advice is appreciated. Thanks in advance.
After spending some time studying Internet sources on collision, and debugging CollisionPolygon solid, I think I was wrong in my initial assumption. All of the intersected polygons are passed to the CollisionHandlers, not one. So there’s no need to code PolygonMesh solid, this is already handled by Panda3D.
I think the main solution for implementing correct kinematic collision is to handle multiple collision points the right way (summing the shoves like CollisionHandlerPusher does seems to be not always correct).
Studying Quake 3 source code I’ve noticed it takes into account collision time.
Collision time is available in the collision entry, I’ll see if I can make use of that.
EDIT: no, it has no use in the current situation, since the collision time is always the same.
Also, Q3 uses “swept collision” tests, instead of resoluting collisions after they have actually happened.
One possibility might be to simply switch to using Bullet for collision-handling. It does have its own down-sides, but at the least I suspect that it’ll handle cases like this more accurately than does Panda’s collision system. In particular, I seem to recall that it can produce multiple contact-points when a collision occurs.
That’s fair; well, good luck with it, then! I hope that you succeed.
Hmm… I once put together a 2D collision system. If I recall correctly, it worked by “rewinding time” until the object in question was in a “valid” spot, updating its velocity, and moving forward again, iterating this cycle until either there were no more collisions or it ran out of “time”. (I’m not sure of what I did in the latter case; perhaps I left it at its last “valid” position.)
In 2D this is more simple, you can let the collision happen, and then bruteforce it and move the collided object pixel by pixel in the opposite direction of movement vector. In 3D there’s no pixel units.
But I didn’t use such a brute-force method. Now, I did have a simplification: I essentially made it a matter of line-line intersections, allowing me to calculate the point of impact, and thus allowing me to calculate how far back the system had to “rewind”.
That said… You could do the “brute-force” method in 3D, if you wanted to, I daresay: just specify some small “step distance”. It doesn’t have to match any specific feature of the setup, like pixels; it just has to be small enough to serve the purpose.
Oh, I wasn’t suggesting that you take the brute-force approach (if that’s what you mean by (implied) “less intelligent methods”); just pointing out that it can be done in 3D just as in 2D.
I do imagine that the “rewind” method–specifically, the non-brute-force approach, as described above–is more complicated when dealing with full polygons, rather than line-segments. Still, perhaps it might work.
Well, I practiced some more time and don’t see how I can fit this (your algorithm, or any other) in the design of Panda3D collision system. It already has separation of concerns coded in separate objects, such as CollisionTraverser and CollisionHandler. CollisionTraverser traverses the graph, CollisionHandler reacts to collision entries.
To follow this pattern in order to implement recursive collision resolution of multiple points, I need to design something like RecursiveCollisionTraverserThatIsAlsoAHandlerWithVelocities class. If I spend time reinventing the wheel, I want at least it to be usable by others and something that I can contribute (for myself I indeed can use Bullet).
If somebody interested, I wanted to implement a more universal simple collision handler, something like a CharacterController component in Unity. The requirements were:
Stay on the floor and slide along walls
Apply pseudo gravity
Walk on slopes (don’t slide down slopes)
Smoothly slide up stairs
Collidable with level geometry from the .egg file
I managed to put up something that works, but only for a limited case: a sphere collider not larger than a size of a wall on z axis. E.g. with a capsule collider that has considerable height it will fail.