home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / graphic / qrt / ray.c < prev    next >
C/C++ Source or Header  |  1989-03-26  |  20KB  |  760 lines

  1. /************************************************************
  2.  
  3.                      ray trace module
  4.  
  5.  ************************************************************/
  6.  
  7. #include <math.h>
  8. #include "qrt.h"
  9.  
  10. /* #define RAYDEBUG 1 */
  11.  
  12. OBJ_PTR new_line();
  13.  
  14.  
  15. /**********************************************************
  16.  
  17.   Diffuse color module. Also compute specular reflections
  18.   here for efficiency sake - only one lamp eneumerator
  19.   needed that way.
  20.  
  21.   - Changed 12 Mar 89 to fix bug where sreflect instead of
  22.     reflect was being tested.  This caused the ray tracer
  23.     to go much slower than needed!!
  24.  
  25.  **********************************************************/
  26.  
  27. DiffColor(color,cinfo,norm,loc,oline)
  28.   SVECT_PTR color;
  29.   VECT_PTR norm,loc;
  30.   CINFO_PTR cinfo;
  31.   OBJ_PTR oline;
  32. {
  33.   OBJ_PTR lamp, line, CurrObj, Ray_Hit();
  34.   float t;
  35.   register float dist, t1,t2;
  36.   VECTOR refl, atten;
  37.  
  38.   line=new_line();
  39.   VectEQ(&(line->loc),loc);
  40.   lamp=THEWORLD.lamps;
  41.  
  42.   while (lamp!=NULL) {
  43.  
  44. #   ifdef ROBUST
  45.       if (lamp->type!=LAMP) Error(INTERNAL_ERROR,601);
  46. #   endif
  47.  
  48.     /* find dir to lamp */
  49.     VecSubtract(&(line->vect1),&(lamp->loc),loc);
  50.  
  51.     CurrObj=NULL;
  52.     atten.x = atten.y = atten.z = 1.00;
  53.  
  54.     if (def.shadow==TRUE) {
  55.  
  56.       /* set light attenuation factor */
  57.  
  58.       CurrObj=Ray_Hit(THEWORLD.stack,line,&t,TRUE,TRUE,&atten);
  59.  
  60.       THEWORLD.to_lamp++;
  61.     }
  62.  
  63.     if (CurrObj==NULL) {                         /* hit nothing ? */
  64.  
  65.       dist = DotProd((line->vect1),(line->vect1));
  66.       Normalize(&(line->vect1));
  67.  
  68.       if (cinfo->diff.r>0 || cinfo->diff.g>0 || cinfo->diff.b>0) {
  69.         t1 = DotProd((*norm),(line->vect1));
  70.  
  71.         if (t1>0) {
  72.           t2 = lamp->vect1.y*t1/sqrt(dist);
  73.  
  74.           color->r+=(short)((lamp->cinfo.amb.r) * atten.x *
  75.                     t2*(cinfo->diff.r)/CNUM);
  76.           color->g+=(short)((lamp->cinfo.amb.g) * atten.y *
  77.                     t2*(cinfo->diff.g)/CNUM);
  78.           color->b+=(short)((lamp->cinfo.amb.b) * atten.z *
  79.                     t2*(cinfo->diff.b)/CNUM);
  80.         }
  81.       }
  82.  
  83.       if (cinfo->reflect>0) {                  /* specular */
  84.         line->vect1.x = -line->vect1.x;        /* reverse line */
  85.         line->vect1.y = -line->vect1.y;
  86.         line->vect1.z = -line->vect1.z;
  87.         Reflect(&refl,&(line->vect1),norm);
  88.         t1 = -DotProd(refl,(oline->vect1));
  89.         if (t1>SMALL) {
  90.  
  91.           t2 = pow(t1,cinfo->sreflect)*        /* this is slow !! */
  92.                lamp->vect1.y/sqrt(dist);
  93.  
  94.           t2 *= (float)cinfo->reflect/(float)CNUM;
  95.  
  96.           color->r+=(short)(t2 * atten.x * (lamp->cinfo.amb.r));
  97.           color->g+=(short)(t2 * atten.y * (lamp->cinfo.amb.g));
  98.           color->b+=(short)(t2 * atten.z * (lamp->cinfo.amb.b));
  99.         }
  100.       }
  101.     }
  102.     lamp=lamp->nextobj;
  103.   }
  104.  
  105. # ifdef RAYDEBUG
  106.     printf("DIFFCOLOR: r=%d, g=%d, b=%d\n",
  107.             color->r, color->g, color->b);
  108. # endif
  109.  
  110.   free(line);
  111. }
  112.  
  113.  
  114. /**********************************************************
  115.  
  116.                      Ambient color module
  117.  
  118.    Really simple - just add the color, no questions asked.
  119.  
  120.  **********************************************************/
  121.  
  122. AmbColor(color, cinfo, norm, loc)
  123.   SVECT_PTR color;
  124.   VECT_PTR norm, loc;
  125.   CINFO_PTR cinfo;
  126. {
  127.   color->r+=(short)((int)cinfo->amb.r*(int)cinfo->diff.r/CNUM);
  128.   color->g+=(short)((int)cinfo->amb.g*(int)cinfo->diff.g/CNUM);
  129.   color->b+=(short)((int)cinfo->amb.b*(int)cinfo->diff.b/CNUM);
  130.  
  131. # ifdef RAYDEBUG
  132.     printf("AMBCOLOR: added r=%d, g=%d, b=%d\n",
  133.             cinfo->amb.r,cinfo->amb.g,cinfo->amb.b);
  134. # endif
  135. }
  136.  
  137.  
  138. /**********************************************************
  139.  
  140.                  Transmitted color module
  141.  
  142.  This is hairy and slow - bends ray around normal vector
  143.  by ratio of indicies of refraction.  line->flag=TRUE
  144.  if we are inside a piece of glass - this means glass must
  145.  have a simple structure.
  146.  
  147.  10 Aug 88 - Fixed TransColor so that it works.  The
  148.  original algorithm came from a book, and I had some
  149.  problems getting it to work.  This one came from my head,
  150.  and seems to work ok.
  151.  
  152.  11 Aug 88 - Added density effects (light is reduced
  153.  more by thicker glass).
  154.  
  155.  **********************************************************/
  156.  
  157. /* #define TESTTRANS TRUE */
  158.  
  159. TransColor(color,cinfo,norm,loc,line,inmult)
  160.   SVECT_PTR color;
  161.   VECT_PTR norm,loc;
  162.   OBJ_PTR line;
  163.   CINFO_PTR cinfo;
  164.   float inmult;
  165. {
  166.   OBJ_STRUCT newline;
  167.   SVECTOR    col1;
  168.   VECTOR     toadd, negvect1, distance;
  169.   float      index2, multiplier, side1;
  170.   int        maxtrans;
  171.  
  172.   /* these vars are used to keep track of the distance
  173.      traveled through the glass so we can attenuate the
  174.      light accordingly.                                 */
  175.  
  176.   static     VECTOR prevpos;
  177.   VECTOR     displacement;
  178.   SVECTOR    attenuation;
  179.   float      glassdist;
  180.  
  181. # ifdef TRANSDEBUG
  182.     printf("TRANSCOLOR:\n");
  183. # endif
  184. # ifdef RAYDEBUG
  185.     printf("TRANSCOLOR:\n");
  186. # endif
  187.  
  188.   if ((cinfo->trans.r < def.ithreshold) &&
  189.       (cinfo->trans.g < def.ithreshold) &&
  190.       (cinfo->trans.b < def.ithreshold)) return;
  191.  
  192. # ifdef ROBUST
  193.     if (line->type!=LINE) Error(INTERNAL_ERROR,602);
  194.     if ((THEWORLD.globindex == 0) ||
  195.         (cinfo->index == 0))
  196.           Error(ZERO_INDEX,603);
  197. # endif
  198.  
  199.   if (line->flag) {
  200.  
  201.     /* inside an object going out ? */
  202.     index2 = cinfo->index/THEWORLD.globindex;
  203.  
  204.     /* find offset from prev position */
  205.     VecSubtract(&displacement,loc,&prevpos);
  206.  
  207.     /* measure distance */
  208.     glassdist = sqrt(DotProd(displacement,displacement));
  209.  
  210.   } else {
  211.  
  212.     /* outside an object going in ? */
  213.     index2 = THEWORLD.globindex/cinfo->index;
  214.     /* remember this position */
  215.     VectEQ(&prevpos,loc);
  216.   }
  217.  
  218.   /* doesn't currently use new_line() call */
  219.   newline.type = LINE;
  220.   newline.child = newline.nextobj = NULL;
  221.  
  222.   /* this ray starts from where we hit glass */
  223.   VectEQ(&(newline.loc),loc);
  224.   VectEqZero(&toadd);
  225.  
  226.   VectNegate(&negvect1,&(line->vect1));
  227.   side1 = DotProd((*norm),negvect1);
  228.  
  229.   VectAddMult(&toadd,-side1,norm,(float)1,&negvect1);
  230.  
  231.   VectScale(&toadd,((float)1.0-index2));
  232.  
  233.   VectorAdd(&(newline.vect1),&(line->vect1),&toadd);
  234.  
  235.   Normalize(&(newline.vect1));
  236.  
  237.   maxtrans = MAX(MAX(cinfo->trans.r,cinfo->trans.g),
  238.                      cinfo->trans.b);
  239.  
  240.   /* if we were inside, now we're out */
  241.   newline.flag = !(line->flag);
  242.  
  243. # ifdef TESTTRANS
  244.  
  245.     if (line->flag) printf("line TRUE\n");
  246.     if (newline.flag) printf("newline TRUE\n");
  247.  
  248.     printf("Trans = %d %d %d\n",cinfo->trans.r,
  249.                                 cinfo->trans.g,
  250.                                 cinfo->trans.b);
  251.  
  252.     printf("index2 = %f\n",index2);
  253.     printf("side1  = %f\n",side1);
  254.  
  255.     printf("Dot(toadd,norm) = %f\n",
  256.            DotProd(toadd,(*norm)));
  257.  
  258.     printf("Dot(norm,negvect1) = %f\n",
  259.            DotProd((*norm),negvect1));
  260.  
  261.     printf("Dot(-norm,newvect) = %f\n",
  262.            -DotProd((*norm),newline.vect1));
  263.  
  264.     printf("inmult, maxtrans = %f %d\n",inmult,maxtrans);
  265. # endif
  266.  
  267.   multiplier = inmult * (float)maxtrans/(float)CNUM;
  268.   Ray_Trace(&newline,&col1,multiplier);
  269.   THEWORLD.refl_trans++;
  270.  
  271. # ifdef TESTTRANS
  272.     printf("Col1 = %d %d %d\n",col1.r,col1.g,col1.b);
  273. # endif
  274.  
  275.   color->r += col1.r;
  276.  
  277.   color->g += col1.g;
  278.  
  279.   color->b += col1.b;
  280.  
  281.   if (line->flag) {          /* density effects? */
  282.  
  283.     /* density uses x,y,z not r,g,b cuz its a floating
  284.        point vector.                                   */
  285.  
  286.     attenuation.r = (int)(cinfo->density.x * glassdist *
  287.                          (float)(color->r));
  288.  
  289.     attenuation.g = (int)(cinfo->density.y * glassdist *
  290.                          (float)(color->g));
  291.  
  292.     attenuation.b = (int)(cinfo->density.z * glassdist *
  293.                          (float)(color->b));
  294.  
  295.     /* don't remove more than original intensity! */
  296.  
  297.     color->r -= MIN(attenuation.r,color->r);
  298.     color->g -= MIN(attenuation.g,color->g);
  299.     color->b -= MIN(attenuation.b,color->b);
  300.  
  301.   }
  302. }
  303.  
  304.  
  305. /**********************************************************
  306.  
  307.                    Reflective color module
  308.  
  309.       Bounce ray off object and recursively ray trace.
  310.  
  311.  **********************************************************/
  312.  
  313. ReflectColor(color,cinfo,norm,loc,line,inmult)
  314.   SVECT_PTR color;
  315.   VECT_PTR  norm,loc;
  316.   OBJ_PTR   line;
  317.   CINFO_PTR cinfo;
  318.   float inmult;
  319. {
  320.   SVECTOR col1;
  321.   OBJ_STRUCT newline;
  322.   float multiplier;
  323.   int maxmirror;
  324.  
  325. # ifdef ROBUST
  326.     if (line->type!=LINE) Error(INTERNAL_ERROR,604);
  327. # endif
  328.  
  329.   if ((cinfo->mirror.r < def.ithreshold) &&
  330.       (cinfo->mirror.g < def.ithreshold) &&
  331.       (cinfo->mirror.b < def.ithreshold)) return;
  332.  
  333.   newline.type = LINE;
  334.  
  335.   newline.child = newline.nextobj = NULL;
  336.  
  337.   VectEQ(&(newline.loc),loc);
  338.   Reflect(&(newline.vect1),&(line->vect1),norm);
  339.  
  340.   maxmirror = MAX(MAX(cinfo->mirror.r,cinfo->mirror.g),
  341.               cinfo->mirror.b);
  342.  
  343.   multiplier = inmult * (float)maxmirror/CNUM;
  344.  
  345.   Ray_Trace(&newline,&col1,multiplier);
  346.   THEWORLD.refl_trans++;
  347.  
  348.   color->r+=(int)col1.r*(int)cinfo->mirror.r/CNUM;
  349.  
  350.   color->g+=(int)col1.g*(int)cinfo->mirror.g/CNUM;
  351.  
  352.   color->b+=(int)col1.b*(int)cinfo->mirror.b/CNUM;
  353.  
  354. # ifdef RAYDEBUG
  355.     printf("REFLECTCOLOR:\n");
  356.     printf("  col1 = %d %d %d\n",col1.r,col1.g,col1.b);
  357. # endif
  358.  
  359. }
  360.  
  361.  
  362. /**********************************************************
  363.  
  364.    Computes sky color given line - interpolate between
  365.    horizon and zenith to find color (user should dither
  366.    the explitive out of the sky to compensate for lack
  367.    of color resolution.
  368.  
  369.  **********************************************************/
  370.  
  371. SkyColor(line,color)
  372.   OBJ_PTR line;
  373.   SVECT_PTR color;
  374. {
  375.   float length, horiz, zenith;
  376.  
  377. # ifdef ROBUST
  378.     if (line->type!=LINE) Error(INTERNAL_ERROR,605);
  379. # endif
  380.  
  381.   if (THEWORLD.sky==NULL) return;
  382.  
  383. # ifdef ROBUST
  384.     if (THEWORLD.sky->type != SKY)
  385.       Error(INTERNAL_ERROR,606);
  386. # endif
  387.  
  388.   length = DotProd(line->vect1,line->vect1);
  389.  
  390.   zenith = sqr(line->vect1.y)/length;
  391.   horiz  = (sqr(line->vect1.x)+sqr(line->vect1.z))/length;
  392.  
  393.   color->r += (short)(zenith*THEWORLD.skycolor_zenith.r+
  394.                       horiz *THEWORLD.skycolor_horiz.r);
  395.  
  396.   color->g += (short)(zenith*THEWORLD.skycolor_zenith.g+
  397.                       horiz *THEWORLD.skycolor_horiz.g);
  398.  
  399.   color->b += (short)(zenith*THEWORLD.skycolor_zenith.b+
  400.                       horiz *THEWORLD.skycolor_horiz.b);
  401.  
  402.   Dither(color,&((THEWORLD.sky)->cinfo));
  403.  
  404.  
  405. # ifdef RAYDEBUG
  406.     printf("SKYCOLOR:\n");
  407. # endif
  408.  
  409. }
  410.  
  411.  
  412. /**********************************************************
  413.  
  414.   Color dithering rountine - negative dither number will
  415.   dither all three colors together - positive with perform
  416.   separate color dithering on all colors.
  417.  
  418.  **********************************************************/
  419.  
  420. #define MINCOL 10
  421. Dither(color,cinfo)
  422.   SVECT_PTR color;
  423.   CINFO_PTR cinfo;
  424. {
  425.   register int r,g,b;
  426.   int PsRand();
  427.  
  428.   if (cinfo->dither==0) return;
  429.  
  430.   if (cinfo->dither>0) {
  431.     r=PsRand(); g=PsRand(); b=PsRand();
  432.  
  433.     if (color->r<MINCOL) r=IABS(r);
  434.     if (color->g<MINCOL) g=IABS(g);
  435.     if (color->b<MINCOL) b=IABS(b);
  436.  
  437.     color->r += (short)(r*cinfo->dither/CNUM);
  438.     color->g += (short)(g*cinfo->dither/CNUM);
  439.     color->b += (short)(b*cinfo->dither/CNUM);
  440.   } else {
  441.     r=PsRand();
  442.     if ((color->r+color->g+color->b)>(3*MINCOL)) r=IABS(r);
  443.  
  444.     color->r += (short)(r*cinfo->dither/CNUM);
  445.     color->g += (short)(r*cinfo->dither/CNUM);
  446.     color->b += (short)(r*cinfo->dither/CNUM);
  447.   }
  448. }
  449.  
  450.  
  451. /**********************************************************
  452.  
  453.    Returns pointer to object hit by ray.
  454.    Parameters:
  455.      CurrObj = root of object tree
  456.      line    = light ray
  457.      MinT    = parameter T for line/obj intersection
  458.      sflag   = if TRUE, stop on first intersection
  459.      fflag   = ALWAYS pass TRUE here.
  460.      pos1    = position vector for object relative coords
  461.      pos2    = position vector for object relative coords
  462.  
  463.   - changed 11 jun 88 to fix shadow routine -
  464.  
  465.   - changed 12 aug 88 to add light attenuation by glass.
  466.             this is not done correctly, but is better
  467.             than nothing.
  468.  
  469.  **********************************************************/
  470.  
  471. OBJ_PTR Ray_Hit(CurrObj,line,MinT,sflag,fflag,atten)
  472.   OBJ_PTR line, CurrObj;
  473.   float *MinT;
  474.   short sflag,fflag;
  475.   VECT_PTR atten;           /* light attenuation by glass */
  476. {
  477.   static OBJ_PTR MinObj;
  478.   VECTOR loc;
  479.   OBJ_PTR obj;
  480.   short collision;
  481.   static short stop;
  482.   float t;
  483.  
  484.   obj = CurrObj;
  485.  
  486.   if (fflag) {
  487.  
  488. #   ifdef ROBUST
  489.       if (line->type!=LINE) Error(INTERNAL_ERROR,607);
  490. #   endif
  491.  
  492.     *MinT=BIG;
  493.     MinObj=NULL;
  494.     stop=FALSE;
  495.   }
  496.  
  497.   while (obj!=NULL && !stop) {         /* check for object collisions */
  498.  
  499.     collision =
  500.       (*(ObjData[obj->type].ColTest))(line,obj,&t);
  501.  
  502.     if (collision && (obj->remove != NULL)) {
  503.       FindPos(&loc,line,t);
  504.       if (Find_Color(obj,obj->remove,&loc,NULL, 1.0, 1.0))
  505.         collision = FALSE;
  506.     }
  507.  
  508.     THEWORLD.intersect_tests++;
  509.  
  510.     if (collision && (t>SMALL)) {      /* did we hit something ? */
  511.  
  512. #     ifdef RAYDEBUG
  513.         printf("RAY_HIT: Collision t=%f\n",t);
  514. #     endif
  515.  
  516.       if (obj->type!=BBOX) {           /* if not BBOX */
  517.         THEWORLD.ray_intersects++;
  518.         if (sflag && t<1) {
  519.  
  520.           /* did we hit a transparent object? */
  521.           /* PS - this is not right - fix it later */
  522.  
  523.           if ((obj->cinfo.trans.r < def.ithreshold) &&
  524.               (obj->cinfo.trans.g < def.ithreshold) &&
  525.               (obj->cinfo.trans.b < def.ithreshold)) {
  526.  
  527.             stop   = TRUE;
  528.             MinObj = obj;
  529.             return(obj);
  530.  
  531.           } else {
  532.  
  533.             /* attenuate light if transparent object.  This is
  534.                REALLY screwy and not at all correct, but it is
  535.                the only simple way to do it.
  536.             */
  537.  
  538.             if (atten != NULL) {
  539.               atten->x *= sqr(((float)obj->cinfo.trans.r) /
  540.                           (float)CNUM);
  541.               atten->y *= sqr(((float)obj->cinfo.trans.g) /
  542.                           (float)CNUM);
  543.               atten->z *= sqr(((float)obj->cinfo.trans.b) /
  544.                           (float)CNUM);
  545.             }
  546.           }
  547.         }
  548.         if ((!sflag) && (t<*MinT)) {   /* nearest collision ? */
  549.           *MinT  = t;                  /* if so, save it */
  550.           MinObj = obj;
  551.         }
  552.       } else {                         /* is bbox hit */
  553.         THEWORLD.bbox_intersects++;
  554.         Ray_Hit(obj->child,line,MinT,sflag,FALSE,atten);
  555.       }
  556.     }
  557.     obj=obj->nextobj;
  558.   }
  559.  
  560.   return(MinObj);
  561. }
  562.  
  563.  
  564. /**********************************************************
  565.  
  566.   Performs ray tracing in line, fills color structure.
  567.   Multiplier is a number by which the color output will
  568.   be mulplied (0..1) so that we can tell when its useless
  569.   to continue recursivly tracing rays.
  570.  
  571.  **********************************************************/
  572.  
  573. int Ray_Trace(line,color,multiplier)
  574.   OBJ_PTR line;
  575.   SVECT_PTR color;
  576.   float multiplier;
  577. {
  578.   float MinT, divisor;
  579.   OBJ_PTR MinObj;
  580.   CINFO cinfo;
  581.   VECTOR MinLoc, MinNorm;
  582.  
  583. # ifdef ROBUST
  584.     if (line->type!=LINE) Error(INTERNAL_ERROR,608);
  585. # endif
  586.  
  587.   color->r = color->g = color->b = 0;
  588.  
  589.   /* check here if so little light is added that it doesn't matter */
  590.   if (multiplier < def.threshold) return(FALSE);
  591.  
  592.   MinObj=Ray_Hit(THEWORLD.stack,line,&MinT,FALSE,TRUE,NULL);
  593.  
  594.   if (MinObj!=NULL) {
  595.     FindPos(&MinLoc,line,MinT);
  596.  
  597. #   ifdef RAYDEBUG
  598.       printf("RAY_TRACE: Collision, x,y,z = %f %f %f\n",
  599.              MinLoc.x, MinLoc.y, MinLoc.z);
  600. #   endif
  601.  
  602.     /*  Find object normal vector */
  603.  
  604.     (*(ObjData[MinObj->type].FindNorm))(&MinNorm,MinObj,&MinLoc);
  605.  
  606.     if (DotProd(MinNorm,(line->vect1)) >0) {   /* reverse   */
  607.       MinNorm.x = -MinNorm.x;                  /* normal if */
  608.       MinNorm.y = -MinNorm.y;                  /* necessary */
  609.       MinNorm.z = -MinNorm.z;
  610.     }
  611.                                                /* Find colinfo */
  612.     Find_Color(MinObj,
  613.                MinObj->pattern,
  614.                &MinLoc,
  615.                &cinfo,
  616.                MinObj->xmult,
  617.                MinObj->ymult
  618.               );
  619.  
  620.     AmbColor(color,&cinfo,&MinNorm,&MinLoc);
  621.     DiffColor(color,&cinfo,&MinNorm,&MinLoc,line);
  622.     TransColor(color,&cinfo,&MinNorm,&MinLoc,line,multiplier);
  623.     ReflectColor(color,&cinfo,&MinNorm,&MinLoc,line,multiplier);
  624.     Dither(color,&cinfo);
  625.  
  626.   } else {
  627.     SkyColor(line,color);
  628.   }
  629.  
  630.   if (color->r > CNUM || color->g > CNUM || color->b > CNUM) {
  631.     divisor = (float)MAX(MAX(color->r,color->g),color->b) /
  632.               (float)CNUM;
  633.  
  634.     color->r = (float)color->r/divisor;
  635.     color->g = (float)color->g/divisor;
  636.     color->b = (float)color->b/divisor;
  637.   }
  638.  
  639.   return(MinObj!=NULL);
  640. }
  641.  
  642.  
  643. /**********************************************************
  644.  
  645.      Generates line for a given x,y pixel position
  646.      This fn needs a little work, as currently it
  647.      produces some distortion around the edge of
  648.      the screen.
  649.  
  650.  **********************************************************/
  651.  
  652. PixelLine(x, y, line)           /* generate equation for a line */
  653.   int x,y;
  654.   OBJ_PTR line;
  655. {
  656.   register float xf, yf;
  657.  
  658. # ifdef ROBUST
  659.     if (line->type!=LINE) Error(INTERNAL_ERROR,609);
  660. # endif
  661.  
  662.   xf=((float)(def.x_center-x))/(THEWORLD.x_divisor);
  663.   yf=((float)(def.y_center-y))/(THEWORLD.y_divisor);
  664.  
  665.   VectEQ(&(line->loc),&(THEWORLD.observer->loc));
  666.   VectEQ(&(line->vect1),&(THEWORLD.observer->vect1));
  667.   VectAddMult(&(line->vect1),xf,&(THEWORLD.obsright),
  668.                              yf,&(THEWORLD.obsup));
  669.  
  670.   line->flag = FALSE;           /* redundant? */
  671. }
  672.  
  673.  
  674. /**********************************************************
  675.  
  676.    Sends scan line color data to file - file format is:
  677.  
  678.    BYTE 0 : low  byte of x resolution
  679.    BYTE 1 : high byte of x resolution
  680.    BYTE 2 : low  byte of y resolution
  681.    BYTE 3 : high byte of y resolution
  682.  
  683.    Then, for each scan line, the line number is listed
  684.    (2 bytes), followed by the r,g, and b bytes.
  685.  
  686.  **********************************************************/
  687.  
  688. Dump_Line(lineno,r,g,b)
  689.   short r[],g[],b[];
  690.   int lineno;
  691. {
  692.   int x;
  693.  
  694. #ifndef RAYDEBUG
  695.  
  696.   /** line number **/
  697.  
  698.   fputc(((unsigned char)(lineno&(0xff))),THEWORLD.filept);
  699.   fputc(((unsigned char)(lineno>>8)),    THEWORLD.filept);
  700.  
  701.   for (x=0; x<def.x_res; x++) {
  702.     fputc((unsigned char)r[x],THEWORLD.filept);
  703.   }
  704.   for (x=0; x<def.x_res; x++) {
  705.     fputc((unsigned char)g[x],THEWORLD.filept);
  706.   }
  707.   for (x=0; x<def.x_res; x++) {
  708.     fputc((unsigned char)b[x],THEWORLD.filept);
  709.   }
  710. #endif
  711. }
  712.  
  713.  
  714. /**********************************************************
  715.  
  716.                   Ray trace whole screen
  717.  
  718.  **********************************************************/
  719.  
  720. Screen_Trace() {
  721.   int x,y;
  722.   short rbyte[MAX_XRES], gbyte[MAX_XRES], bbyte[MAX_XRES];
  723.   SVECTOR color;
  724.   OBJ_PTR line;
  725.  
  726.   line=new_line();
  727.  
  728. # ifdef RAYDEBUG
  729.     printf("SCREEN_TRACE: line:\n");
  730. # endif
  731.  
  732.   for (y=0; y<def.y_res; y++) {
  733.  
  734.     for (x=0; x<def.x_res; x++) {
  735.  
  736.       PixelLine(x,y,line);
  737.  
  738.       Ray_Trace(line,&color,(float)1.0);
  739.       THEWORLD.primary_traced++;
  740.  
  741. #     ifdef RAYDEBUG
  742.         printf("SCREEN_TRACE: r,g,b = %d %d %d\n",
  743.                color.r,color.g,color.b);
  744. #     endif
  745.  
  746.       rbyte[x] = color.r;
  747.       gbyte[x] = color.g;
  748.       bbyte[x] = color.b;
  749.  
  750. #     ifdef RAYDEBUG
  751.         printf("SCREEN_TRACE: r=%d, g=%d, b=%d\n",
  752.                color.r,color.g,color.b);
  753. #     endif
  754.     }
  755.  
  756.     Dump_Line(y,rbyte,gbyte,bbyte);
  757.   }
  758.   free(line);
  759. }
  760.