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

ken@turtleva.UUCP (Ken Turkowski) (12/16/83)

echo x - hsalgs/ftb_pxls.c
cat >hsalgs/ftb_pxls.c <<'!Funky!Stuff!'
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ftb_pxls.c - writes pixels for front-to-back algorithms using coverage
                  bits
        Entries:
        - ftb_pxls(X_pos,pixel,coverage)
        - getseg(Y_pos,xleft,xrght)
        - putseg(Y_pos,xleft,xrght)
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

#define X       0
#define Y       1
#define Z       2

#define R       0
#define G       1
#define B       2
#define T       3
#define XN      4
#define YN      5
#define ZN      6
#define TX_X    7
#define TX_Y    8

#define NORMS            9
#define NORM_PARMS       6

#define LT_R            3
#define LT_G            4
#define LT_B            5

#define TX_RES        128               /* texture image resolution */

#define HRES          640
#define TRANS_MIN     .02               /* minimum effective transmittance */
#define MAXOBJ          2

#define sqr(x)   ((x)*(x))

short    cvr[HRES+2];
double   red[HRES+2],grn[HRES+2],blu[HRES+2];  /* scanline buffer */
                                /* global variables for pixel output routine */
extern short    num_lights,hilit_power,txtr,object;
extern struct { short r,g,b,t,s; }  texture[MAXOBJ][TX_RES][TX_RES];



/* ++++++++++++++++++++++++ GETSEG +++++++++++++++++++++++++++++++++++++++ */
getseg(Y_pos,xleft,xrght)             /* read and unpack section of scanline */
short Y_pos,xleft,xrght;
{   short i;   unsigned long line[642]; 
    /* for (i=xleft; i<=xrght; i++) line[i] = 0; */
    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(Y_pos,xleft,xrght)          /* pack up and write a section of scanline */
short Y_pos,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]; 
    } 
    bbwrite(xleft,Y_pos,&line[xleft],xrght-xleft+1);
/* printf(" scanline %d written, %d - %d\n",Y_pos,xleft,xrght); */
}



/* +++++++++++++++++++++++++++ FTB_PXLS +++++++++++++++++++++++++++++++++++ */
void  ftb_pxls(X_pos,pixel,covrge)      /* blend pixels using coverage bits */
short X_pos;    double pixel[],covrge;
{   double oldcvr,mag_norm,hilit_value,newred,newgrn,newblu,px_trans,pow();
    short i,tx,ty;    struct { short r,g,b,t,s; } *txtr_ptr;
                                                                
    if (txtr)  {  double pix_tx_x,pix_tx_y;
                  pix_tx_x = pixel[TX_X];       pix_tx_y = pixel[TX_Y];
                  while (pix_tx_x < 0.) pix_tx_y += 1.;
                  while (pix_tx_y < 0.) pix_tx_y += 1.;
                  tx = (short)(TX_RES * pix_tx_x) % TX_RES; /* txtr coords */
                  ty = (short)(TX_RES * pix_tx_y) % TX_RES;
                  txtr_ptr = &texture[object][tx][ty];
                  if (object > 0)
                        object = object + 1 -1;
               }
    newred = pixel[R];  newgrn = pixel[G];  newblu = pixel[B];
    
    if (txtr)                                     /* color from texture */
    {   newred *= txtr_ptr->r / 255.;
        newgrn *= txtr_ptr->g / 255.;
        newblu *= txtr_ptr->b / 255.;
    }
                                               /* transmittance from texture */
    px_trans = txtr?  pixel[T] * txtr_ptr->t / 255. : pixel[T]; 
    
    if (hilit_power > 0.)  for (i=0; i<num_lights; i++)          /* hilight */
    {   short k;
        k = NORMS + i*NORM_PARMS;            /* offset for highlight normals */
        mag_norm = sqr(pixel[k+X]) + sqr(pixel[k+Y]) + sqr(pixel[k+Z]);
        hilit_value = pow(sqr(pixel[k+Z]) / mag_norm , (double)hilit_power); 
        if (txtr)  hilit_value *= txtr_ptr->s / 255.;
        newred = newred + (pixel[k+LT_R] - newred) * hilit_value; 
        newgrn = newgrn + (pixel[k+LT_G] - newgrn) * hilit_value; 
        newblu = newblu + (pixel[k+LT_B] - newblu) * hilit_value; 
   
        if (px_trans > (1.0 - hilit_value))   px_trans = 1.0 - hilit_value;
    }

    if (px_trans > TRANS_MIN)  covrge *= 1.0 - px_trans; /* transmittance */ 

    oldcvr = cvr[X_pos];                      /* get previous pixel coverage */
    if (oldcvr == 0.) 
    {   cvr[X_pos] = covrge * 255. + .5;              /* no previous coverage */
        if (cvr[X_pos] > 0)
        {   red[X_pos] = newred;  grn[X_pos] = newgrn;  blu[X_pos] = newblu;   }
    } 
    else if (oldcvr < 255.)                    /* partial previous coverage */ 
    {   oldcvr /= 255.;                    /* convert to 0. <= oldcvr <= 1. */
        if ((oldcvr + covrge) >= 1.)                  /* pixel fully covered */
        {   covrge = 1. - oldcvr;    cvr[X_pos] = 255;   } 
        else                                      /* pixel partially covered */
        {   double adj;
            adj = oldcvr + covrge;      cvr[X_pos] = adj * 255. + .5; 
            oldcvr /= adj;              covrge /= adj; 
        }

        red[X_pos] = red[X_pos] * oldcvr + newred * covrge; 
        grn[X_pos] = grn[X_pos] * oldcvr + newgrn * covrge; 
        blu[X_pos] = blu[X_pos] * oldcvr + newblu * covrge;
    }
}
!Funky!Stuff!