Help with static groups and collitions

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
dynamoman
Posts: 12
Joined: Mon Sep 27, 2010 12:35 am

Help with static groups and collitions

Post by dynamoman »

Hey Norbo, I'm working on a 2.5D platformer, and we want a weapon to shoot a projectile that "attaches" to the ground and then it will move following the stage, (if there is a wall it will go up, at the end of the wall it will turn right, at a pit it would go down and so on). Right now we have boxes for the geometry of the stage, but we put them in a static group, so when I check the list of current collitions it gives me a static group, what would be the best way to implement such behavior(it has to follow the stage geometry).

My first idea was to use a couple of rays(down and forward) to detect if it was colliding with the ground(and save that mesh) or if there was a wall in front of it, if at some point there is no ground, then I would teleport the object to the edge of the latest saved mesh, and then change direction, but with the static group, I think is not possible to find the size of the boxes since is now a big group of meshes.
My other idea was to use forces, but if it goes too fast you can see how it "detaches" from the surface.

Any ideas?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Help with static groups and collitions

Post by Norbo »

Assuming this kind of behavior is what you're looking for:
surfacefollowing.jpg
surfacefollowing.jpg (12.57 KiB) Viewed 2985 times
then this is quite similar to a 6DOF-walk-on-walls SphereCharacterController variant I built a while ago (which unfortunately isn't public). In that project, I found that using an enlarged spherical collision query to find potential supports and former supports worked the best.

The process looks like this:
1) Collect any nearby contacts. You can do this using a one-shot query like the SphereCharacterController.QueryManager.QueryContacts function, or you can just keep a sphere in the space to collect pairs over time. If the sphere actually belongs to the space, you'll probably want to set the collision rules to disable collision response.
2) Calibrate the normals to point at the center of the sphere. Collision detection will produce contacts which can face either towards or away, since neither object is 'preferred'. Do this by negating normals which point 'away' from the center (or vice versa). You can measure which way they face by comparing the offset from the center to the contact position to the contact normal. To avoid corrupting any internal state, I would recommend doing the contact modifications on your own game logic copies of the contact data.
3) Update the 'support'.
-If the object does not yet have a support, check the list of queried contacts. If one exists, consider it the support. If multiple exist, use a heuristic to choose which one will be the support.
-If the object already has a support and there other options available, use a heuristic to determine if it should switch to a different support.
-Generally, if there exists a contact which has a similar normal to the previous support, it's a good idea to use it as the new support. This makes it easy to smoothly traverse curved surfaces or go over convex edges.
-Examples of other heuristics: is the object moving toward or away from this contact? Can use either velocity or the desired goal velocity for this purpose. If the object's running into a wall, the support probably needs to swap to the wall contact.
-When the support is updated, use the shortest rotation between the former support normal and the new support normal to update any orientation stuff (goal movement direction, object orientation, or whatever else).
4) While the object has a support, remove velocity along the support normal. Include an extra term to keep the object at a certain distance within the sphere's radius to avoid drifting off. In pseudocode:

Code: Select all

object.Velocity += supportNormal * (-relativeVelocityAlongNormal + distanceCorrectionTerm)
Which expands to:

Code: Select all

object.Velocity += supportNormal * (-Vector3.Dot(object.Velocity - supportVelocity), supportNormal) + (goalDistanceFromCenterToSupport - currentDistanceFromCenterToSupport) * 0.2 / dt)
The distance correction term's multiplier of 0.2 / dt tries to remove 20% of the error per frame.
(Small sidenote: the distance as measured from the sphere center to the contact position isn't exactly the distance from the center of the sphere to the nearest surface. The contact tends to be somewhere in the middle of the intersection volume. If you wanted to, you could find an approximation of the surface by taking into account the contact penetration depth or casting a ray from the center of the sphere to the contact position.)

Here's how the query sphere would look as it went around a convex edge, along with an approximate visualization of the support:
surfacefollowingqueries.jpg
surfacefollowingqueries.jpg (27.88 KiB) Viewed 2985 times
Collision queries have the advantage of not caring where the contacts came from. Whether it's moving on meshes, boxes in a static group, or just entities directly, it just works.
dynamoman
Posts: 12
Joined: Mon Sep 27, 2010 12:35 am

Re: Help with static groups and collitions

Post by dynamoman »

Thanks Norbo, I'll try to implement the solution, and that's exactly the kind of movement I'm trying to have, I'll probably ask more things when I'm implementing it (tonight or tomorrow):P.
Post Reply