by
Jeff Lander
Gamasutra
February 10, 2000
This
article originally appeared in the
January 1999 issue of:

|
|
Features

Don’t
Cross that Line
The quadrant
method is pretty efficient. However, there’s a completely different approach.
An interesting feature of this problem can be found if you draw a line
from the test point to a point definitely outside the polygon. Now count
how many polygon edges crossed that line. If that number is odd, the point
is inside the polygon. If the number of edge crossings is even, the point
is on the outside. Try it out.
I saw a
pretty fast way to implement this in Graphic Gems IV. This method
projects a line from the hit position along the x axis. Only testing line
segments that are on either side of this position lets you avoid some
calculations. Segments that could cross this line require an x intercept
calculation to be sure. However, this can be simplified to eliminate a
divide because of the unique needs of the test. The code for this routine
is in Listing 2. Whether or not this method
is faster than the quadrant method depends greatly on the polygon being
testing. The routines are so easy to implement that you should try both
in your application if speed is a real issue.
Standing
at Arm’s Length
The above
routines are enough to let your player navigate around in a Doom-style
level. You would just need to make sure that the player is always inside
a sector. If the player leaves one sector and does not enter any other,
a "collision" has happened. This works very well. However, using
the inside polygon test for collision by itself has a drawback. The player
can get very close to the wall of a sector and still be considered "inside."
Logically, this works fine. However, in a 3D rendered game engine, being
too close to a wall is a bad thing. Textures will look blocky, they can
distort badly, and walls may clip out.
What you
really want to do is keep the walls at "arm’s length" from the
player. You can simply make the logical collision walls closer in than
the visual walls; however, this can lead to other problems. So how do
I keep the character away from the wall? Turn once again to our dear old
friend, the dot product. Take a look at Figure 5.
 |
|
Figure
5. Checking the distance.
|
What I want
to know is, how far away is the test point, t, from line segment A. An
easy solution would be to find the nearest point, n, to the test point
on the line segment and measure the distance to it. First, I create a
vector, B, from the test point, t, to vertex p1. I can dot this vector
with the line segment A. This will give me the cosine of the interior
angle. If this angle is 90 degrees or greater, the nearest point is the
vertex itself and I’m done. But let’s say that the dot product gives me
0.7, or the cosine of about 45 degrees. I will then do the same thing
on the other side. I create a vector C and dot it with the segment A.
If it had returned an angle greater than or equal to 90 degrees, point
p2 would be the closest and I would be done again. In this case, the dot
product returns 0.75, or the cosine of about 40 degrees. Now that I have
the two dot products, a linear ratio will solve the problem.

You can
see the code that determines the nearest point on a line segment to an
input point in Listing 3. The squared distance
from t to n can be used to make sure the player cannot get too close to
the wall. When I combine this with the inside-polygon tests, I have the
pieces I need to create a Doom-style collision model. In these days of
Quake III and Unreal, it may seem a bit retro to talk about
Doom-style collision detection. However, the ability to build simple collision
boundaries that you can use and modify in real-time is a very attractive
feature. Rules in game development are meant to be broken. Just because
these days you are displaying a world made of 3D polygons, your collision
boundaries don’t have to be 3D polygons. Many of the environments we wish
to interact with have boundaries that can easily be defined as 2D concave-polygonal-line-segments.
Sometimes the best results can be achieved with simple solutions. If you
didn’t have these routines already in your math library, add them and
you will be surprised by how often you use them.
________________________________________________________
Colliding
in the Third Dimension
|