Software Polygon Rendering Source Code
I rescued this off a 5 1/4" floppy the other day.
Some software only polygon code I wrote for making games in 1988. Props to "Foley VanDam"
#define demo 1
/************************************************************/
/* Polygon code by Mike Johnson 9/9/88 */
/* */
/* True concave polygones. Very hi-preformance. Portable. */
/* For highest performance it calles hline,line, and point */
/* routines, though you could just use a line routine. */
/*----------------------------------------------------------*/
/* mycal@netacsys.com */
/* All Rights Reserved (c)1988 */
/************************************************************/
#include
#define MAXEDGES 12 /* maximum edges in polygon */
#define DRAW_EDGES 0 /* set to draw poly edges */
#define CONCAVE 1 /* set for concave polygons */
unsigned int lines[200]; /* Array of line start addresses */
struct points
{
short x,y;
};
/* */
/* structure for the edges of a polygon */
/* */
// union REGS regs;
struct edge
{
/* end points */
short xstart;
short ystart;
short xend;
short yend;
/* DDA vars */
short dx; /* deltaX xend-xstart */
short dy; /* deltaY yend-ystart */
short error; /* */
short incS; /* increment error */
short incSE; /* reset increment */
short x; /* current x */
short y; /* current y */
short xdir; /* x direction -1 or 1 */
struct edge *ptr; /* pointer to next in active list */
};
/****************************************************************/
/* Poly(verts,num) - */
/* verts is a pointer to an array of polygon vertices. */
/* num is the number of vertices in the array. */
/* color is set before this call. */
/*--------------------------------------------------------------*/
/* */
/****************************************************************/
poly(verts,num,color)
struct points *verts;
int num;
int color;
{
struct edge edges[MAXEDGES];/* edge table */
struct edge tedge;
struct edge *ptr,*nptr,*tptr,*lptr; /* pointer to an edge table */
int i,j; /* counter */
int flag;
int ypos; /* ypos = scanline */
int eypos; /* end of the polygon */
int next; /* next value to recalc the active list */
int len;
int xst;
ypos = 32767;
eypos= 0;
i=0;
switch(num){
/* polygon is just a point */
case 1:
i=2;
i=1;
i=0;
// polyline(verts[0].y,verts[0].x,verts[0].x);
return;
/* polygon is just a line, nothing to fill */
case 2:
i=0;
i=1;
i=2;
// evgaline_640/*polyline1*/(verts[0].x,verts[0].y,verts[1].x,verts[1].y,color);
return;
default:
/* this is a real polygon, so lets do it */
/* copy first vert to last for wraparound */
verts[num] = verts[0];
/* we can only do MAXEDGES */
if (num>MAXEDGES)
num = MAXEDGES;
/* build edge table */
i=0; /* edge number */
j=0; /* vert number */
while ( i<= num-1) {
/* always have a positive dy */
if (verts[j].y < verts[j+1].y) {
edges[i].y = edges[i].ystart = verts[j].y;
edges[i].x = edges[i].xstart = verts[j].x;
edges[i].yend = verts[j+1].y;
edges[i].xend = verts[j+1].x;
}else{
edges[i].y = edges[i].ystart = verts[j+1].y;
edges[i].x = edges[i].xstart = verts[j+1].x;
edges[i].yend = verts[j].y;
edges[i].xend = verts[j].x;
} /* end if */
/* find start and end pos of polygon */
if (ypos>edges[i].ystart) /* find smallest y */
ypos=edges[i].ystart;
if (eypos= edges[i].ystart) &&
(ypos < edges[i].yend))
{
if (ptr==0) {
ptr = &edges[i];
edges[i].ptr = 0;
nptr = ptr;
}else {
if(ptr->x > edges[i].x) { // insert at head of list
edges[i].ptr = ptr;
ptr = &edges[i];
} else {
flag = 0;
lptr = ptr;
tptr = ptr->ptr;
while(!flag){
if(tptr==0) { // insert at end of list
nptr->ptr=&edges[i];
edges[i].ptr=0;
nptr=nptr->ptr;
flag=1;
}else if(tptr->x > edges[i].x) {
edges[i].ptr = tptr;
lptr->ptr = &edges[i];
flag = 1;
} else {
lptr= tptr;
tptr = tptr->ptr;
}
}/*while*/
}/*else*/
}/*else*/
if(next>edges[i].yend) // next calc at edge end?
next = edges[i].yend ; // yes save ypos
}else
/* see if next edge recalc occures on new edge */
if ((yposedges[i].ystart))
next = edges[i].ystart;
} /*end for*/
} /*endif*/
/**********************/
/* draw the scan line */
/**********************/
nptr = ptr;
while (nptr) {
xst = nptr->x;
len = nptr->ptr->x - xst;
// evgaline_640(nptr->x,ypos,nptr->ptr->x,ypos,color);
asm {
mov ax, 0A000H // Video adapter is at A0000H
mov es, ax
mov al, byte ptr color
mov ah, al
mov di, ypos // Lookup (200 - y) * 320
shl di, 1
mov di, word ptr lines[di]
add di, xst // add starting x coordinate
mov cx, len
cld // Clear direction flag
inc cx // Always at least one byte
test di, 1 // If odd address, set one byte
jz Set_Even
stosb
dec cx
jz Set_Done
}
Set_Even:
asm {
shr cx, 1 // Set rest as words
rep stosw
adc cx, cx // Set any last byte
rep stosb
}
Set_Done:
// printf("Y = %5d, X = %5d to %5d\n",ypos,nptr->x,nptr->ptr->x);
nptr = nptr->ptr->ptr;
}
/****************************************/
/* Update DDA variables in active edges */
/****************************************/
nptr = ptr;
while (nptr) {
if (nptr->dy < nptr->dx) {
if (nptr->error > 0){
nptr->error = nptr->error + nptr->incSE;
nptr->x = nptr->x + nptr->xdir;
//nptr->y = nptr->y + 1;
} /*endif*/
while(nptr->error <= 0) {
nptr->error = nptr->error + nptr->incS;
nptr->x = nptr->x + nptr->xdir;
} /*endwhile*/
}else{
if (nptr->error>0){
nptr->error = nptr->error + nptr->incSE;
nptr->x = nptr->x + nptr->xdir;
//nptr->y = nptr->y + 1;
} /*endif*/
else {
nptr->error = nptr->error + nptr->incS;
//nptr->y = nptr->y + 1;
} /*endelse*/
}/*endelse*/
nptr = nptr->ptr;
} /*endwhile*/
ypos = ypos + 1; /* set to next scan line */
/****************************************************/
/* scan through active edge list and see if there */
/* has been an edge order change. if so set recalc */
/* flag. NOTE: not needed for non concave polys */
/****************************************************/
#if CONCAVE
nptr = ptr;
while (nptr->ptr) { // check to see if edges are in correct order
if((nptr->ptr->x <= nptr->x))
next=ypos; // force recalc
nptr = nptr->ptr;
}
#endif
} /*endwhile*/
}/*endswitch*/
} /* end of poly render */
#if 1
main()
{
struct points verts[20];
long stime,etime,dtime;
float sdtime;
int temp;
int i, y,j;
union REGS regs;
/* Initialize the table of lines */
asm {
mov ax, ds
mov es, ax
cld
mov di, offset lines
mov ax, 320 * (200 - 1) // 200 lines of 320 bytes each
}
Init_Loop:
asm {
stosw // Put in value
sub ax, 320 // Move to next line
jnc Init_Loop // Do all the lines
}
regs.x.ax =0x0013;
int86(0x10, ®s, ®s);
//for(i=1;i<100;i++) {
verts[0].x =10;
verts[0].y =10;
verts[1].x =50;
verts[1].y =40;
verts[2].x =30;
verts[2].y =30;
verts[3].x =40;
verts[3].y =70;
for (i=1; i < 20000; i++) poly(verts,4,(i >> 8) & 0xF);
/*
verts[1].x =100;
verts[1].y =100;
verts[2].x =200;
verts[2].y =200;
verts[3].x =200;
verts[3].y =100;
verts[4].x =100;
verts[4].y =200;
verts[1].x =100;
verts[1].y =100;
verts[2].x =200;
verts[2].y =200;
verts[3].x =150;
verts[3].y =225;
verts[4].x =100;
verts[4].y =150;
verts[5].x =125;
verts[5].y =175;
*/
// stime = get_tick();
/* for(i=1;i<500;i++){
for(j=0;j<10;j++) {
verts[j].x = (rand()%600+20);
verts[j].y = (rand()%400+20);
}
poly(verts,(rand()%7+3),(rand()%14+1));
/* vert array, # of verts, color */
// }
// etime = get_tick();
// dtime = etime-stime;
// sdtime = (dtime/18.2);
// text();
// printf("Poly draw test (500) = %f seconds, %d ticks\n",sdtime,dtime);
/*
for(j=1;j<301;j++){
for(i=1;i<25;i++) {
verts[i].x = (rand()%639);
verts[i].y = (rand()%479);
}
poly(verts,(rand()%20+4),(rand()%14+1));
/* vert array, # of verts, color */
//}
// etime = regs.x.dx-stime;
// int86(0x1a, ®s, ®s);
// stime = regs.x.dx;
// scanf("%c",&temp);
regs.x.ax = 0x0003;
int86(0x10,®s,®s);
//printf("poly = %d rect = %d \n",etime,stime);
}
#endif
|