home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* pbvol.c */
- /* */
- /* Bounding volume creation and manipulation routines */
- /* (See also hbvol.c for hierarchical bounding volume routines */
- /* (See also raysp.c for culling bounding volume routines */
- /* */
- /* Copyright (C) 1992, Bernard Kwok */
- /* All rights reserved. */
- /* Revision 1.0 */
- /* May, 1992 */
- /**********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "misc.h"
- #include "geo.h"
-
- #define NUMDIM 3
- #define SetIfLess(a, b, c) ((c) = ((a) < (b) ? (a) : (b)))
- #define SetIfGreater(a, b, c) ((c) = ((a) > (b) ? (a) : (b)))
-
- void BoundsPrint();
-
- /**********************************************************************/
- /* Initialize box to invalid box */
- /**********************************************************************/
- void BoxInit(box)
- BoundingBoxType *box;
- {
- box->min.x = VERY_LARGE;
- box->min.y = VERY_LARGE;
- box->min.z = VERY_LARGE;
- box->max.x = -VERY_LARGE;
- box->max.y = -VERY_LARGE;
- box->max.z = -VERY_LARGE;
- }
-
- /**********************************************************************/
- /* Update the size of a box by a given point */
- /**********************************************************************/
- void Update_BoxSize(pt,box)
- Vector pt;
- BoundingBoxType *box;
- {
- if (pt.x > box->max.x) box->max.x = pt.x;
- if (pt.y > box->max.y) box->max.y = pt.y;
- if (pt.z > box->max.z) box->max.z = pt.z;
-
- if (pt.x < box->min.x) box->min.x = pt.x;
- if (pt.y < box->min.y) box->min.y = pt.y;
- if (pt.z < box->min.z) box->min.z = pt.z;
- }
-
- /**********************************************************************/
- /* Form bounding box for a cone - unit cube. Sits on z = 0 plane */
- /**********************************************************************/
- BoundingBoxType BoxCone()
- {
- BoundingBoxType box;
-
- box.min.x= -1.0;
- box.min.y= -1.0;
- box.min.z= 0.0;
- box.max.x= 1.0;
- box.max.y= 1.0;
- box.max.z= 2.0;
- return(box);
- }
-
- /**********************************************************************/
- /* Form bounding box for a cube - unit cube */
- /**********************************************************************/
- BoundingBoxType BoxCube()
- {
- BoundingBoxType box;
-
- box.min.x= -1.;
- box.min.y= -1.;
- box.min.z= -1.;
- box.max.x= 1.;
- box.max.y= 1.;
- box.max.z= 1.;
- return(box);
- }
-
- /**********************************************************************/
- /* Form bounding box for cylinder - unit box */
- /**********************************************************************/
- BoundingBoxType BoxCylinder()
- {
- BoundingBoxType box;
-
- box.min.x= -1.;
- box.min.y= -1.;
- box.min.z= -1.;
- box.max.x= 1.;
- box.max.y= 1.;
- box.max.z= 1.;
- return(box);
- }
-
- /**********************************************************************/
- /* Form bounding box for sphere - unit box */
- /**********************************************************************/
- BoundingBoxType BoxSphere()
- {
- BoundingBoxType box;
-
- box.min.x= -1.;
- box.min.y= -1.;
- box.min.z= -1.;
- box.max.x= 1.;
- box.max.y= 1.;
- box.max.z= 1.;
- return(box);
- }
-
- /**********************************************************************/
- /* Find bounding box of the union of two bounding boxes. */
- /**********************************************************************/
- void Bounds_Union(box1, box2, new)
- BoundingBoxType box1, box2;
- BoundingBoxType *new;
- {
- SetIfLess(box1.min.x, box2.min.x, new->min.x);
- SetIfLess(box1.min.y, box2.min.y, new->min.y);
- SetIfLess(box1.min.z, box2.min.z, new->min.z);
- SetIfGreater(box1.max.x, box2.max.x, new->max.x);
- SetIfGreater(box1.max.y, box2.max.y, new->max.y);
- SetIfGreater(box1.max.z, box2.max.z, new->max.z);
- }
-
- /**********************************************************************/
- /* Bounds box 1 same as box 2 */
- /**********************************************************************/
- int Bounds_Same(box1, box2)
- BoundingBoxType *box1, *box2;
- {
- if (box2->min.x != box1->min.x) return 0;
- if (box2->min.y != box1->min.y) return 0;
- if (box2->min.z != box1->min.z) return 0;
- if (box2->max.x != box1->max.x) return 0;
- if (box2->max.y != box1->max.y) return 0;
- if (box2->max.z != box1->max.z) return 0;
- return 1;
- }
-
- #define OUTSIDE 0
- #define OVERLAP 1
- #define INSIDE 2
- #define CONTAINS 3
- /**********************************************************************/
- /* Test if 2 bounding boxes intersect, inside, or outside each other */
- /**********************************************************************/
- int Bounds_Compare(box1,box2)
- BoundingBoxType *box1, *box2;
- {
- int xoverlap, yoverlap, zoverlap;
- BoundingBoxType box12;
-
- Bounds_Union(*box1, *box2, &box12);
- if (Bounds_Same(box1, &box12)) { /* Test box contains other box */
- /* BoundsPrint(*box1, stdout, "box1 contains");
- BoundsPrint(*box2, stdout, "box2."); */
- return CONTAINS;
- }
- if (Bounds_Same(box2, &box12)) { /* Test box is inside other box */
- /* BoundsPrint(*box1, stdout, "box1 inside");
- BoundsPrint(*box2, stdout, "box2."); */
- return INSIDE;
- }
-
- xoverlap = ((box1->max.x > box2->min.x && box1->max.x < box2->max.x) ||
- (box1->min.x > box2->min.x && box1->min.x < box2->max.x));
- yoverlap = ((box1->max.y > box2->min.y && box1->max.y < box2->max.y) ||
- (box1->min.y > box2->min.y && box1->min.y < box2->max.y));
- zoverlap = ((box1->max.z > box2->min.z && box1->max.z < box2->max.z) ||
- (box1->min.z > box2->min.z && box1->min.z < box2->max.z));
- if (xoverlap && yoverlap && zoverlap) {
- /* BoundsPrint(*box1, stdout, "box1 overlaps");
- BoundsPrint(*box2, stdout, "box2."); */
- return OVERLAP;
- }
- return OUTSIDE;
- }
-
- /**********************************************************************/
- /* Copy bounds from box 1 to box 2 */
- /**********************************************************************/
- void Bounds_Copy(box1, box2)
- BoundingBoxType box1, *box2;
- {
- box2->min.x = box1.min.x;
- box2->min.y = box1.min.y;
- box2->min.z = box1.min.z;
- box2->max.x = box1.max.x;
- box2->max.y = box1.max.y;
- box2->max.z = box1.max.z;
- }
-
- /**********************************************************************/
- /* Transforming Axis-Aligned Bounding Boxes by James Arvo */
- /* from "Graphics Gems", Academic Press, 1990 */
- /* */
- /* Transform axis-aligned bounding box via transformation, and */
- /* computing the axis-aligned bounding box enclosing the result */
- /* (translation in x,y,z is in M[3][0 to 2] */
- /**********************************************************************/
- void Bounds_Transform( M, A, B )
- Matrix M; /* Transform matrix. */
- BoundingBoxType A; /* The original bounding box. */
- BoundingBoxType *B; /* The transformed bounding box. */
- {
- float a, b;
- float Amin[3], Amax[3];
- float Bmin[3], Bmax[3];
- int i, j;
-
- /* Copy box A into a min array and a max array for easy reference.*/
- Amin[0] = A.min.x; Amax[0] = A.max.x;
- Amin[1] = A.min.y; Amax[1] = A.max.y;
- Amin[2] = A.min.z; Amax[2] = A.max.z;
-
- /* Take care of translation by beginning at T. */
- Bmin[0] = Bmax[0] = M[3][0];
- Bmin[1] = Bmax[1] = M[3][1];
- Bmin[2] = Bmax[2] = M[3][2];
-
- /* Now find the extreme points by considering the product of the */
- /* min and max with each component of M. */
- for( i=0; i<3; i++ ) {
- for( j=0; j<3; j++ ) {
- a = M[i][j] * Amin[j];
- b = M[i][j] * Amax[j];
- if( a < b ) {
- Bmin[i] += a;
- Bmax[i] += b;
- } else {
- Bmin[i] += b;
- Bmax[i] += a;
- }
- }
- }
- /* Copy the result into the new box. */
- B->min.x = Bmin[0]; B->max.x = Bmax[0];
- B->min.y = Bmin[1]; B->max.y = Bmax[1];
- B->min.z = Bmin[2]; B->max.z = Bmax[2];
- }
-
- /**********************************************************************/
- /* Print a bounding box */
- /**********************************************************************/
- void BoundsPrint(box, fp, label)
- BoundingBoxType box;
- FILE *fp;
- char *label;
- {
- fprintf(fp,"\tBounding box: %s : ", label);
- fprintf(fp,"X: %g to %g; ", box.min.x, box.max.x);
- fprintf(fp,"Y: %g to %g; ", box.min.y, box.max.y);
- fprintf(fp,"Z: %g to %g\n", box.min.z, box.max.z);
- }
-