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

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

echo x - hsalgs/bbox_task.c
cat >hsalgs/bbox_task.c <<'!Funky!Stuff!'
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
    bbox_task.c - displays bounding boxes on various devices  
        based on priority information from obj_sort and program names
        and file names gathered by scn_assmblr
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/

#include "scn_assmblr.h"

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

               

extern  short   ramp_lnth;                /* globals from obj_sort */
extern  double  view_angle;

static  FILE *bstream,*popen();
static  double sqrt(),cos(),sin(),cot_x,cot_y;
static  float   light_postn[3];    
static  short   bbits;
static  short   pol[6][4] = {   0, 1, 2, 3, 
                                4, 5, 6, 7,
                                7, 6, 1, 0,
                                3, 2, 5, 4,
                                1, 6, 5, 2,
                                7, 0, 3, 4,   }; 


/* ++++++++++++++++++++++++++ BBOX_TASK ++++++++++++++++++++++++++++++++++ */
bbox_task(obj_array,p_list,dvc,num_bits,divisions,frmnum) /* render bounding
                                                    boxes in priority order */
object_def *obj_array;  struct { short obj,insep; } p_list[];   char *dvc;
short num_bits,divisions,frmnum;
{   short i,cnt;

    bbits = num_bits;

    cot_x = cos(DtoR * view_angle/2.) / sin(DtoR * view_angle/2.);
    cot_y = cot_x / .75;

    if (!bbits)                                     /* line-drawing device */ 
        if      (strcmp(dvc,"meg") == 0)  bstream = popen("megdrawl","w");
        else if (strcmp(dvc,"vt" ) == 0)  bstream = popen("vtdrawl" ,"w");
        else if (strcmp(dvc,"crt") == 0)  bstream = popen("crtdrawl","w");
        else if (strcmp(dvc,"h19") == 0)  bstream = popen("h19drawl","w");
        else fprintf(stderr,"bbox_task: %s not a line-drawing device\n");
    else                                                /* raster device */
    {   double mag_light;
        bstream = popen("tiler","w");
        if (strcmp(dvc,"fb") == 0)
          fprintf(bstream,"device\t\t%s %d\n",dvc,frmnum);
        else
          fprintf(bstream,"device\t\t%s %d %d %d\n",dvc,bbits,divisions,frmnum);
        if (strcmp(dvc,"fb") == 0)
            cot_y *= 640./512.;  /* adjust for pixel distortion on 512x484 */
        else if (strcmp(dvc,"aed") == 0)
            cot_y = cot_x * 512./483.;
        light_postn[0] = light_postn[1] = light_postn[2] = 0.;
        transform(light_postn,obj_array[LIT].comp_mtx,light_postn);
        mag_light = sqrt(sqr(light_postn[0]) + sqr(light_postn[1]) + 
                                               sqr(light_postn[2])); 
        light_postn[0] /= mag_light;       /* normalize light source vector */
        light_postn[1] /= mag_light;
        light_postn[2] /= mag_light;
    }

    /* ----------------------- traverse priority list --------------------- */
    cnt = 0;
    while (p_list[cnt].obj != 0) cnt++;         /* count displayed objects */

    if (bbits) for (i=cnt-1; i>=0;  i--) bbox_output(&obj_array[p_list[i].obj]);
    else       for (i=0;     i<cnt; i++) bbox_output(&obj_array[p_list[i].obj]);

    pclose(bstream);                                 /* stop display program */
}





