home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / simplerd.lha / simplerad / FinalFTP / Light / raybox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-21  |  4.9 KB  |  156 lines

  1. /**********************************************************************/
  2. /* raybox.c                                                           */
  3. /*                                                                    */
  4. /* Ray / box intersection routines                                    */
  5. /*                                                                    */
  6. /* Copyright (C) 1992, Bernard Kwok                                   */
  7. /* All rights reserved.                                               */
  8. /* Revision 1.0                                                       */
  9. /* May, 1992                                                          */
  10. /**********************************************************************/
  11. /* Finished */
  12. #include <stdio.h>
  13. #include "geo.h"
  14. #include "misc.h"
  15. #include "struct.h"
  16. #include "io.h"
  17. #include "ray.h"
  18. #include "bvol.h"
  19.  
  20. /**********************************************************************/
  21. extern OptionType Option;
  22. extern RayStats_Type RayStats;
  23.  
  24. #define RIGHT    0
  25. #define LEFT    1
  26. #define MIDDLE    2
  27. #define NUMDIM 3
  28.  
  29. /**********************************************************************/
  30. /* Ray-Box Intersection by Andrew Woo from "Graphics Gems", Academic  */
  31. /* Press, 1990                                                        */
  32. /* Returns true if intersects, and intersect distance.                */
  33. /**********************************************************************/
  34. int RayBoundingBox(box, ray, d)
  35.      BoundingBoxType box;      
  36.      Ray ray;
  37.      double *d;
  38. {
  39.   double minB[NUMDIM], maxB[NUMDIM];        /* box */
  40.   double coord[NUMDIM];                /* hit point */
  41.   double ray_orig[NUMDIM], ray_dir[NUMDIM]; /* ray */
  42.   char inside = TRUE;
  43.   char quadrant[NUMDIM];
  44.   register int i;
  45.   int whichPlane;
  46.   double maxT[NUMDIM];
  47.   double candidatePlane[NUMDIM];
  48.   Vector *t;
  49.  
  50.   /* Do some setup */
  51.   minB[0] = box.min.x;  minB[1] = box.min.y;  minB[2] = box.min.z;
  52.   maxB[0] = box.max.x;  maxB[1] = box.max.y;  maxB[2] = box.max.z;
  53.   ray_orig[0] = ray.origin.x;  
  54.   ray_orig[1] = ray.origin.y;  
  55.   ray_orig[2] = ray.origin.z;
  56.   ray_dir[0] = ray.dir.x;   
  57.   ray_dir[1] = ray.dir.y;
  58.   ray_dir[2] = ray.dir.z; *d = 0.0;
  59.  
  60.   /* Find candidate planes; this loop can be avoided if
  61.      rays cast all from the eye (assume perpsective view) */
  62.   for (i=0; i<3; i++)
  63.     if (ray_orig[i] < minB[i]) {
  64.       quadrant[i] = LEFT;
  65.       candidatePlane[i] = minB[i];
  66.       inside = FALSE;
  67.     } else if (ray_orig[i] > maxB[i]) {
  68.       quadrant[i] = RIGHT;
  69.       candidatePlane[i] = maxB[i];
  70.       inside = FALSE;
  71.     } else    {
  72.       quadrant[i] = MIDDLE;
  73.     }
  74.   
  75.   /* Ray is inside bounding box */
  76.   if (inside) {
  77.     /* *t = ray.origin; */
  78.     return (TRUE);
  79.   }
  80.   
  81.   /* Calculate the distances to candidate planes */
  82.   for (i=0; i<NUMDIM; i++)
  83.     if (quadrant[i] != MIDDLE && ray_dir[i] !=0.0)
  84.       maxT[i] = (candidatePlane[i]-ray_orig[i]) / ray_dir[i];
  85.     else
  86.       maxT[i] = -1.;
  87.   
  88.   /* Get largest of the maxT's for final choice of intersection */
  89.   whichPlane = 0;
  90.   for (i = 1; i < NUMDIM; i++)
  91.     if (maxT[whichPlane] < maxT[i])
  92.       whichPlane = i;
  93.   
  94.   /* Check if final candidate actually inside box */
  95.   if (maxT[whichPlane] < 0.0) 
  96.     return (FALSE);
  97.   for (i = 0; i < NUMDIM; i++)
  98.     if (whichPlane != i) {
  99.       coord[i] = ray_orig[i] + maxT[whichPlane] * ray_dir[i];
  100.       if ((quadrant[i] == RIGHT && coord[i] < minB[i]) ||
  101.       (quadrant[i] == LEFT && coord[i] > maxB[i]))
  102.     return (FALSE);    /* outside box */
  103.     } else {
  104.       coord[i] = candidatePlane[i];
  105.     }
  106.  
  107.   /* t->x = coord[0]; t->y = coord[1]; t->z = coord[2]; */
  108.   *d = maxT[whichPlane];
  109.   return (TRUE);                /* ray hits box */
  110. }
  111.  
  112. /**********************************************************************/
  113. /* Axis-aligned bounding box intersection normal */
  114. /**********************************************************************/
  115. int BoxNormal(box, pos, nrm, gnrm)
  116.      Vector *pos, *nrm;    /* point of intersection, and normal to return */
  117.      BoundingBoxType *box;
  118. {
  119.   nrm->x = nrm->y = nrm->z = 0.;
  120.   
  121.   if (equal(pos->x,box->max.x))
  122.     nrm->x = 1.0;
  123.   else if (equal(pos->x,box->min.x))
  124.     nrm->x = -1.0;
  125.   else if (equal(pos->y,box->max.y))
  126.     nrm->y = 1.0;
  127.   else if (equal(pos->y,box->min.y))
  128.     nrm->y = -1.0;
  129.   else if (equal(pos->z,box->max.z))
  130.     nrm->z = 1.0;
  131.   else if (equal(pos->z,box->min.z))
  132.     nrm->z = -1.0;
  133.   else {
  134.     fprintf(stderr, "Can't get normal of bounding box intersection\n");
  135.     return 0;
  136.   }
  137.   return(1);
  138. }
  139.  
  140. /**********************************************************************/
  141. /* Determine if ray enters (TRUE) or leaves (0) box at pos */
  142. /**********************************************************************/
  143. int BoxEnter(box, ray, mind, hitd)
  144.      BoundingBoxType *box;
  145.      Ray *ray;
  146.      double mind, hitd;
  147. {
  148.   Vector pos;
  149.  
  150.   pos.x = ray->origin.x + mind * ray->dir.x;
  151.   pos.y = ray->origin.y + mind * ray->dir.y;
  152.   pos.z = ray->origin.z + mind * ray->dir.z;
  153.   return OutOfBounds(&pos, box);
  154. }
  155.  
  156.