[net.sources] Graphics source in C: hsalgs/ptiler.c

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!