home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / macraysh.sit / Code / Source / bounds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-28  |  5.4 KB  |  247 lines

  1. /*
  2.  * bounds.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: bounds.c,v 4.0 91/07/17 14:36:21 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    bounds.c,v $
  19.  * Revision 4.0  91/07/17  14:36:21  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "geom.h"
  24.  
  25. /*
  26.  * Check for intersection between bounding box and the given ray.
  27.  * If there is an intersection between mindist and *maxdist along
  28.  * the ray, *maxdist is replaced with the distance to the point of
  29.  * intersection, and TRUE is returned.  Otherwise, FALSE is returned.
  30.  *
  31.  * If this routine is used to check for intersection with a volume
  32.  * rather than a "hollow" box, one should first determine if
  33.  * (ray->pos + mindist * ray->dir) is inside the bounding volume, and
  34.  * call BoundsIntersect() only if it is not.
  35.  */
  36. int
  37. BoundsIntersect(ray, bounds, mindist, maxdist)
  38. Ray *ray;
  39. Float bounds[2][3], mindist, *maxdist;
  40. {
  41.     Float t, tmin, tmax;
  42.     Float dir, pos;
  43.  
  44.     tmax = *maxdist;
  45.     tmin = mindist;
  46.  
  47.     dir = ray->dir.x;
  48.     pos = ray->pos.x;
  49.  
  50.     if (dir < 0) {
  51.         t = (bounds[LOW][X] - pos) / dir;
  52.         if (t < tmin)
  53.             return FALSE;
  54.         if (t <= tmax)
  55.             tmax = t;
  56.         t = (bounds[HIGH][X] - pos) / dir;
  57.         if (t >= tmin) {
  58.             if (t > tmax)
  59.                 return FALSE;
  60.             tmin = t;
  61.         }
  62.     } else if (dir > 0.) {
  63.         t = (bounds[HIGH][X] - pos) / dir;
  64.         if (t < tmin)
  65.             return FALSE;
  66.         if (t <= tmax)
  67.             tmax = t;
  68.         t = (bounds[LOW][X] - pos) / dir;
  69.         if (t >= tmin) {
  70.             if (t > tmax)
  71.                 return FALSE;
  72.             tmin = t;
  73.         }
  74.     } else if (pos < bounds[LOW][X] || pos > bounds[HIGH][X])
  75.         return FALSE;
  76.  
  77.     dir = ray->dir.y;
  78.     pos = ray->pos.y;
  79.  
  80.     if (dir < 0) {
  81.         t = (bounds[LOW][Y] - pos) / dir;
  82.         if (t < tmin)
  83.             return FALSE;
  84.         if (t <= tmax)
  85.             tmax = t;
  86.         t = (bounds[HIGH][Y] - pos) / dir;
  87.         if (t >= tmin) {
  88.             if (t > tmax)
  89.                 return FALSE;
  90.             tmin = t;
  91.         }
  92.     } else if (dir > 0.) {
  93.         t = (bounds[HIGH][Y] - pos) / dir;
  94.         if (t < tmin)
  95.             return FALSE;
  96.         if (t <= tmax)
  97.             tmax = t;
  98.         t = (bounds[LOW][Y] - pos) / dir;
  99.         if (t >= tmin) {
  100.             if (t > tmax)
  101.                 return FALSE;
  102.             tmin = t;
  103.         }
  104.     } else if (pos < bounds[LOW][Y] || pos > bounds[HIGH][Y])
  105.         return FALSE;
  106.  
  107.     dir = ray->dir.z;
  108.     pos = ray->pos.z;
  109.  
  110.     if (dir < 0) {
  111.         t = (bounds[LOW][Z] - pos) / dir;
  112.         if (t < tmin)
  113.             return FALSE;
  114.         if (t <= tmax)
  115.             tmax = t;
  116.         t = (bounds[HIGH][Z] - pos) / dir;
  117.         if (t >= tmin) {
  118.             if (t > tmax)
  119.                 return FALSE;
  120.             tmin = t;
  121.         }
  122.     } else if (dir > 0.) {
  123.         t = (bounds[HIGH][Z] - pos) / dir;
  124.         if (t < tmin)
  125.             return FALSE;
  126.         if (t <= tmax)
  127.             tmax = t;
  128.         t = (bounds[LOW][Z] - pos) / dir;
  129.         if (t >= tmin) {
  130.             if (t > tmax)
  131.                 return FALSE;
  132.             tmin = t;
  133.         }
  134.     } else if (pos < bounds[LOW][Z] || pos > bounds[HIGH][Z])
  135.         return FALSE;
  136.  
  137.     if (tmin == mindist) {
  138.         if (tmax < *maxdist) {
  139.             *maxdist = tmax;
  140.             return TRUE;
  141.         }
  142.     } else {
  143.         if (tmin < *maxdist) {
  144.             *maxdist = tmin;
  145.             return TRUE;
  146.         }
  147.     }
  148.     return FALSE;    /* hit, but not closer than maxdist */
  149. }
  150.  
  151. /*
  152.  * Transform an object's bounding box by the given transformation
  153.  * matrix.
  154.  */
  155. void
  156. BoundsTransform(trans, objbounds)
  157. RSMatrix *trans;
  158. Float objbounds[2][3];
  159. {
  160.     Vector tmp;
  161.     Float bounds[2][3];
  162.     int x, y, z;
  163.  
  164.     /*
  165.      * Can't (and shouldn't) do anything with unbounded objects.
  166.      */
  167.     if (objbounds[LOW][X] > objbounds[HIGH][X])
  168.         return;
  169.         
  170.     BoundsInit(bounds);
  171.  
  172.     /*
  173.      * Find bounding box of transformed corners of bounding box.
  174.      */
  175.     for (x = 0 ; x < 2; x++) {
  176.         for (y = 0; y < 2; y++) {
  177.             for (z = 0; z < 2; z++) {
  178.                 tmp.x = objbounds[x][X];
  179.                 tmp.y = objbounds[y][Y];
  180.                 tmp.z = objbounds[z][Z];
  181.                 PointTransform(&tmp, trans);
  182.                 if (tmp.x < bounds[LOW][X])
  183.                     bounds[LOW][X] = tmp.x;
  184.                 if (tmp.x > bounds[HIGH][X])
  185.                     bounds[HIGH][X] = tmp.x;
  186.                 if (tmp.y < bounds[LOW][Y])
  187.                     bounds[LOW][Y] = tmp.y;
  188.                 if (tmp.y > bounds[HIGH][Y])
  189.                     bounds[HIGH][Y] = tmp.y;
  190.                 if (tmp.z < bounds[LOW][Z])
  191.                     bounds[LOW][Z] = tmp.z;
  192.                 if (tmp.z > bounds[HIGH][Z])
  193.                     bounds[HIGH][Z] = tmp.z;
  194.             }
  195.         }
  196.     }
  197.  
  198.     BoundsCopy(bounds, objbounds);
  199. }
  200.  
  201. void
  202. BoundsInit(bounds)
  203. Float bounds[2][3];
  204. {
  205.     bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = FAR_AWAY;
  206.     bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -FAR_AWAY;
  207. }
  208.  
  209. void
  210. BoundsCopy(from, into)
  211. Float into[2][3], from[2][3];
  212. {
  213.     into[LOW][X] = from[LOW][X];
  214.     into[LOW][Y] = from[LOW][Y];
  215.     into[LOW][Z] = from[LOW][Z];
  216.     into[HIGH][X] = from[HIGH][X];
  217.     into[HIGH][Y] = from[HIGH][Y];
  218.     into[HIGH][Z] = from[HIGH][Z];
  219. }
  220.  
  221. #define SetIfLess(a, b)        (a = ((a) < (b) ? (a) : (b)))
  222. #define SetIfGreater(a, b)    (a = ((a) > (b) ? (a) : (b)))
  223.  
  224. /*
  225.  * Find bounding box of the union of two bounding boxes.
  226.  */
  227. void
  228. BoundsEnlarge(old, new)
  229. Float old[2][3], new[2][3];
  230. {
  231.     SetIfLess(old[LOW][X], new[LOW][X]);
  232.     SetIfLess(old[LOW][Y], new[LOW][Y]);
  233.     SetIfLess(old[LOW][Z], new[LOW][Z]);
  234.     SetIfGreater(old[HIGH][X], new[HIGH][X]);
  235.     SetIfGreater(old[HIGH][Y], new[HIGH][Y]);
  236.     SetIfGreater(old[HIGH][Z], new[HIGH][Z]);
  237. }
  238.  
  239. void
  240. BoundsPrint(box)
  241. Float box[2][3];
  242. {
  243.     printf("\tX: %f to %f\n",box[LOW][X], box[HIGH][X]);
  244.     printf("\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]);
  245.     printf("\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]);
  246. }
  247.