home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* raybox.c */
- /* */
- /* Ray / box intersection routines */
- /* */
- /* Copyright (C) 1992, Bernard Kwok */
- /* All rights reserved. */
- /* Revision 1.0 */
- /* May, 1992 */
- /**********************************************************************/
- /* Finished */
- #include <stdio.h>
- #include "geo.h"
- #include "misc.h"
- #include "struct.h"
- #include "io.h"
- #include "ray.h"
- #include "bvol.h"
-
- /**********************************************************************/
- extern OptionType Option;
- extern RayStats_Type RayStats;
-
- #define RIGHT 0
- #define LEFT 1
- #define MIDDLE 2
- #define NUMDIM 3
-
- /**********************************************************************/
- /* Ray-Box Intersection by Andrew Woo from "Graphics Gems", Academic */
- /* Press, 1990 */
- /* Returns true if intersects, and intersect distance. */
- /**********************************************************************/
- int RayBoundingBox(box, ray, d)
- BoundingBoxType box;
- Ray ray;
- double *d;
- {
- double minB[NUMDIM], maxB[NUMDIM]; /* box */
- double coord[NUMDIM]; /* hit point */
- double ray_orig[NUMDIM], ray_dir[NUMDIM]; /* ray */
- char inside = TRUE;
- char quadrant[NUMDIM];
- register int i;
- int whichPlane;
- double maxT[NUMDIM];
- double candidatePlane[NUMDIM];
- Vector *t;
-
- /* Do some setup */
- minB[0] = box.min.x; minB[1] = box.min.y; minB[2] = box.min.z;
- maxB[0] = box.max.x; maxB[1] = box.max.y; maxB[2] = box.max.z;
- ray_orig[0] = ray.origin.x;
- ray_orig[1] = ray.origin.y;
- ray_orig[2] = ray.origin.z;
- ray_dir[0] = ray.dir.x;
- ray_dir[1] = ray.dir.y;
- ray_dir[2] = ray.dir.z; *d = 0.0;
-
- /* Find candidate planes; this loop can be avoided if
- rays cast all from the eye (assume perpsective view) */
- for (i=0; i<3; i++)
- if (ray_orig[i] < minB[i]) {
- quadrant[i] = LEFT;
- candidatePlane[i] = minB[i];
- inside = FALSE;
- } else if (ray_orig[i] > maxB[i]) {
- quadrant[i] = RIGHT;
- candidatePlane[i] = maxB[i];
- inside = FALSE;
- } else {
- quadrant[i] = MIDDLE;
- }
-
- /* Ray is inside bounding box */
- if (inside) {
- /* *t = ray.origin; */
- return (TRUE);
- }
-
- /* Calculate the distances to candidate planes */
- for (i=0; i<NUMDIM; i++)
- if (quadrant[i] != MIDDLE && ray_dir[i] !=0.0)
- maxT[i] = (candidatePlane[i]-ray_orig[i]) / ray_dir[i];
- else
- maxT[i] = -1.;
-
- /* Get largest of the maxT's for final choice of intersection */
- whichPlane = 0;
- for (i = 1; i < NUMDIM; i++)
- if (maxT[whichPlane] < maxT[i])
- whichPlane = i;
-
- /* Check if final candidate actually inside box */
- if (maxT[whichPlane] < 0.0)
- return (FALSE);
- for (i = 0; i < NUMDIM; i++)
- if (whichPlane != i) {
- coord[i] = ray_orig[i] + maxT[whichPlane] * ray_dir[i];
- if ((quadrant[i] == RIGHT && coord[i] < minB[i]) ||
- (quadrant[i] == LEFT && coord[i] > maxB[i]))
- return (FALSE); /* outside box */
- } else {
- coord[i] = candidatePlane[i];
- }
-
- /* t->x = coord[0]; t->y = coord[1]; t->z = coord[2]; */
- *d = maxT[whichPlane];
- return (TRUE); /* ray hits box */
- }
-
- /**********************************************************************/
- /* Axis-aligned bounding box intersection normal */
- /**********************************************************************/
- int BoxNormal(box, pos, nrm, gnrm)
- Vector *pos, *nrm; /* point of intersection, and normal to return */
- BoundingBoxType *box;
- {
- nrm->x = nrm->y = nrm->z = 0.;
-
- if (equal(pos->x,box->max.x))
- nrm->x = 1.0;
- else if (equal(pos->x,box->min.x))
- nrm->x = -1.0;
- else if (equal(pos->y,box->max.y))
- nrm->y = 1.0;
- else if (equal(pos->y,box->min.y))
- nrm->y = -1.0;
- else if (equal(pos->z,box->max.z))
- nrm->z = 1.0;
- else if (equal(pos->z,box->min.z))
- nrm->z = -1.0;
- else {
- fprintf(stderr, "Can't get normal of bounding box intersection\n");
- return 0;
- }
- return(1);
- }
-
- /**********************************************************************/
- /* Determine if ray enters (TRUE) or leaves (0) box at pos */
- /**********************************************************************/
- int BoxEnter(box, ray, mind, hitd)
- BoundingBoxType *box;
- Ray *ray;
- double mind, hitd;
- {
- Vector pos;
-
- pos.x = ray->origin.x + mind * ray->dir.x;
- pos.y = ray->origin.y + mind * ray->dir.y;
- pos.z = ray->origin.z + mind * ray->dir.z;
- return OutOfBounds(&pos, box);
- }
-
-