How can I fix this wall jittering in capsule to octree collision?

Started by
3 comments, last by Gnollrunner 1 year, 10 months ago

BH

In the three.js example for a first person game https://threejs.org/examples/?q=game#games_fps you should notice that at the corners it gets stuck, seemingly because it collides with one side, then pushes it into the other side (when there's less than a 90 degree angle) then that side pushes it back into the first side, and if one keeps trying to move this process keeps getting repeated.

The relevant part of the collision is https://github.com/mrdoob/three.js/blob/dev/examples/games_fps.html​ (can't figure out how to add text after code here, but basically First just checks if it's on the ground (and if not then makes it fall down along the wall it's colliding it, or at least that's what I think it does) then slides it the opposite direction of whatever it collides with, which seemingly is what's causing the jitter since it's just pushing it into the other wall when it's at an acute angle.

I tried tweaking with it but have no idea what to do or how to start, any ideas?)

function playerCollisions() {

				const result = worldOctree.capsuleIntersect( playerCollider );

				playerOnFloor = false;

				if ( result ) {

					playerOnFloor = result.normal.y > 0;

					if ( ! playerOnFloor ) {

						playerVelocity.addScaledVector( result.normal, - result.normal.dot( playerVelocity ) );

					}

					playerCollider.translate( result.normal.multiplyScalar( result.depth ) );

				}

			}

Blessings and Success

Advertisement

The way I handle this is to check for double plane collisions in addition to the normal single collisions. I do general mesh collision and I keep a list of all faces that the capsule is "touching". That list is generally very small but it could conceivably be larger with some sort of cone like structure the capsule is resting in, but in practice it's like 2 or 3 faces.

In any case I do a check for all possible single and double plane collision responses that are not blocked by a touching plane. For double plane responses I take the cross product of both plane normals to get a new response vector. If there is more than one possible way to go I take the one that is closest the direction the capsule is being pushed. This is a bit more complex but I believe it covers all possible cases. Also there is no bouncing since you can not move into a touching plane.

BH

@gnollrunner hi thanks for the reply. That's a good idea to keep a list of current plane collisions,I tried doing a similar thing in 2d a while ago but even then I couldn't figure out the collision resolution, when I tried to take the average of the two points it would be a point that's even further in then it would keep going until eventually getting stuck, then jittering more.

What exactly is the cross product in 3d in this case and how do I find out?

Blessings and Success

First here's the paper I started out with :

https://www.peroxide.dk/papers/collision/collision.pdf

This is pretty good but after implementing it I quickly found the double collision problem and things would get stuck. The first thing I did was define 2 spheres. The inside sphere is the one I calculate collision from. The outside sphere, which is a tad larger defines when I'm touching part of the mesh. That means anything between the two spheres you are touching. As noted in the paper that could be a vertex and edge or a plane.

Now when I move and collide with something, I calculate the new response. So let's say that takes me into another plane, which which will push me back to the first plane. After a couple of iterations I would basically be bouncing back and forth between the two, however since I have the touching list which now contains more than one item. I can do a cross-product on vectors from the contact points of the sphere to it's center. this gives me a new vector perpendicular to both. Depending on the order I did the cross product, I might have to invert it to get the right direction. You can always check by doing a dot product of the vector and one that represents the original direction you are being pushed. I refer to it as the force vector. If the angle is greater than 90 degrees, just flip it to the other direction.

Now you have a new response that works for both contact points. Keep in mind there could be more planes of contact and more combinations you might want to check if you want to be 100% thorough. You can do dot products for all pairs of collisions. However as I said, typically there are going to be only 2 anyway and maybe 3 or 4 max.

So as an example if you are in some sort of corner or are pushing up a mini valley, you will have 3 ways to go, the two single plane collision responses and the cross product response. You pick the one that best matches the force vector. In the case of the mini valley, the single plane responses will be blocked by the other touching plane, which leaves only the two plane response as an option. If all response are blocked that means you simply can't move and you exit your response loop.

I should note this was my solution so I'm not sure if it is at all standard or if there is a better solution out there, however I can say it worked very well for me.

This topic is closed to new replies.

Advertisement