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

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!