home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / mtvraytrace / part02 / intersect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-26  |  4.6 KB  |  197 lines

  1. /***********************************************************************
  2.  * $Author: markv $
  3.  * $Revision: 1.2 $
  4.  * $Date: 88/09/12 12:54:48 $
  5.  * $Log:    intersect.c,v $
  6.  * Revision 1.2  88/09/12  12:54:48  markv
  7.  * Added early cutoffs, as suggested by Haines in the RT-News, and 
  8.  * independantly discovered by myself during our correspondence.
  9.  * Now, Intersect takes a max distance, and will not search for 
  10.  * any intersections beyond the max distance.
  11.  * Also, to enable shadow caching, Shadow now returns the object
  12.  * that it found on its way to the light source.
  13.  * 
  14.  * These optimizations speed up shadow testing considerably, and 
  15.  * normal rays some small amount.
  16.  * 
  17.  * Revision 1.1  88/09/11  11:00:40  markv
  18.  * Initial revision
  19.  * 
  20.  ***********************************************************************/
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <assert.h>
  25. #include "defs.h"
  26. #include "extern.h"
  27.  
  28. /*
  29.  * intersect.c
  30.  * Much nicer now, uses the nifty priority queue search
  31.  * as suggested by Kajiya...
  32.  */
  33.  
  34. Flt        num[NSLABS] ;
  35. Flt        den[NSLABS] ;
  36.  
  37. /***********************************************************************
  38.  * CheckAndEnqueue(obj, maxdist)
  39.  * Check the current ray (as paramaterized with the num and den 
  40.  * arrays above) against the bounding volume of obj.
  41.  * If we intersect the bounding volume, then insert it into the 
  42.  * priority queue.
  43.  *
  44.  * Note: should be broken into two separate procedures...
  45.  ***********************************************************************/
  46.  
  47. INLINE
  48. CheckAndEnqueue(obj, maxdist)
  49.  Object * obj ;
  50.  Flt maxdist ;
  51. {
  52.     int i ;
  53.     Flt tmp ;
  54.     Flt tmin, tmax ;
  55.     Flt dmin = -HUGE ;
  56.     Flt dmax = maxdist ;
  57.  
  58.     nChecked ++ ;
  59.  
  60.     for (i = 0 ; i < NSLABS ; i ++) {
  61.  
  62.         /* enters the slab here...    */
  63.         tmin = (obj -> o_dmin[i] - num[i]) * den[i] ;
  64.         /* and exits here...        */
  65.         tmax = (obj -> o_dmax[i] - num[i]) * den[i] ;
  66.  
  67.         /* but we may have to swap...    */
  68.         if (tmin > tmax) {
  69.             tmp = tmin ; tmin = tmax ; tmax = tmp ;
  70.         }
  71.  
  72.         /* if exited closer than we thought, update     */
  73.         if (tmax < dmax)
  74.             dmax = tmax ;
  75.         /* if entered farther than we thought, update     */
  76.         if (tmin > dmin)
  77.             dmin = tmin ;
  78.  
  79.         if (dmin > dmax || dmax < rayeps)
  80.             return ;
  81.     }
  82.     PriorityQueueInsert(dmin, obj) ;
  83.     nEnqueued ++ ;
  84. }
  85.  
  86. /***********************************************************************
  87.  * Intersect(ray, hit, maxdist)
  88.  * 
  89.  * Returns true if we hit something in the root model closer than maxdist.  
  90.  * Returns the closest hit in the "hit" buffer.
  91.  ***********************************************************************/
  92.  
  93. Intersect(ray, hit, maxdist)
  94.  Ray * ray ;
  95.  Isect * hit ;
  96.  Flt maxdist ;
  97. {
  98.     Isect        nhit ;
  99.     int        i ;
  100.     Flt        min_dist = maxdist ;
  101.     Object *    cobj ;
  102.     Object *     pobj = NULL ;
  103.     CompositeData     * cdp ;
  104.     Flt        key ;
  105.  
  106.     /* If the object is simple, then return the hit that it gives you */
  107.  
  108.     if (Root -> o_type != T_COMPOSITE)
  109.         return (Root -> o_procs -> intersect) (Root, ray, hit) ;
  110.  
  111.     for (i = 0 ; i < NSLABS ; i ++) {
  112.         num[i] = VecDot(ray -> P, Slab[i]) ;
  113.         den[i] = 1.0 / VecDot(ray -> D, Slab[i]) ;
  114.     }
  115.  
  116.     /* start with an empty priority queue */
  117.     PriorityQueueNull() ;
  118.  
  119.     CheckAndEnqueue(Root, maxdist) ;
  120.  
  121.     for (;;) {
  122.  
  123.         if (PriorityQueueEmpty())
  124.             break ;
  125.  
  126.         PriorityQueueDelete(&key, &cobj) ;
  127.  
  128.         if (key > min_dist) {
  129.  
  130.             /*
  131.              * we have already found a primitive
  132.              * that was closer, we need look no further...
  133.              */
  134.              break ;
  135.  
  136.         } else if (cobj -> o_type == T_COMPOSITE) {
  137.             /* 
  138.              * if it is in the queue, it got hit.
  139.              * check each of its children to see if their
  140.              * bounding volumes get hit.
  141.              * if so, then push them into the priority
  142.              * queue...
  143.              */
  144.             
  145.             cdp = (CompositeData *) cobj -> o_data ;
  146.  
  147.             for (i = 0 ; i < cdp -> c_size ; i ++ ) {
  148.                 CheckAndEnqueue(cdp -> c_object[i], maxdist) ;
  149.             }
  150.  
  151.         } else {
  152.  
  153.             /*
  154.              * we have a primitive 
  155.              * intersect with the primitive, and possibly
  156.              * update the nearest hit if it is indeed closer
  157.              * than the one we currently have...
  158.              */
  159.             
  160.             if ((cobj -> o_procs -> intersect) (cobj, ray, &nhit)) {
  161.                 if (nhit.isect_t < min_dist) {
  162.                     pobj = cobj ;
  163.                     *hit = nhit ;
  164.                     min_dist = nhit.isect_t ;
  165.                 }
  166.             }
  167.         }
  168.     }
  169.  
  170.     if (pobj)
  171.         return 1 ;
  172.     else
  173.         return 0 ;
  174. }
  175.  
  176. /***********************************************************************
  177.  * Shadow(ray, hit, tmax)
  178.  * 
  179.  * Returns true if we are unshadowed.  Returns the primitive in 
  180.  * the "hit" buffer.
  181.  *
  182.  * Note: the return value of this procedure is a bit strange, as well 
  183.  * as the name.  Should probably be changed.
  184.  ***********************************************************************/
  185.  
  186. int 
  187. Shadow(ray, hit, tmax) 
  188.  Ray * ray ;
  189.  Isect * hit ;
  190.  Flt tmax ;
  191. {
  192.     if (Intersect(ray, hit, tmax))
  193.         return 0 ;
  194.     else
  195.         return 1 ;
  196. }
  197.