Graphics source in C: hsalgs/tiler.c
Ken Turkowski
ken at turtleva.UUCP
Thu Dec 22 16:42:51 AEST 1983
echo x - hsalgs/tiler.c
cat >hsalgs/tiler.c <<'!Funky!Stuff!'
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tiler.c - tiler for convex polygons - takes piped input with -1 < x < 1
-.75 < y < .75 and scan converts to the specified device
Keywords:
- device <dvc> <bits> <divisions> <frmnum>
- polygon <npts> (followed by appropriate number of vertices)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define NULLCHAR '\0'
#define LINE_LENGTH 81
#define POLYSIZE 64
#define HRES 640
#define VRES 484
#define SUBPIX .01 /* minimum allowable width or height */
#define MAXLONG 0x7FFFFFFF
#define MAXFLOAT 0xFFFF7FFF /* yes, that's right (look in the VAX manual) */
#define SQR(x) ((x)*(x))
/* parameters for image placement in big buffer memory */
static short Xofset,Yofset/*,rgb_24bit,rgb_16bit,bw_8bit,bw_4bit*/,field;
static short hres,vres/*,Y_pos,xleft,xrght*/;
static short xofset,yofset,maxY,fb,aed,byte;
/* +++++++++++++++++++++++++ MAIN +++++++++++++++++++++++++++++++++++++++++ */
main()
{
char instrg[LINE_LENGTH],keywd[LINE_LENGTH],remainder[LINE_LENGTH],dvc[3];
char *eofchk,*gets();
short i;
double atof(),sqrt(),fabs();
/* scan input for keywords */
do
{ short bits,divisions,frmnum;
eofchk = gets(instrg);
if (eofchk != NULL) get_term(instrg,keywd,remainder); /* get keyword */
else continue;
if ( strcmp(keywd,"device") == 0 ) /* device description */
{ sscanf(remainder,"%s %hd %hd %hd",dvc,&bits,&divisions,
&frmnum);
if (bits == 32) rgbtilinit(bits,divisions,frmnum);
else if (strcmp(dvc,"bb") == 0) bptilinit(frmnum,divisions);
else if (strcmp(dvc,"fb") == 0) ptilinit(bits);
else if (strcmp(dvc,"aed") == 0) aptilinit(0);
else error(" bad device name - %s\n",dvc);
}
else if ( strcmp(keywd,"polygon") == 0 ) /* begin polygon description */
{ short npts; struct { double x,y,z,r,g,b; } pts[POLYSIZE];
sscanf(remainder,"%hd",&npts);
if (bits == 32) /* full color */
{ for (i=0; i<npts; i++)
sscanf(gets(instrg),"%f %f %f %f %f",&pts[i].x,
&pts[i].y,&pts[i].r,&pts[i].g,&pts[i].b);
rgbtiler(npts,pts);
}
else /* pseudocolor */
{ for (i=0; i<npts; i++)
sscanf(gets(instrg),"%f %f %f",&pts[i].x,&pts[i].y,
&pts[i].r);
ptiler(npts,pts);
}
}
else fprintf(stderr,"tiler - bad keyword %s\n",instrg);
} while (eofchk != NULL); /* continue until input exhausted */
} /* done with main program */
/* +++++++++++++++++++++ GET_TERM +++++++++++++++++++++++++++++++++ */
get_term(instrg,term,remainder) /* remove first term from string */
char *instrg,*term,*remainder; /* blanks, tabs, nulls, commas are separators */
{ short i,index1,index2;
index1 = 0; /* find first non-separator */
while ((instrg[index1] == ' ') || (instrg[index1] == '\t') ||
(instrg[index1] == NULLCHAR) || (instrg[index1] == ',' )) index1++;
index2 = index1; /* find next separator */
while ((instrg[index2] != ' ') && (instrg[index2] != '\t') &&
(instrg[index2] != NULLCHAR) && (instrg[index2] != ',' ) &&
(instrg[index2] != '\n')) index2++;
for (i=index1; i<index2; i++) term[i-index1] = instrg[i];
term[i-index1] = NULLCHAR;
while ((instrg[i] != NULLCHAR) && (instrg[i] != '\n'))
{ remainder[i-index2] = instrg[i]; i++; }
remainder[i-index2] = NULLCHAR;
}
/* +++++++++++++++++++++++++ RGBTILINIT ++++++++++++++++++++++++++++++++++++ */
rgbtilinit(bits,divisions,frmnum) /* init tiler, set pointer to frame buffer */
short bits,divisions,frmnum;
{ /* short i; */ double pow(),sqrt(); long array[4];
/* static short palred[256],palgrn[256],palblu[256]; /* pallette */
if (frmnum == 0) system("bbreset");
if (bbopen() < 0) exit(); /* give up if bb won't open */
array[0] = frmnum; array[1] = divisions; array[2] = bits; array[3] = 1;
bbwrite(0,502,array,4); /* load animation control */
divisions = sqrt((double)divisions);
hres = (32/divisions)*20; vres = 484/divisions;
field = frmnum % (32/bits); frmnum /= 32/bits;
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);
}
/* +++++++++++++++++++++++++ RGBTILER ++++++++++++++++++++++++++++++++++++++ */
rgbtiler(npts,pts) /* tile a convex polygon with vertices taken clockwise */
short npts; struct { double x,y,z,r,g,b; } pts[];
{
struct { double x,r,g,b; } l_edge,r_edge,l_incr,r_incr;
short i,iy,l_lnth,r_lnth,lpt,rpt,ptcnt,top_pt;
double top,ceil(),floor();
if (npts < 3) { printf(" degenerate polygon\n"); return; }
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; }
pts[i].r *= 255.; pts[i].g *= 255.; pts[i].b *= 255.;
}
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 r,rxinc,g,gxinc,b,bxinc;
long line[HRES];
while((l_lnth == 0) && (ptcnt <= npts))
{ bmkedge(&lpt,pts,&l_edge,&l_incr,&l_lnth,npts-1,npts);
if (l_lnth >= 0) ptcnt++; else break; }
while((r_lnth == 0) && (ptcnt <= npts))
{ bmkedge(&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;
r = l_edge.r; if (numpix>0) rxinc = (r_edge.r - r)/numpix;
g = l_edge.g; if (numpix>0) gxinc = (r_edge.g - g)/numpix;
b = l_edge.b; if (numpix>0) bxinc = (r_edge.b - b)/numpix;
for (ix=xlft; ix<xrgt; ix++) /* write scan segment */
{ line[ix] = (long)b + ((long)g << 8) + ((long)r << 16);
r += rxinc; g += gxinc; b += bxinc;
}
bbwrite(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.r += l_incr.r; r_edge.r += r_incr.r;
l_edge.g += l_incr.g; r_edge.g += r_incr.g;
l_edge.b += l_incr.b; r_edge.b += r_incr.b;
}
}
/* ++++++++++++++++++++++++++ BMKEDGE +++++++++++++++++++++++++++++++++++++ */
/* calculate edge block for tiler */
bmkedge(ptr,pts,edge,incmnts,lnth,ptrinc,npts)
short *ptr,*lnth,ptrinc,npts;
struct { double x,y,z,r,g,b; } pts[];
struct { double x,r,g,b; } *edge,*incmnts;
{
short opt; double floor(),ydif;
opt = *ptr; *ptr = (*ptr + ptrinc) % npts; /* increment vertex ptr. */
edge->x = pts[opt].x;
edge->r = pts[opt].r;
edge->g = pts[opt].g;
edge->b = pts[opt].b;
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->r = (pts[*ptr].r - pts[opt].r) / ydif;
incmnts->g = (pts[*ptr].g - pts[opt].g) / ydif;
incmnts->b = (pts[*ptr].b - pts[opt].b) / ydif;
}
else
{ incmnts->x = pts[*ptr].x - pts[opt].x;
incmnts->r = pts[*ptr].r - pts[opt].r;
incmnts->g = pts[*ptr].g - pts[opt].g;
incmnts->b = pts[*ptr].b - pts[opt].b;
}
}
/* ++++++++++++++++++++++ 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)? 486/2 : 243/2;
maxY = vres * 2;
fb = TRUE; aed = FALSE;
}
/* ++++++++++++++++++++++++ APTILINIT +++++++++++++++++++++++++++++++++++++ */
aptilinit(quad) /* initialize tiler for aed display */
short quad;
{ 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) /* initialize for animation on big buffer */
short frmnum,divisions;
{ long array[4]; long byte,mult; double sqrt();
if (frmnum == 0) bbinit(); else bbopen(); /* init if 1st frame in seq. */
array[0] = frmnum; array[1] = divisions; array[2] = 8; array[3] = 1;
bbwrite(0,502,array,4); /* load animation control */
byte = ((3 - frmnum%4) << 6) | 0x3F; bbwrite(2,497,&byte,1);/* set byte */
mult = sqrt((double)divisions); array[0] = mult;
array[1] = ((frmnum/4)%mult) * 32/mult;
array[2] = ((frmnum/4)/mult) * 2 * 242/mult;
bbwrite(1,501,array,3); /* set zoom and pan */
divisions = sqrt((double)divisions);
hres = (32/divisions)*20; vres = 484/divisions;
byte = frmnum % 4; frmnum /= 4;
xofset = (frmnum % divisions) * hres;
yofset = (divisions-1 - (frmnum / divisions)) * vres;
hres = hres/2; vres = vres/2;
fb = FALSE; aed = FALSE;
}
/* ++++++++++++++++++++++++++ PTILER ++++++++++++++++++++++++++++++++++++++++ */
ptiler(npts,pts) /* tile a convex polygon with vertices taken clockwise */
short npts;
struct { double x, y, z, tns, g, b; } 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); /* aed dma makes 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;
}
}
/* +++++++++++++++++++++++++++ MKEDGE +++++++++++++++++++++++++++++++++++++++ */
mkedge(ptr,pts,edge,incmnts,lnth,ptrinc,npts) /*calculate edge block for tiler*/
short *ptr,*lnth,ptrinc,npts;
struct { double x,y,z,t,g,b; } 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!
More information about the Comp.sources.unix
mailing list