Line Collision (Ray testing)

What is ray testing and why should I use it?

Raytesting is a type of collision test to see what objects get hit by a ray(or, line). Raytesting can be used for bullets or for detecting the angle of the ground a player is walking on.

Functions

In JigLibX, we use the SegmentIntersect function to test if a ray hits a physics object. The function looks like this:

public abstract bool SegmentIntersect(    out float fracOut,
                                        out CollisionSkin skinOut,
                                        out Vector3 posOut,
                                        out Vector3 normalOut,
                                        Segment seg,
                                        CollisionSkinPredicate1 collisionPredicate);

As you can see it needs a few reference variables and a Segment. A Segment is a struct located in Line.cs. The constructor is as follows:

new Segment(Vector3 origin, Vector3 delta)

It takes a origin and a delta vector. A Segment is basically a line that starts at the origin and goes as far as origin + delta.

The other out variables pretty much speak for themselves, the fracOut is the exact distance to the collision, the skinOut is the physics skin that has been hit, posOut is the world position of the collision and last but not least is the normal of the polygon it hit.

collisionPredicate

But what about collisionPredicate? Well, the title says it pretty much. If your native language is not English, the word could not mean much to you, but it actually means this: (computer programming), a choice to execute or not to execute a given instruction based on the content of a machine register.

So in a way, you could see the collisionPredicate as a filter to see what collisions are valid and not. A very simple predicate is to check if the skin actually exists or if a skin is active/immovable.

A simple custom implentation is found in the jiggle game class;

    class ImmovableSkinPredicate : CollisionSkinPredicate1
    {
        public override bool ConsiderSkin(CollisionSkin skin0)
 
        {
            if (skin0.Owner != null && !skin0.Owner.Immovable)
                return true;
 
            else
                return false;
        }
    }

The function returns true when the skin has a owner (Body) and is not immovable so it is counted as a valid collision.

Doing a test

Now that's out of the way, we can do a ray test using the functions described above. I'll show you the code first, then dive in and explain it line by line.

Vector3 ray = new Vector3(0f, 0f, 0f);
float dist;
CollisionSkin skin;
Vector3 pos, normal;
 
ImmovableSkinPredicate pred = new ImmovableSkinPredicate();
Segment seg = new Segment(ray, Vector3.Down * 1000000000.0f)
 
world.CollisionSystem.SegmentIntersect(out dist, out skin, out pos, out normal, seg, pred);
 
if(skin != null)
{
    //Collision
}

The first line defines the start position of the ray, which is in the middle of the world.

The next three lines are the variables that get populated by the SegmentIntersect function.

The ImmovableSkinPredicate line initializes our predicate "filter" to be used with the SegmentIntersect function.

The segment is the actual line that gets tested, wich goes from the middle of the world 1000000000 units down.

After that the magic starts, we call the SegmentIntersect function to test the line and get the results. All the out variables that we defined now contain values about the collision. The SegmentIntersect function can be used on the world or any other physics skin. In this example I use this from my world collision system.
A collision has happened when the skin is not null, when it is null, there was no collision.

What to do with the results

Well, there are a lot of things you can do with the results. For example, you can use the Normal to calculate the angle of a players foot-bone and the frac (Distance) to place the foot exactly on the ground.
In an other example, you can use the ray like a bullet. Do a check so you can find the player class associated with the skin and do some damage.

I created this tutorial with great care, but if you find something that is updated in a later version of JigLibX or simply incorrect, send me a mail at wesleyelfring [!at!] gmail com.
Also, if you have some questions remaining, please feel free to make a post on the forums.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License