229 lines
8.7 KiB
HTML
229 lines
8.7 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META name=vsisbn content="1576101746">
|
|
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
|
<META name=vsauthor content="Michael Abrash">
|
|
<META name=vspublisher content="The Coriolis Group">
|
|
<META name=vspubdate content="07/01/97">
|
|
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Of Songs, Taxes, and the Simplicity of Complex Polygons</TITLE>
|
|
|
|
<!-- HEADER -->
|
|
<!-- Empty Reference Subhead -->
|
|
|
|
<!--ISBN=1576101746//-->
|
|
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
|
<!--AUTHOR=Michael Abrash//-->
|
|
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
|
<!--CHAPTER=40//-->
|
|
<!--PAGES=750-753//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="40-02.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="40-04.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<H3><A NAME="Heading5"></A><FONT COLOR="#000077">Complex Polygon Filling: An Implementation</FONT></H3>
|
|
<P>Listing 40.1 just shown presents a function, <B>FillPolygon()</B>, that fills polygons of all shapes. If <B>CONVEX_FILL_LINKED</B> is defined, the fast convex fill code from Chapter 39 is linked in and used to draw convex polygons. Otherwise, convex polygons are handled as if they were complex. Nonconvex polygons are also handled as complex, although this is not necessary, as discussed shortly.</P>
|
|
<P>Listing 40.1 is a faithful implementation of the complex polygon filling approach just described, with separate functions corresponding to each of the tasks, such as building the GET and X-sorting the AET. Listing 40.2 provides the actual drawing code used to fill spans, built on a draw pixel routine that is the only hardware dependency anywhere in the C code. Listing 40.3 is the header file for the polygon filling code; note that it is an expanded version of the header file used by the fast convex polygon fill code from Chapter 39. (They may have the same name but are <I>not</I> the same file!) Listing 40.4 is a sample program that, when linked to Listings 40.1 and 40.2, demonstrates drawing polygons of various sorts.</P>
|
|
<P><B>LISTING 40.2 L40-2.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* Draws all pixels in the horizontal line segment passed in, from
|
|
(LeftX,Y) to (RightX,Y), in the specified color in mode 13h, the
|
|
VGA’s 320x200 256-color mode. Both LeftX and RightX are drawn. No
|
|
drawing will take place if LeftX > RightX. */
|
|
|
|
#include <dos.h>
|
|
#include “polygon.h”
|
|
|
|
#define SCREEN_WIDTH 320
|
|
#define SCREEN_SEGMENT 0xA000
|
|
|
|
static void DrawPixel(int, int, int);
|
|
|
|
void DrawHorizontalLineSeg(Y, LeftX, RightX, Color) {
|
|
int X;
|
|
|
|
/* Draw each pixel in the horizontal line segment, starting with
|
|
the leftmost one */
|
|
for (X = LeftX; X <= RightX; X++)
|
|
DrawPixel(X, Y, Color);
|
|
}
|
|
|
|
/* Draws the pixel at (X, Y) in color Color in VGA mode 13h */
|
|
static void DrawPixel(int X, int Y, int Color) {
|
|
unsigned char far *ScreenPtr;
|
|
|
|
#ifdef __TURBOC__
|
|
ScreenPtr = MK_FP(SCREEN_SEGMENT, Y * SCREEN_WIDTH + X);
|
|
#else /* MSC 5.0 */
|
|
FP_SEG(ScreenPtr) = SCREEN_SEGMENT;
|
|
FP_OFF(ScreenPtr) = Y * SCREEN_WIDTH + X;
|
|
#endif
|
|
*ScreenPtr = (unsigned char) Color;
|
|
}
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><B>LISTING 40.3 POLYGON.H</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* POLYGON.H: Header file for polygon-filling code */
|
|
|
|
#define CONVEX 0
|
|
#define NONCONVEX 1
|
|
#define COMPLEX 2
|
|
|
|
/* Describes a single point (used for a single vertex) */
|
|
struct Point {
|
|
int X; /* X coordinate */
|
|
int Y; /* Y coordinate */
|
|
};
|
|
/* Describes a series of points (used to store a list of vertices that
|
|
describe a polygon; each vertex connects to the two adjacent
|
|
vertices; the last vertex is assumed to connect to the first) */
|
|
struct PointListHeader {
|
|
int Length; /* # of points */
|
|
struct Point * PointPtr; /* pointer to list of points */
|
|
};
|
|
/* Describes the beginning and ending X coordinates of a single
|
|
horizontal line (used only by fast polygon fill code) */
|
|
struct HLine {
|
|
int XStart; /* X coordinate of leftmost pixel in line */
|
|
int XEnd; /* X coordinate of rightmost pixel in line */
|
|
};
|
|
/* Describes a length-long series of horizontal lines, all assumed to
|
|
be on contiguous scan lines starting at YStart and proceeding
|
|
downward (used to describe a scan-converted polygon to the
|
|
low-level hardware-dependent drawing code) (used only by fast
|
|
polygon fill code). */
|
|
struct HLineList {
|
|
int Length; /* # of horizontal lines */
|
|
int YStart; /* Y coordinate of topmost line */
|
|
struct HLine * HLinePtr; /* pointer to list of horz lines */
|
|
};
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><B>LISTING 40.4 L40-4.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* Sample program to exercise the polygon-filling routines */
|
|
|
|
#include <conio.h>
|
|
#include <dos.h>
|
|
#include “polygon.h”
|
|
|
|
#define DRAW_POLYGON(PointList,Color,Shape,X,Y) \
|
|
Polygon.Length = sizeof(PointList)/sizeof(struct Point); \
|
|
Polygon.PointPtr = PointList; \
|
|
FillPolygon(&Polygon, Color, Shape, X, Y);
|
|
|
|
void main(void);
|
|
extern int FillPolygon(struct PointListHeader *, int, int, int, int);
|
|
|
|
void main() {
|
|
int i, j;
|
|
struct PointListHeader Polygon;
|
|
static struct Point Polygon1[] =
|
|
{{0,0},{100,150},{320,0},{0,200},{220,50},{320,200}};
|
|
static struct Point Polygon2[] =
|
|
{{0,0},{320,0},{320,200},{0,200},{0,0},{50,50},
|
|
{270,50},{270,150},{50,150},{50,50}};
|
|
static struct Point Polygon3[] =
|
|
{{0,0},{10,0},{105,185},{260,30},{15,150},{5,150},{5,140},
|
|
{260,5},{300,5},{300,15},{110,200},{100,200},{0,10}};
|
|
static struct Point Polygon4[] =
|
|
{{0,0},{30,-20},{30,0},{0,20},{-30,0},{-30,-20}};
|
|
static struct Point Triangle1[] = {{30,0},{15,20},{0,0}};
|
|
static struct Point Triangle2[] = {{30,20},{15,0},{0,20}};
|
|
static struct Point Triangle3[] = {{0,20},{20,10},{0,0}};
|
|
static struct Point Triangle4[] = {{20,20},{20,0},{0,10}};
|
|
union REGS regset;
|
|
|
|
/* Set the display to VGA mode 13h, 320×200 256-color mode */
|
|
regset.x.ax = 0×0013;
|
|
int86(0x10, ®set, ®set);
|
|
|
|
/* Draw three complex polygons */
|
|
DRAW_POLYGON(Polygon1, 15, COMPLEX, 0, 0);
|
|
getch(); /* wait for a keypress */
|
|
DRAW_POLYGON(Polygon2, 5, COMPLEX, 0, 0);
|
|
getch(); /* wait for a keypress */
|
|
DRAW_POLYGON(Polygon3, 3, COMPLEX, 0, 0);
|
|
getch(); /* wait for a keypress */
|
|
|
|
/* Draw some adjacent nonconvex polygons */
|
|
for (i=0; i<5; i++) {
|
|
for (j=0; j<8; j++) {
|
|
DRAW_POLYGON(Polygon4, 16+i*8+j, NONCONVEX, 40+(i*60),
|
|
30+(j*20));
|
|
}
|
|
}
|
|
getch(); /* wait for a keypress */
|
|
|
|
/* Draw adjacent triangles across the screen */
|
|
for (j=0; j<=80; j+=20) {
|
|
for (i=0; i<290; i += 30) {
|
|
DRAW_POLYGON(Triangle1, 2, CONVEX, i, j);
|
|
DRAW_POLYGON(Triangle2, 4, CONVEX, i+15, j);
|
|
}
|
|
}
|
|
for (j=100; j<=170; j+=20) {
|
|
/* Do a row of pointing-right triangles */
|
|
for (i=0; i<290; i += 20) {
|
|
DRAW_POLYGON(Triangle3, 40, CONVEX, i, j);
|
|
}
|
|
/* Do a row of pointing-left triangles halfway between one row
|
|
of pointing-right triangles and the next, to fit between */
|
|
for (i=0; i<290; i += 20) {
|
|
DRAW_POLYGON(Triangle4, 1, CONVEX, i, j+10);
|
|
}
|
|
}
|
|
getch(); /* wait for a keypress */
|
|
|
|
/* Return to text mode and exit */
|
|
regset.x.ax = 0x0003;
|
|
int86(0x10, &regset, &regset);
|
|
}
|
|
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="40-02.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="40-04.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|