home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * csg.c
- *
- * This module implements routines for constructive solid geometry.
- *
- * from Persistence of Vision Raytracer
- * Copyright 1993 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
-
- METHODS CSG_Union_Methods =
- {
- All_CSG_Union_Intersections,
- Inside_CSG_Union, NULL /*Normal*/,
- Copy_CSG,
- Translate_CSG, Rotate_CSG,
- Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
- };
-
- METHODS CSG_Merge_Methods =
- {
- All_CSG_Merge_Intersections,
- Inside_CSG_Union, NULL /*Normal*/,
- Copy_CSG,
- Translate_CSG, Rotate_CSG,
- Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
- };
-
- METHODS CSG_Intersection_Methods =
- {
- All_CSG_Intersect_Intersections,
- Inside_CSG_Intersection, NULL /*Normal*/,
- Copy_CSG,
- Translate_CSG, Rotate_CSG,
- Scale_CSG, Transform_CSG, Invert_CSG_Intersection, Destroy_CSG
- };
-
- extern RAY *VP_Ray;
-
- int All_CSG_Union_Intersections (Object, Ray, Depth_Stack)
- OBJECT *Object;
- RAY *Ray;
- ISTACK *Depth_Stack;
- {
- register int Found;
- OBJECT *Current_Sib, *Clip;
- ISTACK *Local_Stack;
- INTERSECTION *Sibling_Intersection;
-
- Found = FALSE;
-
- if ((Clip = Object->Clip) == NULL) /* Use shortcut if no clip */
- {
- for (Current_Sib = ((CSG *)Object)->Children;
- Current_Sib != NULL ;
- Current_Sib = Current_Sib->Sibling)
- if (Ray_In_Bounds (Ray, Current_Sib->Bound))
- if (All_Intersections (Current_Sib, Ray, Depth_Stack))
- Found = TRUE;
- }
- else
- {
- Local_Stack = open_istack ();
-
- for (Current_Sib = ((CSG *)Object)->Children;
- Current_Sib != NULL ;
- Current_Sib = Current_Sib->Sibling)
- if (Ray_In_Bounds (Ray, Current_Sib->Bound))
- if (All_Intersections (Current_Sib, Ray, Local_Stack))
- while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
- if (Point_In_Clip (&Sibling_Intersection->IPoint, Clip))
- {
- push_copy (Depth_Stack, Sibling_Intersection);
- Found = TRUE;
- }
- close_istack (Local_Stack);
- }
- return (Found);
- }
-
- int All_CSG_Intersect_Intersections (Object, Ray, Depth_Stack)
- OBJECT *Object;
- RAY *Ray;
- ISTACK *Depth_Stack;
- {
- int Maybe_Found, Found;
- OBJECT *Current_Sib, *Inside_Sib;
- ISTACK *Local_Stack;
- INTERSECTION *Sibling_Intersection;
-
- Local_Stack = open_istack ();
-
- Found = FALSE;
-
- for (Current_Sib = ((CSG *)Object)->Children;
- Current_Sib != NULL;
- Current_Sib = Current_Sib->Sibling)
- {
- if (Ray_In_Bounds (Ray, Current_Sib->Bound))
- if (All_Intersections (Current_Sib, Ray, Local_Stack))
- while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
- {
- Maybe_Found = TRUE;
- for (Inside_Sib = ((CSG *)Object)->Children;
- Inside_Sib != NULL;
- Inside_Sib = Inside_Sib->Sibling)
- if (Inside_Sib != Current_Sib)
- if (!Inside_Object (&Sibling_Intersection->IPoint, Inside_Sib))
- {
- Maybe_Found = FALSE;
- break;
- }
- if (Maybe_Found)
- if (Point_In_Clip (&Sibling_Intersection->IPoint, Object->Clip))
- {
- push_copy(Depth_Stack, Sibling_Intersection);
- Found = TRUE;
- }
- }
- }
- close_istack (Local_Stack);
- return (Found);
- }
-
- int All_CSG_Merge_Intersections (Object, Ray, Depth_Stack)
- OBJECT *Object;
- RAY *Ray;
- ISTACK *Depth_Stack;
- {
- register int Found, inside_flag;
- OBJECT *Sib1, *Sib2;
- ISTACK *Local_Stack;
- INTERSECTION *Sibling_Intersection;
-
- Found = FALSE;
-
- Local_Stack = open_istack ();
-
- for (Sib1 = ((CSG *)Object)->Children;
- Sib1 != NULL ;
- Sib1 = Sib1->Sibling)
- if (Ray_In_Bounds (Ray, Sib1->Bound))
- if (All_Intersections (Sib1, Ray, Local_Stack))
- while ((Sibling_Intersection = pop_entry (Local_Stack)) != NULL)
- if (Point_In_Clip (&Sibling_Intersection->IPoint,Object->Clip))
- {
- inside_flag = TRUE;
- for (Sib2 = ((CSG *)Object)->Children;
- Sib2 != NULL && inside_flag == TRUE;
- Sib2 = Sib2->Sibling)
- if (Sib1 != Sib2)
- if (Inside_Object(&Sibling_Intersection->IPoint,Sib2))
- inside_flag = FALSE;
- if (inside_flag == TRUE)
- {
- Found = TRUE;
- push_copy (Depth_Stack, Sibling_Intersection);
- }
- }
- close_istack (Local_Stack);
- return (Found);
- }
-
- int Inside_CSG_Union (IPoint, Object)
- VECTOR *IPoint;
- OBJECT *Object;
- {
- OBJECT *Current_Sib;
-
- for (Current_Sib = ((CSG *)Object)->Children;
- Current_Sib != NULL ;
- Current_Sib = Current_Sib->Sibling)
- if (Inside_Object (IPoint, Current_Sib))
- return (TRUE);
-
- return (FALSE);
- }
-
- int Inside_CSG_Intersection (IPoint, Object)
- OBJECT *Object;
- VECTOR *IPoint;
- {
- OBJECT *Current_Sib;
-
- for (Current_Sib = ((CSG *)Object)->Children;
- Current_Sib != NULL ;
- Current_Sib = Current_Sib->Sibling)
- if (!Inside_Object (IPoint, Current_Sib))
- return (FALSE);
-
- return (TRUE);
- }
-
- void *Copy_CSG (Object)
- OBJECT *Object;
- {
- CSG *New;
- OBJECT *Old_Sib, *New_Sib, *Prev_Sib;
-
- if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
- MAError ("CSG");
-
- New->Children = Prev_Sib = NULL;
-
- for (Old_Sib = ((CSG *)Object)->Children;
- Old_Sib != NULL ;
- Old_Sib = Old_Sib->Sibling)
- {
- New_Sib = Copy_Object (Old_Sib);
-
- if (New->Children == NULL)
- New->Children = New_Sib;
-
- if (Prev_Sib != NULL)
- Prev_Sib->Sibling = New_Sib;
-
- Prev_Sib = New_Sib;
- }
-
- return (New);
- }
-
- void Translate_CSG (Object, Vector)
- OBJECT *Object;
- VECTOR *Vector;
- {
- OBJECT *Sib;
-
- for (Sib = ((CSG *) Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- Translate_Object (Sib, Vector);
- Compute_CSG_Bounds(Object);
- }
-
- void Rotate_CSG (Object, Vector)
- OBJECT *Object;
- VECTOR *Vector;
- {
- OBJECT *Sib;
-
- for (Sib = ((CSG *) Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- Rotate_Object (Sib, Vector);
- Compute_CSG_Bounds(Object);
- }
-
- void Scale_CSG (Object, Vector)
- OBJECT *Object;
- VECTOR *Vector;
- {
- OBJECT *Sib;
-
- for (Sib = ((CSG *) Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- Scale_Object (Sib, Vector);
- Compute_CSG_Bounds(Object);
- }
-
- void Transform_CSG (Object, Trans)
- OBJECT *Object;
- TRANSFORM *Trans;
- {
- OBJECT *Sib;
-
- for (Sib = ((CSG *) Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- Transform_Object (Sib, Trans);
- Compute_CSG_Bounds(Object);
- }
-
- void Destroy_CSG (Object)
- OBJECT *Object;
- {
- Destroy_Object (((CSG *) Object)->Children);
- free (Object);
- }
-
- void Invert_CSG_Union (Object)
- OBJECT *Object;
- {
- OBJECT *Sib;
-
- Object->Methods = &CSG_Intersection_Methods;
-
- for (Sib = ((CSG *)Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- Invert_Object (Sib);
- }
-
- void Invert_CSG_Intersection (Object)
- OBJECT *Object;
- {
- OBJECT *Sib;
-
- Object->Methods = &CSG_Union_Methods;
-
- for (Sib = ((CSG *)Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- Invert_Object (Sib);
- }
-
- CSG *Create_CSG_Union ()
- {
- CSG *New;
-
- if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
- MAError ("union");
-
- INIT_OBJECT_FIELDS(New, UNION_OBJECT, &CSG_Union_Methods)
-
- New->Children = NULL;
- return (New);
- }
-
- CSG *Create_CSG_Merge ()
- {
- CSG *New;
-
- if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
- MAError ("merge");
-
- INIT_OBJECT_FIELDS(New, MERGE_OBJECT, &CSG_Merge_Methods)
-
- New->Children = NULL;
- return (New);
- }
-
- CSG *Create_CSG_Intersection ()
- {
- CSG *New;
-
- if ((New = (CSG *) malloc (sizeof (CSG))) == NULL)
- MAError ("intersection");
-
- INIT_OBJECT_FIELDS(New, INTERSECTION_OBJECT, &CSG_Intersection_Methods)
-
- New->Children = NULL;
- return (New);
- }
-
- void Compute_CSG_Bounds (Object)
- OBJECT *Object;
- {
- VECTOR mins, maxs;
- DBL tmin, tmax;
- OBJECT *Sib;
-
- Make_Vector(&mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
- Make_Vector(&maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
-
- for (Sib = ((CSG *) Object)->Children;
- Sib != NULL ;
- Sib = Sib->Sibling)
- {
- tmin = Sib->Bounds.Lower_Left.x;
- tmax = Sib->Bounds.Lower_Left.x + Sib->Bounds.Lengths.x;
- if (tmin < mins.x) mins.x = tmin;
- if (tmax > maxs.x) maxs.x = tmax;
- tmin = Sib->Bounds.Lower_Left.y;
- tmax = Sib->Bounds.Lower_Left.y + Sib->Bounds.Lengths.y;
- if (tmin < mins.y) mins.y = tmin;
- if (tmax > maxs.y) maxs.y = tmax;
- tmin = Sib->Bounds.Lower_Left.z;
- tmax = Sib->Bounds.Lower_Left.z + Sib->Bounds.Lengths.z;
- if (tmin < mins.z) mins.z = tmin;
- if (tmax > maxs.z) maxs.z = tmax;
- }
- Object->Bounds.Lower_Left = mins;
- VSub(Object->Bounds.Lengths, maxs, mins);
- }
-
-