ken@turtleva.UUCP (Ken Turkowski) (12/22/83)
echo x - hsalgs/ptiler.c cat >hsalgs/ptiler.c <<'!Funky!Stuff!' /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ptiler.c - scan convert polygons - smooth shaded Entries: - ptilinit(quad) - bptilinit(frmnum,divisions) - ptiler(npts,pts) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include <stdio.h> #define HRES 640 /* max x - resolution */ #define VRES 484 /* max y - resolution */ #define SUBPIX .01 /* minimum sub-pixel feature size used for avoiding end conditions */ #define TRUE 1 #define FALSE 0 #define SQR(x) ((x)*(x)) static short xofset,yofset,maxY,hres,vres,fb,aed,byte; /* ++++++++++++++++++++++ PTILINIT +++++++++++++++++++++++++++++++++++++ */ ptilinit(quad) /* initialize tiler (set up quadrant) */ short quad; { fbquad(quad); /* open frame buffer */ xofset = yofset = 0; hres = (quad == 0)? 512/2 : 256/2; vres = (quad == 0)? 484/2 : 242/2; maxY = vres * 2; fb = TRUE; aed = FALSE; } /* ++++++++++++++++++++++++ ATILINIT +++++++++++++++++++++++++++++++++++++ */ aptilinit() /* initialize tiler for aed display */ { aed_init(0); /* open aed frame buffer */ xofset = yofset = 0; hres = 512/2; vres = 483/2; maxY = vres * 2; aed = TRUE; fb = FALSE; } /* ++++++++++++++++++++++++ BPTILINIT +++++++++++++++++++++++++++++++++++++ */ bptilinit(frmnum,divisions) /* initilize for animation on big buffer */ short frmnum,divisions; { double sqrt(); long array[4]; if (bbopen() < 0) exit(); /* get big buffer */ divisions = sqrt((double)divisions); /* byte = frmnum % 4; bits = frmnum /= 4; */ array[0] = frmnum; array[1] = divisions; array[2] = 8; array[3] = 1; bbwrite(0,502,array,4); /* load animation control */ hres = (32/divisions)*20; vres = 484/divisions; xofset = (frmnum % divisions) * hres; yofset = (divisions-1 - (frmnum / divisions)) * vres; hres /= 2; vres /= 2; /* use half-res for scaling later */ bbzoom(divisions, xofset + hres, yofset + vres + 1); fb = aed = FALSE; } /* ++++++++++++++++++++++++++ PTILER ++++++++++++++++++++++++++++++++++++++++ */ ptiler(npts,pts) /* tile a convex polygon with vertices taken clockwise */ short npts; struct { double x, y, z, tns, g, b, xn, yn, zn, t; } pts[]; { struct { double x, y, z, tns; } l_edge,r_edge,l_incr,r_incr; short i,iy,l_lnth,r_lnth,lpt,rpt,ptcnt,top_pt; double top,ceil(),floor(); top = 0.0; for(i=0; i<npts; i++) /* scale for resolution & find top vertex */ { pts[i].x = hres * (pts[i].x + 1.) + xofset + SUBPIX; pts[i].y = vres * (pts[i].y + 1.) + yofset + SUBPIX; if(pts[i].y > top) { top = pts[i].y; top_pt = i; } } l_lnth = r_lnth = 0; /* scanlines left */ lpt = rpt = top_pt; ptcnt = 0; /* vertex pointers */ iy = floor(top); /* top scanline */ while(ptcnt <= npts) { short ix,xlft,xrgt,numpix; double t,txinc; short line[HRES]; unsigned char linbuf[HRES]; while((l_lnth == 0) && (ptcnt <= npts)) { mkedge(&lpt,pts,&l_edge,&l_incr,&l_lnth,npts-1,npts); if (l_lnth >= 0) ptcnt++; else break; } while((r_lnth == 0) && (ptcnt <= npts)) { mkedge(&rpt,pts,&r_edge,&r_incr,&r_lnth,npts+1,npts); if (r_lnth >= 0) ptcnt++; else break; } xlft = floor(l_edge.x); xrgt = floor(r_edge.x); numpix = xrgt - xlft; t = l_edge.tns; if (numpix>0) txinc = (r_edge.tns - t)/numpix; for (ix=xlft; ix<xrgt; ix++) /* write scan segment */ { line[ix] = t; t += txinc; } if (fb) fbwrite(xlft,maxY-iy,&line[xlft],numpix);/* write to FB */ else if (aed) { for (ix=xlft; ix<xrgt; ix++) { linbuf[ix] = line[ix]; aed_mov(ix,iy); aed_wpx(linbuf[ix]); } /* aed_write(xlft, iy, line, xrgt-xlft); /* May cause I/O errors */ } else bbwbyte(byte,xlft,iy,&line[xlft],numpix);/* write to BB */ if ((l_lnth < 0) && (r_lnth < 0)) break; /* done if at bottom vtx */ --iy; --l_lnth; --r_lnth; l_edge.x += l_incr.x; r_edge.x += r_incr.x; l_edge.tns += l_incr.tns; r_edge.tns += r_incr.tns; } } /* calculate edge block for tiler */ mkedge(ptr,pts,edge,incmnts,lnth,ptrinc,npts) short *ptr,*lnth,ptrinc,npts; struct { double x,y,z,t,g,b,xn,yn,zn,trns; } pts[]; struct { double x,y,z,t; } *edge,*incmnts; { short opt; double floor(),ydif; opt = *ptr; *ptr = (*ptr + ptrinc) % npts; /* increment vertex ptr. */ edge->x = pts[opt].x; edge->t = pts[opt].t; if (pts[opt].y < pts[*ptr].y) { *lnth = -1; return; } /* bottom vtx */ *lnth = floor(pts[opt].y) - floor(pts[*ptr].y); if (*lnth > 1) { ydif = *lnth; incmnts->x = (pts[*ptr].x - pts[opt].x) / ydif; incmnts->t = (pts[*ptr].t - pts[opt].t) / ydif; } else { incmnts->x = pts[*ptr].x - pts[opt].x; incmnts->t = pts[*ptr].t - pts[opt].t; } } !Funky!Stuff!