-----===== POLYGON CLIPPING ====----
by: Adrian Brown
version: 1.0
date: 17th September 1996
******************************************************************************
This paper is designed to take you through the step of 2 polygon clipping
techniques. The first is the frequently used scanline by scanline technique
while the second is arithmetic clipping. This involves clipping the polygon
before you actuall go to draw it, Adding new vertices where required to
produce a new polygon which has coordinates that are all on the screen.
******************************************************************************
** DISCLAIMER
I assume no responsibility whatsoever for any effect that this file, the
information contained therein or the use thereof has. No warranty is
provided nor implied with this information.
******************************************************************************
** Contents
1) What is clipping?
a) 2D Sprite based clipping.
b) Edge scanning a polygon.
2) Scanline by scanline clipping.
a) Clipping to the Top and Bottom.
b) Clipping to the Left and Right.
3) Arithmetic clipping.
******************************************************************************
** 2) What is clipping?
a) 2D Sprite based clipping.
----------------------------
Clipping is a way of making sure that anything you draw to a fixed size
screen stays within the boundaries of that screen. In a simple 2d sprite
based system a clipping routine would have looked something like this.
/* SAMPLE CODE FOR BASIC 2D SPRITE CLIP
this is only example code. I do not promise that it will compile or work.*/
if (Sprite.X > SCREEN_WIDTH ÝÝ (Sprite.X + Sprite.W) < 0 ÝÝ
Sprite.Y > SCREEN_HEIGHT ÝÝ (Sprite.Y + Sprite.H) < 0)
{
// Sprite is fully off screen. No need to draw.
return;
}
if (Sprite.X < 0)
{
// Sprite needs Clipping on left of screen
Sprite.GfxX += -Sprite.X;
Sprite.W += Sprite.X;
Sprite.X = 0;
}
if ((Sprite.X + Sprite.W) > SCREEN_WIDTH)
{
// Sprite need Clipping on right of screen
Sprite.W -= (Sprite.X + Sprite.W) - SCREEN_WIDTH;
}
if (Sprite.Y < 0)
{
// Sprite needs Clipping on top of screen
Sprite.GfxY += -Sprite.Y;
Sprite.H += Sprite.Y;
Sprite.Y = 0;
}
if ((Sprite.Y + Sprite.H) > SCREEN_HEIGHT)
{
// Sprite need Clipping on bottom of screen
Sprite.H -= (Sprite.Y + Sprite.H) - SCREEN_HEIGHT;
}
* END OF EXAMPLE CODE *
This first of all checks to see if the sprite is even on screen. It then
proceeds to check each side of the sprite with the sides of the screen. If
any edges need clipping in moves the appropriate X/W or W/H values. It also
moves the start graphic locations to match.
The principles behind this simple 2d sprite based clipping are the same when
it comes to clipping polygons. You are still trying to fit an object into a
screen size. I am going to cover 2 methods I have used to clip polygons,
both of them clip the 2d polygon. This means if you are using it in a 3d
based environment you must convert the polygon x,y,z coordinates into screen
x,y coordinates before you can use these methods. I also assume that you
use an edge scanning polygon technique to draw your polygons.
b) Edge scanning a polygon.
---------------------------
Edge scanning polygon draw routines use a method of tracing down each edge
of a polygon. The X coordinate of the line is stored in a table at the
corresponding Y coordinate. e.g. if a point on the edge of a polygon was at
X = 10, Y = 101 then at entry 101 in the edge table you would store the value
10.
For more information about Edge scanning polygon draw routines please
refer to the works of Chris Egerter in his tutorials 1,2 and 3. These can
be found at many ftp sites including x2ftp.oulu.fi/pub/msdos/programming/wgt.
******************************************************************************
** 2) Scanline by Scanline clipping.
a) Clipping the top and bottom.
-------------------------------
Clipping the top and bottom of a polygon is done in the line draw routine.
Before you start to draw your line you check to see if the Y start coordinate
of the line is less than 0. If it is then you must move the starting X
coordinate to the point where Y = 0. This is generally done using the
gradient of the line.
X1, Y1
/Ý
/ Ý
/ Ý
---------/------Ý------------- line Y = 0
/ Ý
/ Ý gradient of line X1,Y1 - X2,Y2 =
/ Ý (Y2 - Y1) / (X2 - X1)
/______________Ý
X2, Y2
Using the gradient of the line we can say where any particular coordinate
is based upon the other. In the case of clipping we want to know what the X
will be when Y = 0. Lets run this through an example:-
100, -50
/Ý
/ Ý d
/ Ý
---------/------Ý------------- line Y = 0
/ c Ý b
/ Ý
/ Ý
/______________Ý
0, 50 a
where:-
a = X2 - X1 = -100
b = Y2 - Y1 = 100
c = Wanted value.
d = portion of line above Y = 0 (-Y1) = 50
The gradient for this line would be b / a
= 100 / -100
= -1
Math's states that since the gradient of a triangle is the same no matter
where you take the values from b/a will equal d/c. We can use this
information by rearranging it to give us the unknown value.
b d b d x a
- = - -> - x c = d -> b x c = d x a -> c = -----
a c a b
Plug in the values we know to the formula at the end and you get:-
50 x -100
--------- = -50
100
You simply add the value you get from this formula to X1 and you get the
value for X1 where Y1 = 0.
The same principles can be used to clip any lines which go off the bottom
of the screen.
b) Clipping the left and right.
-------------------------------
Clipping to the left and right edges of the screen is very easy in scanline
by scanline clipping. When you read the values from your edge table you
check to see if the starting value is off the left hand edge. If it is you
set the value to be the left hand edge. If the finishing edge is off the
right hand side of screen you can set the finishing edge to be the right hand
side of screen.
The inner loop for a draw routine using this technique would look something
like this:-
/* SAMPLE CODE FOR AN INNER LOOP
this is only example code. I do not promise that it will compile or work.*/
// Get the edges to draw between.
X1 = EdgeTable[Y][0];
X2 = EdgeTable[Y][1];
// Check for clipping.
if (X1 < 0)
{
X1 = 0;
}
if (X2 > SCREEN_WIDTH)
{
X2 = SCREEN_WIDTH
}
for(;X1 < X2; X1++)
{
*(Dest + X1) = PixelValue;
}
* END OF EXAMPLE CODE *
The next style of clipping is much harder to implement but I found that it
is much faster, especially on larger polygons.
******************************************************************************
** 3) Arithmetic Clipping
Arithmetic clipping involves removing the parts of the polygon which are off
the screen and adding vertices to create a new polygon. This new polygon is
the same shape as the old apart from there are no edges off the edges of the
screen.
The principles are very simple, but I have found that the clipping must be
done in a certain order. This is the Top then Bottom then Left and final
Right hand edges. If you do not follow this order some very strange shapes
will appear in place of your polygon.
Lets take a normal polygon:-
X1,Y1
/\
/ \
________________/________\____________________
Ý X4,Y4 / \ X2,Y2 Ý
Ý \ / Ý
Ý \ / Ý
Ý \ / Ý
Ý \/ Ý
Ý X3,Y3 Ý
Now to clip this arithmetically we would first clip the lines that are off
the top of screen. There are two which meet this description. X1,Y1 - X4,Y4
and X1,Y1 - X2,Y2. When we clip these lines we will produce an extra vertex
and an extra line. This is because at the moment the two lines both share the
vertex X1,Y1, but when they are clipped we will need vertices where the two
lines cross the top of screen. These two points will not be the same and so
we have to insert a new vertex.
_______________a__________b___________________
Ý X4,Y4 / \ X2,Y2 Ý
Ý \ / Ý
Ý \ / Ý
Ý \ / Ý
Ý \/ Ý
Ý X3,Y3 Ý
The new polygon has 5 lines, not 4.
line 1 = a - b
line 2 = b - X2,Y2
line 3 = X2,Y2 - X3,Y3
line 4 = X3,Y3 - X4,Y4
line 5 = X4,Y4 - a
The coordinates of the new points can be calculated in the same way as we
done for the top/bottom clipping above. We go through all the lines checking
and clipping to the top and bottom of screen and then we use exactly the same
principles for clipping to the left and right edges of screen. When you clip
to L/R edges you must use the new points gained in the T/B clipping.
******************************************************************************
** 4) Closing words
These methods can be used when drawing texture mapped polygons with very
little alteration. The only thing that needs to be added to the clipping
routines are a few lines to move the texture coordinates by the same amount
as the screen coordinates. Likewise with Gouraud shaded polygons.
If you are feeling brave you can even use the same techniques to clip
polygons to other planes an hence have one object be cut by another. This
does require clipping in 3d space but this is all very similar to the 2d
clipping mentioned above.
******************************************************************************
If you want to drop me a line an ask anything about the clipping routines
above, or anything else for that matter, send an email to the above address.
******************************************************************************