home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / libobj / bounds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  6.1 KB  |  269 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.  * bounds.c,v 4.1 1994/08/09 07:58:05 explorer Exp
  17.  *
  18.  * bounds.c,v
  19.  * Revision 4.1  1994/08/09  07:58:05  explorer
  20.  * Bump version to 4.1
  21.  *
  22.  * Revision 1.1.1.1  1994/08/08  04:52:07  explorer
  23.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  24.  *
  25.  * Revision 4.0.1.2  91/10/05  18:17:29  cek
  26.  * patch1: Faster box transform, a la Jim Arvo.
  27.  * 
  28.  * Revision 4.0.1.1  1991/09/29  15:42:05  cek
  29.  * patch1: Justified floating point compare...
  30.  *
  31.  * Revision 4.0  91/07/17  14:36:21  kolb
  32.  * Initial version.
  33.  * 
  34.  */
  35. #include "geom.h"
  36.  
  37. /*
  38.  * Check for intersection between bounding box and the given ray.
  39.  * If there is an intersection between mindist and *maxdist along
  40.  * the ray, *maxdist is replaced with the distance to the point of
  41.  * intersection, and TRUE is returned.  Otherwise, FALSE is returned.
  42.  *
  43.  * If this routine is used to check for intersection with a volume
  44.  * rather than a "hollow" box, one should first determine if
  45.  * (ray->pos + mindist * ray->dir) is inside the bounding volume, and
  46.  * call BoundsIntersect() only if it is not.
  47.  */
  48. int
  49. BoundsIntersect(ray, bounds, mindist, maxdist)
  50. Ray *ray;
  51. Float bounds[2][3], mindist, *maxdist;
  52. {
  53.     Float t, tmin, tmax;
  54.     Float dir, pos;
  55.  
  56.     tmax = *maxdist;
  57.     tmin = mindist;
  58.  
  59.     dir = ray->dir.x;
  60.     pos = ray->pos.x;
  61.  
  62.     if (dir < 0) {
  63.         t = (bounds[LOW][X] - pos) / dir;
  64.         if (t < tmin)
  65.             return FALSE;
  66.         if (t <= tmax)
  67.             tmax = t;
  68.         t = (bounds[HIGH][X] - pos) / dir;
  69.         if (t >= tmin) {
  70.             if (t > tmax)
  71.                 return FALSE;
  72.             tmin = t;
  73.         }
  74.     } else if (dir > 0.) {
  75.         t = (bounds[HIGH][X] - pos) / dir;
  76.         if (t < tmin)
  77.             return FALSE;
  78.         if (t <= tmax)
  79.             tmax = t;
  80.         t = (bounds[LOW][X] - pos) / dir;
  81.         if (t >= tmin) {
  82.             if (t > tmax)
  83.                 return FALSE;
  84.             tmin = t;
  85.         }
  86.     } else if (pos < bounds[LOW][X] || pos > bounds[HIGH][X])
  87.         return FALSE;
  88.  
  89.     dir = ray->dir.y;
  90.     pos = ray->pos.y;
  91.  
  92.     if (dir < 0) {
  93.         t = (bounds[LOW][Y] - pos) / dir;
  94.         if (t < tmin)
  95.             return FALSE;
  96.         if (t <= tmax)
  97.             tmax = t;
  98.         t = (bounds[HIGH][Y] - pos) / dir;
  99.         if (t >= tmin) {
  100.             if (t > tmax)
  101.                 return FALSE;
  102.             tmin = t;
  103.         }
  104.     } else if (dir > 0.) {
  105.         t = (bounds[HIGH][Y] - pos) / dir;
  106.         if (t < tmin)
  107.             return FALSE;
  108.         if (t <= tmax)
  109.             tmax = t;
  110.         t = (bounds[LOW][Y] - pos) / dir;
  111.         if (t >= tmin) {
  112.             if (t > tmax)
  113.                 return FALSE;
  114.             tmin = t;
  115.         }
  116.     } else if (pos < bounds[LOW][Y] || pos > bounds[HIGH][Y])
  117.         return FALSE;
  118.  
  119.     dir = ray->dir.z;
  120.     pos = ray->pos.z;
  121.  
  122.     if (dir < 0) {
  123.         t = (bounds[LOW][Z] - pos) / dir;
  124.         if (t < tmin)
  125.             return FALSE;
  126.         if (t <= tmax)
  127.             tmax = t;
  128.         t = (bounds[HIGH][Z] - pos) / dir;
  129.         if (t >= tmin) {
  130.             if (t > tmax)
  131.                 return FALSE;
  132.             tmin = t;
  133.         }
  134.     } else if (dir > 0.) {
  135.         t = (bounds[HIGH][Z] - pos) / dir;
  136.         if (t < tmin)
  137.             return FALSE;
  138.         if (t <= tmax)
  139.             tmax = t;
  140.         t = (bounds[LOW][Z] - pos) / dir;
  141.         if (t >= tmin) {
  142.             if (t > tmax)
  143.                 return FALSE;
  144.             tmin = t;
  145.         }
  146.     } else if (pos < bounds[LOW][Z] || pos > bounds[HIGH][Z])
  147.         return FALSE;
  148.  
  149.     /*
  150.      * If tmin == mindist, then there was no "near"
  151.      * intersection farther than EPSILON away.
  152.      */
  153.     if (tmin == mindist) {
  154.         if (tmax < *maxdist) {
  155.             *maxdist = tmax;
  156.             return TRUE;
  157.         }
  158.     } else {
  159.         if (tmin < *maxdist) {
  160.             *maxdist = tmin;
  161.             return TRUE;
  162.         }
  163.     }
  164.     return FALSE;    /* hit, but not closer than maxdist */
  165. }
  166.  
  167. /*
  168.  * Transform an object's bounding box by the given transformation
  169.  * matrix.
  170.  */
  171. void
  172. BoundsTransform(trans, objbounds)
  173. RSMatrix *trans;
  174. Float objbounds[2][3];
  175. {
  176.     Float bounds[2][3], a, b;
  177.     int i, j;
  178.  
  179.     /*
  180.      * Can't (and shouldn't) do anything with unbounded objects.
  181.      */
  182.     if (objbounds[LOW][X] > objbounds[HIGH][X])
  183.         return;
  184.  
  185.     bounds[LOW][X] = bounds[HIGH][X] = trans->translate.x;
  186.     bounds[LOW][Y] = bounds[HIGH][Y] = trans->translate.y;
  187.     bounds[LOW][Z] = bounds[HIGH][Z] = trans->translate.z;
  188.  
  189.     for (i = 0; i < 3; i++) {
  190.         for (j = 0; j < 3; j++) {
  191.             a = trans->matrix[j][i] * objbounds[LOW][j];
  192.             b = trans->matrix[j][i] * objbounds[HIGH][j];
  193.             if (a < b) {
  194.                 bounds[LOW][i] += a;
  195.                 bounds[HIGH][i] += b;
  196.             } else {
  197.                 bounds[LOW][i] += b;
  198.                 bounds[HIGH][i] += a;
  199.             }
  200.         }
  201.     }
  202.     BoundsCopy(bounds, objbounds);
  203. }
  204.  
  205. void
  206. BoundsInit(bounds)
  207. Float bounds[2][3];
  208. {
  209.     bounds[LOW][X] = bounds[LOW][Y] = bounds[LOW][Z] = FAR_AWAY;
  210.     bounds[HIGH][X] = bounds[HIGH][Y] = bounds[HIGH][Z] = -FAR_AWAY;
  211. }
  212.  
  213. void
  214. BoundsCopy(from, into)
  215. Float into[2][3], from[2][3];
  216. {
  217.     into[LOW][X] = from[LOW][X];
  218.     into[LOW][Y] = from[LOW][Y];
  219.     into[LOW][Z] = from[LOW][Z];
  220.     into[HIGH][X] = from[HIGH][X];
  221.     into[HIGH][Y] = from[HIGH][Y];
  222.     into[HIGH][Z] = from[HIGH][Z];
  223. }
  224.  
  225. #define SetIfLess(a, b)        (a = ((a) < (b) ? (a) : (b)))
  226. #define SetIfGreater(a, b)    (a = ((a) > (b) ? (a) : (b)))
  227.  
  228. /*
  229.  * Find bounding box of the union of two bounding boxes.
  230.  */
  231. void
  232. BoundsEnlarge(old, new)
  233. Float old[2][3], new[2][3];
  234. {
  235.     SetIfLess(old[LOW][X], new[LOW][X]);
  236.     SetIfLess(old[LOW][Y], new[LOW][Y]);
  237.     SetIfLess(old[LOW][Z], new[LOW][Z]);
  238.     SetIfGreater(old[HIGH][X], new[HIGH][X]);
  239.     SetIfGreater(old[HIGH][Y], new[HIGH][Y]);
  240.     SetIfGreater(old[HIGH][Z], new[HIGH][Z]);
  241. }
  242.  
  243. /*
  244.  * Enlarge bounding box so it contains the sphere centered at 'Center' with 
  245.  * radius 'radius'.
  246.  */
  247. void
  248. BoundsEnlargeSphere(bounds, Center, radius)
  249. Float bounds[2][3], radius;
  250. Vector *Center;
  251. {
  252.     SetIfLess(bounds[LOW][X], Center->x - radius);
  253.     SetIfLess(bounds[LOW][Y], Center->y - radius);
  254.     SetIfLess(bounds[LOW][Z], Center->z - radius);
  255.     SetIfGreater(bounds[HIGH][X], Center->x + radius);
  256.     SetIfGreater(bounds[HIGH][Y], Center->y + radius);
  257.     SetIfGreater(bounds[HIGH][Z], Center->z + radius);
  258. }
  259.  
  260. void
  261. BoundsPrint(box, fp)
  262. Float box[2][3];
  263. FILE *fp;
  264. {
  265.     fprintf(fp,"\tX: %f to %f\n",box[LOW][X], box[HIGH][X]);
  266.     fprintf(fp,"\tY: %f to %f\n",box[LOW][Y], box[HIGH][Y]);
  267.     fprintf(fp,"\tZ: %f to %f\n",box[LOW][Z], box[HIGH][Z]);
  268. }
  269.