want to avoid drawing pixels twice (not a problem with frame buffers but can be with other display technologies.)
pixels within the boundary of a polygon belong to the polygon
pixels on the left and bottom edges belong to a polygon, but not the pixels on the top and right edges
Want a polygon filling routine that handles convex, concave, intersecting polygons and polygons with interior holes.
overall algorithm:
moving from bottom to top up the polygon
starting at a left edge, fill pixels in spans until you come
to a right edge
specific algorithm:
moving from bottom to top up the polygon
parity bit = even (0)
each intersection inverts the parity bit
draw pixels when parity is odd (1)
Why do it horizontally, why not vertically?
Algorithm for step 1: scan-line algorithm
as usual there is the straightforward easy way and the convoluted efficient way.
an easy way:
From above, the specific polygon filling algorithm:
moving from bottom to top up the polygon
parity bit = even (0)
each intersection inverts the parity bit
draw pixels when parity is odd (1)
makes use of the fact that, similar to the midpoint algorithm, once we have an intersection we incrementally compute the next intersection from the current one. Xi+1 = Xi + 1/m
Create a global Edge Table (ET)
Lots of nagging little details for step 3:
- if intersection is at an integer value (say 4.0)
if we are at a left edge then that pixel is interior
if we are at a right edge then that pixel is not interior
- if intersection is at a non integer value (say 4.6) is pixel 4 interior? is pixel 5 interior?
if we are outside the polygon (parity is even) then we round
up (pixel 5 is interior)
if we are inside the polygon (parity is odd) then we round down
(pixel 4 is interior)
- what if more than one vertex shares the same location? (this also handles the situation where you may end up with an odd number of edges in the AET)
bottom vertex of a line segment counts in parity calculation
top vertex of a line segment does not count in parity calculation
- what if 2 vertices define a horizontal edge?
imperfect, but easy, solution is to ignore this edge.
Example:
So the global ET starts out being ...
------ ---------------- --------------- | 20 | --> | 50 | 40 | -1 | --> | 40 | 40 | 0 | ------ ---------------- ---------------- ------ ---------------- ---------------- | 10 | --> | 50 | 10 | 0 | --> | 40 | 70 | -1 | ------ ---------------- ----------------
and the horizontal line from (10,10) to (70,10) is ignored.
Now the active edge table starts out with the minimum Y in the global edge table, i.e.:
---------------- ---------------- Head --> | 50 | 10 | 0 | --> | 40 | 70 | -1 | ---------------- ----------------
Using this edge table for Y=10, parity turns on at X=10 and turns off at X=70, so the pixels from 10 to 69 inclusive would be drawn. Then as Y is increased to 11 for the next line, the active edge table would adjust the X values using the 1/m values, to yield:
---------------- ---------------- Head --> | 50 | 10 | 0 | --> | 40 | 69 | -1 | ---------------- ----------------
Note that the X in the first entry did not change, because that edge is vertical, but the X in the second entry was changed by 1/m, i.e. it changed from 70 to 69. There are no edges to be added or removed, so the pixels from 10 to 68 inclusive would be drawn for Y=11.
The algorithm will continue this way until Y=20, at which point two new edges get added, and so the active edge table becomes:
---------------- ---------------- --------------- ---------------- Head --> | 50 | 10 | 0 | --> | 50 | 40 | -1 | --> | 40 | 40 | 0 |--> | 40 | 60 | -1 | ---------------- ---------------- --------------- ----------------
Traversing this line there are two parity changes at X=40, so all pixels are drawn from X=10 to 59. Then when Y is incremented to 21, the active edge table becomes:
---------------- ---------------- --------------- ---------------- Head --> | 50 | 10 | 0 | --> | 50 | 39 | -1 | --> | 40 | 40 | 0 |--> | 40 | 59 | -1 | ---------------- ---------------- --------------- ----------------
Now pixels are drawn from 10 to 38 and from 40 to 58. This continues until Y reaches 40, at which point the rightmost two edges drop out and the active edge table becomes:
---------------- ---------------- Head --> | 50 | 10 | 0 | --> | 50 | 20 | -1 | ---------------- ----------------
and so on, until Y reaches 50 and the remaining two edges are removed from the active edge table.
Why would this algorithm be much simpler if the polygon were guaranteed to be convex with no intersecting edges?
The above discussion only covers the means of determining the inside versus outside pixels of a polygon defined by straight line segments.
It does not cover polygons whose borders are defined by curves such as circles, ellipses, parabolic functions, or splines. ( Of course these can all be approximated by a series of small straight lines, and given enough, the approximations can be quite good. )
We also haven't addressed what to fill the polygon with. The presence of different lighting models, textures, or bump maps may cause each pixel within the polygons to be colored differently from any of its neighbors. Those issues will come up in later lectures.