ken@turtleva.UUCP (Ken Turkowski) (12/16/83)
echo x - hsalgs/jag_tiler.c cat >hsalgs/jag_tiler.c <<'!Funky!Stuff!' /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rgbtiler.c - simpler anti-aliasing tiler for convex polygons Entries: - rgbtilinit(size,divisions,frmnum) - gets ptr to big buffer, initializes. - rgbtiler(npts,pts) - short npts; struct { double x,y,z,r,g,b; } pts[]; ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #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 TRUE 1 #define FALSE 0 #define SQR(x) ((x)*(x)) /* parameters for image placement in big buffer memory (used by shiny_tlr.c) */ short Xofset,Yofset,rgb_24bit,rgb_16bit,bw_8bit,bw_4bit,field; short hres,vres,Y_pos,xleft,xrght,cvr[642]; double red[642],grn[642],blu[642]; /* ++++++++++++++++++++++++ GETSEG +++++++++++++++++++++++++++++++++++++++ */ getseg(xleft,xrght) /* read and unpack section of scanline */ short xleft,xrght; { short i; unsigned long line[642]; bbread(xleft,Y_pos,&line[xleft],xrght-xleft+1); for (i=xleft; i<=xrght; i++) { cvr[i] = line[i] >> 24; red[i] = (line[i] >> 16) & 255; grn[i] = (line[i] >> 8) & 255; blu[i] = line[i] & 255; } } /* ++++++++++++++++++++++++ PUTSEG ++++++++++++++++++++++++++++++++++++++++ */ putseg(xleft,xrght) /* pack up and write a section of scanline */ short xleft,xrght; { short i; unsigned long line[642]; for (i=xleft; i<=xrght; i++) { line[i] = ( cvr[i] << 24) | ((short)red[i] << 16) | ((short)grn[i] << 8) | (short)blu[i]; /* printf(" %d",cvr[i]); /* diagnostic */ } bbwrite(xleft,Y_pos,&line[xleft],xrght-xleft+1); /* printf(" line %d \n",Y_pos); /* diagnostic */ } /* +++++++++++++++++++++++++ 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 (bbopen() < 0) exit(); switch (bits) { case 4 : { bw_4bit = TRUE; break; } case 8 : { bw_8bit = TRUE; break; } case 16 : { rgb_16bit = TRUE; break; } case 24 : { rgb_24bit = TRUE; break; } } if (frmnum == 0) { if (bw_4bit) for (i=0; i<16; i++) /* special pallette for 4-bit images */ { short j; palred[i] = palgrn[i] = palblu[i] = 4096. * pow(i/256.,.43); j = i << 4; palred[j] = palgrn[j] = palblu[j] = palred[i]; } else for (i=0; i<256; i++) palred[i] = palgrn[i] = palblu[i] = 4096. * pow(i/256.,.43); bbpalw(palred,palgrn,palblu,0,256); } array[0] = frmnum; array[1] = divisions; array[2] = bits; array[3] = 1; bbcntrlw(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,xn,yn,zn,t; } 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,xn,yn,zn,trns; } 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; } } !Funky!Stuff!