/* +++++++++++++++++++++++++++++++ BBOX_OUTPUT ++++++++++++++++++++++++++++ */
bbox_output(object)          /* expand bounding box to polygons and output */
object_def *object;
{   float bbx[8][3],clr_vec[3];    short kp,kv;    
    printf(" bbox for %s\n",object->name);
                                        /* convert bounding box to polygons */
    bbx[0][0] = bbx[1][0] = bbx[6][0] = bbx[7][0] = object->box[0];/*x*/
    bbx[2][0] = bbx[3][0] = bbx[4][0] = bbx[5][0] = object->box[1];
    bbx[0][1] = bbx[1][1] = bbx[2][1] = bbx[3][1] = object->box[2];/*y*/
    bbx[4][1] = bbx[5][1] = bbx[6][1] = bbx[7][1] = object->box[3];
    bbx[0][2] = bbx[3][2] = bbx[4][2] = bbx[7][2] = object->box[4];/*z*/
    bbx[1][2] = bbx[2][2] = bbx[5][2] = bbx[6][2] = object->box[5]; 
        
    for (kv=0; kv<8; kv++)                               /* transform */
        transform(bbx[kv],object->comp_mtx,bbx[kv]);

    /* get polygons in order */
    for (kp=0; kp<6; kp++)              /* for each of 6 sides on box */
    {   double poly[24],poly2[24];   float vec[3];    short i,npts;
    
        npts = 4; 
        for (i=0; i<npts; i++)                        /* copy polygon */
        {   poly[3*i+X] = bbx[pol[kp][i]][0]; 
            poly[3*i+Y] = bbx[pol[kp][i]][1];
            poly[3*i+Z] = bbx[pol[kp][i]][2]; 
        }
                                                        /* get normal vector */
        {   struct  { float x,y,z; } pt1,pt2;
            pt1.x = poly[3+X] - poly[0+X];
            pt1.y = poly[3+Y] - poly[0+Y];
            pt1.z = poly[3+Z] - poly[0+Z];
            pt2.x = poly[6+X] - poly[3+X];
            pt2.y = poly[6+Y] - poly[3+Y];
            pt2.z = poly[6+Z] - poly[3+Z];
            vec[0] = pt1.y*pt2.z - pt1.z*pt2.y;
            vec[1] = pt1.z*pt2.x - pt1.x*pt2.z;
            vec[2] = pt1.x*pt2.y - pt1.y*pt2.x;
        }
        if ((poly[0+X]*vec[0] + poly[0+Y]*vec[1] + poly[0+Z]*vec[2])
                 > 0)    continue;         /* skip out if backfacing */

        if (bbits)                              /* color calculation */ 
        {   double dot_prod,mag_vec; 
            mag_vec = sqrt(sqr(vec[0]) + sqr(vec[1]) + sqr(vec[2]));
            if (mag_vec > 0.0) dot_prod = (vec[0]*light_postn[0] +
                                           vec[1]*light_postn[1] +
                                       vec[2]*light_postn[2]) / mag_vec;
            else               dot_prod = 0.;
            if (dot_prod < 0.) dot_prod = 0.;
            dot_prod = .3 + .7*dot_prod;     /* add 30% ambient light */
            if ((bbits == 8) || (bbits == 10))         /* pseudocolor */
                clr_vec[0] = object->clr_num*ramp_lnth + 1 
                                         + (short)(dot_prod*ramp_lnth);
            else                                       /* full color */
            {   clr_vec[0] = dot_prod * object->clr[0];
                clr_vec[1] = dot_prod * object->clr[1];
                clr_vec[2] = dot_prod * object->clr[2];
            }
        }
        /* predistort and clip */ 
        for (i=0; i<3*npts; i+=3)
        {   poly[i+X] *= cot_x;    poly[i+Y] *= cot_y;   }
        polclp(0,&npts,poly,poly2,3); 
        if (npts < 3)   break;                                /* skip if out */ 

         /* do perspective divide */
        for (i=0; i<3*npts; i+=3)
        {   poly[i+X] /= poly[i+Z];    poly[i+Y] /= poly[i+Z];   }

                        /* send out polygons by vertex coordinates and colors */
        if (bbits)  fprintf(bstream,"polygon %d\n",npts); /* header for tiler */
        else    fprintf(bstream,"m %g %g 1.\n",   /* moveto 1st vtx for lines */
                                poly[3*(npts-1)+X],poly[3*(npts-1)+Y]);
                                                               /* pseudocolor */
        if ((bbits == 8) || (bbits == 10))  for (kv=0; kv<3*npts; kv+=3) 
               fprintf(bstream,"%g %g %g\n",poly[kv+X],poly[kv+Y],clr_vec[0]);
        else if (bbits == 32)  for (kv=0; kv<3*npts; kv+=3)     /* full color */
               fprintf(bstream,"%g %g %g %g %g\n",poly[kv+X],
                       poly[kv+Y],clr_vec[0],clr_vec[1],clr_vec[2]);
        else if (!bbits)  for (kv=0; kv<3*npts; kv+=3)        /* line drawing */
               fprintf(bstream,"d %g %g 1.\n",poly[kv+X],poly[kv+Y]);
    }
}



    
/* +++++++++++++++++++++++++++++ POLCLP +++++++++++++++++++++++++++++++++++++ */
polclp(pass,npts,pts,pt2,npars)                 /* polygon clipper (eyespace) */
    short *npts,pass,npars;    double pts[],pt2[];
{   short i,lk,m;   float dist,last_dist;
    if ((pass == 4) || (*npts < 3))  return;        /* completion conditions */
    last_dist = 0.0;    m = 0;    lk = 0;
    for (i=0; i<=*npts; i++)  
    {   short k,l;
        k = (i == *npts) ?  0 : i*npars;
        switch (pass)  
        {   case 0: { dist = pts[k+Z]+pts[k+X]; break; }  /* left side  */ 
            case 1: { dist = pts[k+Z]-pts[k+X]; break; }  /* right side */
            case 2: { dist = pts[k+Z]+pts[k+Y]; break; }  /* bottom  */
            case 3: { dist = pts[k+Z]-pts[k+Y]; break; }  /* top  */
        }
        if (i == 0) {  last_dist = dist;  lk = k;  continue;  } /* 1st pnt? */ 

        if (last_dist * dist < 0.0)  /* put out point if clip plane crossed */
        {   float t,t1;
            t = dist / (dist - last_dist);  t1 = 1.0 - t;
            for (l=0; l<npars; l++)  pt2[m+l] = pts[k+l] * t1 + pts[lk+l] * t;  
            m += npars;
        } 
        if (dist >= 0.0)                            /* copy point if inside */
        {   for (l=0; l<npars; l++)  pt2[m+l] = pts[k+l];  
            m += npars;
        } 
        lk = k;    last_dist = dist;
    }                                              /* recurse for next plane */
    *npts = m/npars;   polclp(++pass,npts,pt2,pts,npars);
} 





!Funky!Stuff!