home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * ATTENTION!!!
- *
- * THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
- * POV-RAY 2.2 DISTRIBUTION!!!
- *
- * THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 2.2),
- * A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
- *
- * New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
- *
- * The additional modules were written by Dieter Bayer.
- *
- * Send comments, suggestions, bugs, ideas ... to:
- *
- * e-mail: dieter@cip.e-technik.uni-erlangen.de
- * CIS: 100255.3074
- *
- * All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
- *
- * The vista projection was taken from:
- *
- * A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga,
- * "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
- * Projection Image", New Advances in Computer Graphics, Proceedings
- * of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.),
- * Springer, ..., pp. 549-560
- *
- * The idea for the light buffer was taken from:
- *
- * E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing
- * Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
- *
- *****************************************************************************/
-
- /****************************************************************************
- * addon3.c
- *
- * This module was written by Dieter Bayer.
- *
- * This module contains the functions used to recompute the
- * automatically generated bounding boxes and to removed unnecessary
- * bounding objects.
- *
- * 01.04.1994 : Creation
- *
- * 29.04.1994 : Version 2.0
- *
- ******************************************************************************/
-
- #include <time.h>
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
- #include "addon.h"
-
- #ifdef DB_CODE
-
-
-
- /*****************************************************************************
- * external variables
- ******************************************************************************/
-
- extern FRAME Frame;
- extern unsigned int Options, Extended_Options;
-
- extern METHODS Bicubic_Patch_Methods;
- extern METHODS Blob_Methods;
- extern METHODS Box_Methods;
- extern METHODS Cone_Methods;
- extern METHODS Csg_Height_Field_Methods;
- extern METHODS CSG_Intersection_Methods;
- extern METHODS CSG_Merge_Methods;
- extern METHODS CSG_Union_Methods;
- extern METHODS Disc_Methods;
- extern METHODS Ellipsoid_Methods;
- extern METHODS Height_Field_Methods;
- extern METHODS Light_Source_Methods;
- extern METHODS Plane_Methods;
- extern METHODS Poly_Methods;
- extern METHODS Quadric_Methods;
- extern METHODS Smooth_Triangle_Methods;
- extern METHODS Sphere_Methods;
- extern METHODS Triangle_Methods;
-
-
-
- /*****************************************************************************
- * static variables
- ******************************************************************************/
-
- static long int FoundEllipsoid = 0;
- static long int FoundCylinder = 0;
- static long int FoundCone = 0;
-
-
-
- /*****************************************************************************
- * static functions
- ******************************************************************************/
-
- static void Recompute_Bbox PARAMS((OBJECT *Object, long *count));
-
- static void Remove_Bound PARAMS((OBJECT *Object, long *removed));
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Recompute_BBoxes
- *
- * ARGUMENTS : none
- *
- * MODIFIED ARGS : none
- *
- * RETURN VALUE : none
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Recompute all automatically generated bounding slabs.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- void Recompute_Bboxes()
- {
- long count;
- OBJECT *Object;
-
- count = 0;
-
- fprintf(stderr, "Reducing bounding boxes");
-
- Begin_Point();
-
- for (Object = Frame.Objects; Object != NULL; Object = Object->Sibling)
- {
- if (Object->Methods == &Light_Source_Methods)
- Recompute_Bbox(((LIGHT_SOURCE *)Object)->Children, &count);
- else
- Recompute_Bbox(Object, &count);
- }
-
- fprintf(stderr,"(%ld reduced)", count);
-
- End_Point();
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Recompute_BBox
- *
- * ARGUMENTS : Object - Object
- * count - Counter to count reduced bounding boxes
- *
- * MODIFIED ARGS : count
- *
- * RETURN VALUE : none
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Recompute the bounding box of an object:
- *
- * - Calculate the bounding box of CSG intersections by
- * intersecting the bounding boxes of all children (obsolete?)
- *
- * - Consider bounding and clipping objects.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Recompute_Bbox(Object, count)
- OBJECT *Object;
- long *count;
- {
- int counted, i, j;
- DBL Old_Volume, New_Volume, Bounds_Volume, Clip_Volume;
- VECTOR Min, Max, P;
- OBJECT *Sib;
- BBOX New_Bounds, Old_Bounds, Bounds_Bounds, Clip_Bounds;
- METHODS *Methods;
- HEIGHT_FIELD *Height_Field;
-
- if (Object == NULL)
- return;
-
- counted = FALSE;
-
- /* Check for bounds too large
- (I want everything to stay inside the largest bounding box) */
-
- Object->Bounds.Lower_Left.x = max(Object->Bounds.Lower_Left.x, -BOUND_HUGE/2);
- Object->Bounds.Lower_Left.y = max(Object->Bounds.Lower_Left.y, -BOUND_HUGE/2);
- Object->Bounds.Lower_Left.z = max(Object->Bounds.Lower_Left.z, -BOUND_HUGE/2);
-
- Object->Bounds.Lengths.x = min(Object->Bounds.Lengths.x, BOUND_HUGE);
- Object->Bounds.Lengths.y = min(Object->Bounds.Lengths.y, BOUND_HUGE);
- Object->Bounds.Lengths.z = min(Object->Bounds.Lengths.z, BOUND_HUGE);
-
- /* Init New_Bounds */
-
- New_Bounds.Lower_Left.x =
- New_Bounds.Lower_Left.y =
- New_Bounds.Lower_Left.z = -BOUND_HUGE/2;
-
- New_Bounds.Lengths.x =
- New_Bounds.Lengths.y =
- New_Bounds.Lengths.z = BOUND_HUGE;
-
- BOUNDS_VOLUME (New_Volume, New_Bounds);
-
- /* Get Old_Bounds with bounds from current object */
-
- Old_Bounds = Object->Bounds;
-
- BOUNDS_VOLUME (Old_Volume, Old_Bounds);
-
- /* Init Bounds_Bounds with bounds from object's bounding object */
-
- Bounds_Bounds.Lower_Left.x =
- Bounds_Bounds.Lower_Left.y =
- Bounds_Bounds.Lower_Left.z = -BOUND_HUGE/2;
-
- Bounds_Bounds.Lengths.x =
- Bounds_Bounds.Lengths.y =
- Bounds_Bounds.Lengths.z = BOUND_HUGE;
-
- if (Object->Bound != NULL)
- {
- Min.x = Min.y = Min.z = -BOUND_HUGE;
- Max.x = Max.y = Max.z = +BOUND_HUGE;
-
- for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)
- {
- /*
- Recompute_Bbox(Sib, count);
- */
- if (!Test_Inverted(Sib))
- {
- Min.x = max(Min.x, Sib->Bounds.Lower_Left.x);
- Min.y = max(Min.y, Sib->Bounds.Lower_Left.y);
- Min.z = max(Min.z, Sib->Bounds.Lower_Left.z);
- Max.x = min(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
- Max.y = min(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
- Max.z = min(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
- }
- }
-
- Bounds_Bounds.Lower_Left = Min;
- VSub (Bounds_Bounds.Lengths, Max, Min);
- }
-
- BOUNDS_VOLUME (Bounds_Volume, Bounds_Bounds);
-
- /* Init Clip_Bounds with bounds from object's clipping object */
-
- Clip_Bounds.Lower_Left.x =
- Clip_Bounds.Lower_Left.y =
- Clip_Bounds.Lower_Left.z = -BOUND_HUGE/2;
-
- Clip_Bounds.Lengths.x =
- Clip_Bounds.Lengths.y =
- Clip_Bounds.Lengths.z = BOUND_HUGE;
-
- if (Object->Clip != NULL)
- {
- Min.x = Min.y = Min.z = -BOUND_HUGE;
- Max.x = Max.y = Max.z = +BOUND_HUGE;
-
- for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)
- {
- /*
- Recompute_Bbox(Sib, count);
- */
- if (!Test_Inverted(Sib))
- {
- Min.x = max(Min.x, Sib->Bounds.Lower_Left.x);
- Min.y = max(Min.y, Sib->Bounds.Lower_Left.y);
- Min.z = max(Min.z, Sib->Bounds.Lower_Left.z);
- Max.x = min(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
- Max.y = min(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
- Max.z = min(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
- }
- }
-
- Clip_Bounds.Lower_Left = Min;
- VSub (Clip_Bounds.Lengths, Max, Min);
- }
-
- BOUNDS_VOLUME (Clip_Volume, Clip_Bounds);
-
- Methods = Object->Methods;
-
- /* Check for CSG/primitive objects */
-
- if (Object->Type & COMPOUND_OBJECT)
- {
- if (Methods == &Light_Source_Methods)
- {
- Recompute_Bbox(((LIGHT_SOURCE *)Object)->Children, count);
- }
- else
- {
- /* CSG object */
-
- if (Methods == &CSG_Intersection_Methods)
- {
- Min.x = Min.y = Min.z = -BOUND_HUGE;
- Max.x = Max.y = Max.z = +BOUND_HUGE;
-
- /* Get the bounding box by recursively calculating the children's
- bounding boxes. */
-
- for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
- {
- Recompute_Bbox(Sib, count);
-
- /* Inverted objects must not be considered! */
-
- if (!Test_Inverted(Sib))
- {
- Min.x = max(Min.x, Sib->Bounds.Lower_Left.x);
- Min.y = max(Min.y, Sib->Bounds.Lower_Left.y);
- Min.z = max(Min.z, Sib->Bounds.Lower_Left.z);
- Max.x = min(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
- Max.y = min(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
- Max.z = min(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
- }
- }
- }
- else
- {
- Min.x = Min.y = Min.z = +BOUND_HUGE;
- Max.x = Max.y = Max.z = -BOUND_HUGE;
-
- /* Get the bounding box by recursively calculating the children's
- bounding boxes. */
-
- for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
- {
- Recompute_Bbox(Sib, count);
-
- Min.x = min(Min.x, Sib->Bounds.Lower_Left.x);
- Min.y = min(Min.y, Sib->Bounds.Lower_Left.y);
- Min.z = min(Min.z, Sib->Bounds.Lower_Left.z);
- Max.x = max(Max.x, Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x);
- Max.y = max(Max.y, Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y);
- Max.z = max(Max.z, Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z);
- }
- }
-
- New_Bounds.Lower_Left = Min;
- VSub (New_Bounds.Lengths, Max, Min);
-
- BOUNDS_VOLUME(New_Volume, New_Bounds);
- }
- }
- else
- {
- /* Primitive object*/
-
- /* The bounding box for height fields is not calculated in POV-Ray 2.2 */
-
- if ((Methods == &Height_Field_Methods) ||
- (Methods == &Csg_Height_Field_Methods))
- {
- Height_Field = (HEIGHT_FIELD *)Object;
-
- New_Bounds.Lower_Left = Height_Field->bounding_box->bounds[0];
- VSub (New_Bounds.Lengths, Height_Field->bounding_box->bounds[1], Height_Field->bounding_box->bounds[0]);
- recompute_bbox(&New_Bounds, Height_Field->Trans);
- BOUNDS_VOLUME (New_Volume, New_Bounds);
- }
-
- /* The bounding box for bicubic patches is not calculated in POV-Ray 2.2 */
-
- if (Methods == &Bicubic_Patch_Methods)
- {
- Min.x = Min.y = Min.z = +BOUND_HUGE;
- Max.x = Max.y = Max.z = -BOUND_HUGE;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 4; j++)
- {
- P = ((BICUBIC_PATCH *)Object)->Control_Points[i][j];
- Min.x = min (Min.x, P.x);
- Min.y = min (Min.y, P.y);
- Min.z = min (Min.z, P.z);
- Max.x = max (Max.x, P.x);
- Max.y = max (Max.y, P.y);
- Max.z = max (Max.z, P.z);
- }
- }
- New_Bounds.Lower_Left = Min;
- VSub (New_Bounds.Lengths, Max, Min);
- BOUNDS_VOLUME (New_Volume, New_Bounds);
- }
- }
-
- /* Check which bounding box fits best */
-
- if ((New_Volume < Old_Volume) && (New_Volume > 0.0))
- {
- Object->Bounds = New_Bounds;
- Old_Volume = New_Volume;
- if (!counted)
- {
- (*count)++;
- counted = TRUE;
- Print_Point(POINT_MOD);
- }
- }
-
- if ((Bounds_Volume < Old_Volume) && (Bounds_Volume > 0.0))
- {
- Object->Bounds = Bounds_Bounds;
- Old_Volume = Bounds_Volume;
- if (!counted)
- {
- (*count)++;
- counted = TRUE;
- Print_Point(POINT_MOD);
- }
- }
-
- if ((Clip_Volume < Old_Volume) && (Clip_Volume > 0.0))
- {
- Object->Bounds = Clip_Bounds;
- if (!counted)
- {
- (*count)++;
- counted = TRUE;
- Print_Point(POINT_MOD);
- }
- }
- }
-
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Test_Inverted
- *
- * ARGUMENTS : Object - Object
- *
- * MODIFIED ARGS : none
- *
- * RETURN VALUE : int - TRUE, if object is inverted
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Check if an object is inverted.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- int Test_Inverted(Object)
- OBJECT *Object;
- {
- METHODS *methods;
-
- methods = Object->Methods;
-
- if (methods == &Blob_Methods)
- return(((BLOB *)Object)->Inverted);
-
- if (methods == &Box_Methods)
- return(((BOX *)Object)->Inverted);
-
- if (methods == &Cone_Methods)
- return(((CONE *)Object)->Inverted);
-
- if (methods == &Csg_Height_Field_Methods)
- return(((HEIGHT_FIELD *)Object)->Inverted);
-
- if (methods == &CSG_Intersection_Methods)
- return(((CSG *)Object)->Inverted);
-
- if (methods == &CSG_Union_Methods)
- return(((CSG *)Object)->Inverted);
-
- if (methods == &Disc_Methods)
- return(((DISC *)Object)->Inverted);
-
- if (methods == &Ellipsoid_Methods)
- return(((SPHERE *)Object)->Inverted);
-
- if (methods == &Height_Field_Methods)
- return(((HEIGHT_FIELD *)Object)->Inverted);
-
- if (methods == &Poly_Methods)
- return(((POLY *)Object)->Inverted);
-
- if (methods == &Quadric_Methods)
- return(((QUADRIC *)Object)->Inverted);
-
- if (methods == &Sphere_Methods)
- return(((SPHERE *)Object)->Inverted);
-
- return(FALSE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Remove_Unnecessary_Bounds
- *
- * ARGUMENTS : none
- *
- * MODIFIED ARGS : none
- *
- * RETURN VALUE : none
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Remove unnecessary bounding objects.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- void Remove_Unnecessary_Bounds()
- {
- long removed;
- OBJECT *Sib;
-
- removed = 0;
-
- fprintf(stderr, "Removing bounds");
-
- Begin_Point();
-
- for (Sib = Frame.Objects; Sib != NULL; Sib = Sib->Sibling)
- {
- Remove_Bound(Sib, &removed);
- }
-
- fprintf(stderr, "(%ld removed)\n", removed);
-
- End_Point();
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Remove_Bound
- *
- * ARGUMENTS : Object - Object
- * removed - Counter to count removed bounding objects
- *
- * MODIFIED ARGS : removed
- *
- * RETURN VALUE : none
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Remove bounding objects from finite primitive objects. This has to be
- * done after (bounded) unions were split.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Remove_Bound(Object, removed)
- OBJECT *Object;
- long *removed;
- {
- OBJECT *Sib;
-
- if (Object == NULL)
- return;
-
- if (Object->Type & COMPOUND_OBJECT)
- {
- if (Object->Type & LIGHT_SOURCE_OBJECT)
- {
- Remove_Bound(((LIGHT_SOURCE *)Object)->Children, removed);
- }
- else
- {
- /*
- Don't know if this is a good idea ...
-
- Object->Bound = NULL;
- */
-
- for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
- {
- Remove_Bound(Sib, removed);
- }
- }
- }
- else
- {
- if (Object->Bound != NULL)
- {
- /* Remove bounding boxes around finite objects.
- (it's a waste of time to bound these objects) */
-
- if ((Object->Methods == &Bicubic_Patch_Methods) ||
- (Object->Methods == &Box_Methods) ||
- (Object->Methods == &Csg_Height_Field_Methods) ||
- (Object->Methods == &Cone_Methods) ||
- (Object->Methods == &Disc_Methods) ||
- (Object->Methods == &Ellipsoid_Methods) ||
- (Object->Methods == &Height_Field_Methods) ||
- (Object->Methods == &Plane_Methods) ||
- (Object->Methods == &Quadric_Methods) ||
- (Object->Methods == &Sphere_Methods) ||
- (Object->Methods == &Smooth_Triangle_Methods) ||
- (Object->Methods == &Triangle_Methods))
- {
- Object->Bound = NULL;
- Print_Point(POINT_MOD);
- (*removed)++;
- }
- }
- }
- }
-
-
-
- /*****************************************************************************
- *****************************************************************************/
-
- void Print_Quadric_Stats()
- {
- /*
- This gives wrong results....
-
- if (FoundCone)
- fprintf(stderr, "Quadric-Cone found: %ld\n", FoundCone);
- if (FoundCylinder)
- fprintf(stderr, "Quadric-Cylinder found: %ld\n", FoundCylinder);
- if (FoundEllipsoid)
- fprintf(stderr, "Quadric-Ellipsoids found: %ld\n", FoundEllipsoid);
- */
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Compute_Quadric_BBox
- *
- * ARGUMENTS : Quadric - Qaudric object
- *
- * MODIFIED ARGS : Quadric
- *
- * RETURN VALUE : none
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Compute a bounding box around a quadric.
- *
- * This function calculates the bounding box for quadrics given in
- * their normal form, i.e. f(x,y,z) = A*x*x + B*y*y + C*z*z + J = 0.
- * That's the form normally used in the declaration of quadric shapes.
- *
- * They can still be translated, rotated, and scaled after declaration.
- *
- * Currently clipped cones, cylinders, and ellipsoids are supported.
- *
- * (Btw, a quadric ellipsoid is intersected faster than a scaled sphere!!!
- * The problem that quadrics don't respond to automatic bounding is
- * solved for some quadric shapes with this function. With this function
- * the modules for cones/cylinders and ellipsoids may even be obsolete.)
- *
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- void Compute_Quadric_BBox(Quadric)
- QUADRIC *Quadric;
- {
- DBL kx, ky, kz, k, a, b, c;
- DBL rx, ry, rz, rx1, rx2, ry1, ry2, rz1, rz2, x, y, z;
- DBL New_Volume, Old_Volume;
- VECTOR Min, Max, TmpMin, TmpMax, NewMin, NewMax, ClipMin, ClipMax;
- BBOX Old;
- OBJECT *Sib;
-
- if (!(Extended_Options & USE_BOUND_QUADRICS))
- return;
-
- /* Inverted quadrics are infinite */
-
- /*
- That's true ... but it makes no difference in intersecting the quadric ...
- it only affects the inside/outside test ...
-
- if (Quadric->Inverted)
- return;
- */
-
- /* Check for 'normal' form. If the quadric isn't in it's normal form
- we can't do anything (we could, but that would be to tedious!
- Diagonalising the quadric's 4x4 matrix, i.e. finding its eigenvalues
- and eigenvectors -> solving a 4th order polynom) */
-
- kx = Quadric->Mixed_Terms.x;
- ky = Quadric->Mixed_Terms.y;
- kz = Quadric->Mixed_Terms.z;
-
- if ((fabs(kx) > EPSILON) || (fabs(ky) > EPSILON) || (fabs(kz) > EPSILON))
- return;
-
- kx = Quadric->Terms.x;
- ky = Quadric->Terms.y;
- kz = Quadric->Terms.z;
-
- if ((fabs(kx) > EPSILON) || (fabs(ky) > EPSILON) || (fabs(kz) > EPSILON))
- return;
-
- /* Get old bounding box */
-
- Old = Quadric->Bounds;
-
- /* Init new bounding box */
-
- NewMin.x = NewMin.y = NewMin.z = -BOUND_HUGE;
-
- NewMax.x = NewMax.y = NewMax.z = BOUND_HUGE;
-
- /* Get the bounding box of the clipping object */
-
- ClipMin.x = ClipMin.y = ClipMin.z = -BOUND_HUGE;
-
- ClipMax.x = ClipMax.y = ClipMax.z = BOUND_HUGE;
-
- if (Quadric->Clip != NULL)
- {
- Min.x = Min.y = Min.z = -BOUND_HUGE;
- Max.x = Max.y = Max.z = +BOUND_HUGE;
-
- /* Intersect the members bounding boxes */
-
- for (Sib = Quadric->Clip; Sib != NULL; Sib = Sib->Sibling)
- {
- if (!Test_Inverted(Sib))
- {
- if (Sib->Methods == &Plane_Methods)
- {
- Compute_Plane_Min_Max((PLANE *)Sib, &TmpMin, &TmpMax);
- }
- else
- {
- TmpMin.x = Sib->Bounds.Lower_Left.x;
- TmpMin.y = Sib->Bounds.Lower_Left.y;
- TmpMin.z = Sib->Bounds.Lower_Left.z;
- TmpMax.x = Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x;
- TmpMax.y = Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y;
- TmpMax.z = Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z;
- }
- Min.x = max(Min.x, TmpMin.x);
- Min.y = max(Min.y, TmpMin.y);
- Min.z = max(Min.z, TmpMin.z);
- Max.x = min(Max.x, TmpMax.x);
- Max.y = min(Max.y, TmpMax.y);
- Max.z = min(Max.z, TmpMax.z);
- }
- }
-
- ClipMin = Min;
- ClipMax = Max;
- }
-
- /* Get coefficients of 'normal' form: kx*x*x + ky*y*y + kz*z*z + k */
-
- kx = Quadric->Square_Terms.x;
- ky = Quadric->Square_Terms.y;
- kz = Quadric->Square_Terms.z;
- k = Quadric->Constant;
-
- /* We want kx to be non-negative */
-
- if (kx < 0.0)
- {
- kx = -kx;
- ky = -ky;
- kz = -kz;
- k = -k;
- }
-
- /*************************************************************
-
- Check for ellipsoid
-
- x*x y*y z*z
- ----- + ----- + ----- - 1 = 0
- a*a b*b c*c
-
- *************************************************************/
-
- if ((kx > 0.0) && (ky > 0.0) && (kz > 0.0) && (k < 0.0))
- {
- FoundEllipsoid++;
-
- a = sqrt(-k/kx);
- b = sqrt(-k/ky);
- c = sqrt(-k/kz);
-
- NewMin.x = -a;
- NewMin.y = -b;
- NewMin.z = -c;
- NewMax.x = a;
- NewMax.y = b;
- NewMax.z = c;
- }
-
- /*************************************************************
-
- Check for cylinder (x-axis)
-
- y*y z*z
- ----- + ----- - 1 = 0
- b*b c*c
-
- *************************************************************/
-
- if ((kx == 0.0) && (ky > 0.0) && (kz > 0.0) && (k < 0.0))
- {
- FoundCylinder++;
-
- b = sqrt(-k/ky);
- c = sqrt(-k/kz);
-
- NewMin.y = -b;
- NewMin.z = -c;
- NewMax.y = b;
- NewMax.z = c;
- }
-
- /*************************************************************
-
- Check for cylinder (y-axis)
-
- x*x z*z
- ----- + ----- - 1 = 0
- a*a c*c
-
- *************************************************************/
-
- if ((kx > 0.0) && (ky == 0.0) && (kz > 0.0) && (k < 0.0))
- {
- FoundCylinder++;
-
- a = sqrt(-k/kx);
- c = sqrt(-k/kz);
-
- NewMin.x = -a;
- NewMin.z = -c;
- NewMax.x = a;
- NewMax.z = c;
- }
-
- /*************************************************************
-
- Check for cylinder (z-axis)
-
- x*x y*y
- ----- + ----- - 1 = 0
- a*a b*b
-
- *************************************************************/
-
- if ((kx > 0.0) && (ky > 0.0) && (kz == 0.0) && (k < 0.0))
- {
- FoundCylinder++;
-
- a = sqrt(-k/kx);
- b = sqrt(-k/ky);
-
- NewMin.x = -a;
- NewMin.y = -b;
- NewMax.x = a;
- NewMax.y = b;
- }
-
- /*************************************************************
-
- Check for cone (x-axis)
-
- x*x y*y z*z
- ----- - ----- - ----- = 0
- a*a b*b c*c
-
- *************************************************************/
-
- if ((kx > 0.0) && (ky < 0.0) && (kz < 0.0) && (k == 0.0))
- {
- FoundCone++;
-
- a = sqrt(1.0/kx);
- b = sqrt(-1.0/ky);
- c = sqrt(-1.0/kz);
-
- /* Get radii for lower x value */
-
- x = ClipMin.x;
-
- ry1 = fabs(x * b / a);
- rz1 = fabs(x * c / a);
-
- /* Get radii for upper x value */
-
- x = ClipMax.x;
-
- ry2 = fabs(x * b / a);
- rz2 = fabs(x * c / a);
-
- ry = max(ry1, ry2);
- rz = max(rz1, rz2);
-
- NewMin.y = -ry;
- NewMin.z = -rz;
- NewMax.y = ry;
- NewMax.z = rz;
- }
-
- /*************************************************************
-
- Check for cone (y-axis)
-
- x*x y*y z*z
- ----- - ----- + ----- = 0
- a*a b*b c*c
-
- *************************************************************/
-
- if ((kx > 0.0) && (ky < 0.0) && (kz > 0.0) && (k == 0.0))
- {
- FoundCone++;
-
- a = sqrt(1.0/kx);
- b = sqrt(-1.0/ky);
- c = sqrt(1.0/kz);
-
- /* Get radii for lower y value */
-
- y = ClipMin.y;
-
- rx1 = fabs(y * a / b);
- rz1 = fabs(y * c / b);
-
- /* Get radii for upper y value */
-
- y = ClipMax.y;
-
- rx2 = fabs(y * a / b);
- rz2 = fabs(y * c / b);
-
- rx = max(rx1, rx2);
- rz = max(rz1, rz2);
-
- NewMin.x = -rx;
- NewMin.z = -rz;
- NewMax.x = rx;
- NewMax.z = rz;
- }
-
- /*************************************************************
-
- Check for cone (z-axis)
-
- x*x y*y z*z
- ----- + ----- - ----- = 0
- a*a b*b c*c
-
- *************************************************************/
-
- if ((kx > 0.0) && (ky > 0.0) && (kz < 0.0) && (k == 0.0))
- {
- FoundCone++;
-
- a = sqrt(1.0/kx);
- b = sqrt(1.0/ky);
- c = sqrt(-1.0/kz);
-
- /* Get radii for lower z value */
-
- z = ClipMin.z;
-
- rx1 = fabs(z * a / c);
- ry1 = fabs(z * b / c);
-
- /* Get radii for upper z value */
-
- z = ClipMax.z;
-
- rx2 = fabs(z * a / c);
- ry2 = fabs(z * b / c);
-
- rx = max(rx1, rx2);
- ry = max(ry1, ry2);
-
- NewMin.x = -rx;
- NewMin.y = -ry;
- NewMax.x = rx;
- NewMax.y = ry;
- }
-
- /* Intersect clipping object's and quadric's bounding boxes */
-
- if (Quadric->Clip != NULL)
- {
- Min.x = max(NewMin.x, ClipMin.x);
- Min.y = max(NewMin.y, ClipMin.y);
- Min.z = max(NewMin.z, ClipMin.z);
-
- Max.x = min(NewMax.x, ClipMax.x);
- Max.y = min(NewMax.y, ClipMax.y);
- Max.z = min(NewMax.z, ClipMax.z);
-
- NewMin = Min;
- NewMax = Max;
- }
-
- /* Use old or new bounding box? */
-
- New_Volume = (NewMax.x - NewMin.x) *
- (NewMax.y - NewMin.y) *
- (NewMax.z - NewMin.z);
-
- BOUNDS_VOLUME(Old_Volume, Old);
-
- if (New_Volume < Old_Volume)
- {
- Quadric->Bounds.Lower_Left = NewMin;
- VSub (Quadric->Bounds.Lengths, NewMax, NewMin);
-
- /* Beware of lengths too large */
-
- if (Quadric->Bounds.Lengths.x > CRITICAL_LENGTH)
- {
- Quadric->Bounds.Lower_Left.x = -BOUND_HUGE/2;
- Quadric->Bounds.Lengths.x = BOUND_HUGE;
- }
- if (Quadric->Bounds.Lengths.y > CRITICAL_LENGTH)
- {
- Quadric->Bounds.Lower_Left.y = -BOUND_HUGE/2;
- Quadric->Bounds.Lengths.y = BOUND_HUGE;
- }
- if (Quadric->Bounds.Lengths.z > CRITICAL_LENGTH)
- {
- Quadric->Bounds.Lower_Left.z = -BOUND_HUGE/2;
- Quadric->Bounds.Lengths.z = BOUND_HUGE;
- }
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION : Compute_Plane_Min_Max
- *
- * ARGUMENTS : Plane - Plane
- * Min, Max - Vectors containing plane's dimensions
- *
- * MODIFIED ARGS : Min, Max
- *
- * RETURN VALUE : none
- *
- * AUTHOR : Dieter Bayer, May 1994
- *
- * DESCRIPTION
- *
- * Compute min/max vectors for planes perpendicular to an axis.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- void Compute_Plane_Min_Max(Plane, Min, Max)
- PLANE *Plane;
- VECTOR *Min, *Max;
- {
- DBL d;
- VECTOR N;
-
- N = Plane->Normal_Vector;
- d = -Plane->Distance;
-
- Min->x = Min->y = Min->z = -BOUND_HUGE/2;
- Max->x = Max->y = Max->z = BOUND_HUGE/2;
-
- /* y-z-plane */
-
- if (fabs(1.0 - fabs(N.x)) < EPSILON)
- {
- if (N.x > 0.0)
- {
- Max->x = d;
- }
- else
- {
- Min->x = -d;
- }
- }
-
- /* x-z-plane */
-
- if (fabs(1.0 - fabs(N.y)) < EPSILON)
- {
- if (N.y > 0.0)
- {
- Max->y = d;
- }
- else
- {
- Min->y = -d;
- }
- }
-
- /* x-y-plane */
-
- if (fabs(1.0 - fabs(N.z)) < EPSILON)
- {
- if (N.z > 0.0)
- {
- Max->z = d;
- }
- else
- {
- Min->z = -d;
- }
- }
- }
-
-
-
- #endif
-