1 /****************************************************************************
4 * This module implements routines for constructive solid geometry.
6 * from Persistence of Vision(tm) Ray Tracer
7 * Copyright 1996,1999 Persistence of Vision Team
8 *---------------------------------------------------------------------------
9 * NOTICE: This source code file is provided so that users may experiment
10 * with enhancements to POV-Ray and to port the software to platforms other
11 * than those supported by the POV-Ray Team. There are strict rules under
12 * which you are permitted to use this file. The rules are in the file
13 * named POVLEGAL.DOC which should be distributed with this file.
14 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
15 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
16 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
18 * This program is based on the popular DKB raytracer version 2.12.
19 * DKBTrace was originally written by David K. Buck.
20 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
22 *****************************************************************************/
38 /*****************************************************************************
39 * Local preprocessor defines
40 ******************************************************************************/
45 /*****************************************************************************
47 ******************************************************************************/
49 static int All_CSG_Union_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
);
50 static int All_CSG_Merge_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
);
51 static int All_CSG_Intersect_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
);
52 static int Inside_CSG_Union (VECTOR point
, OBJECT
*Object
);
53 static int Inside_CSG_Intersection (VECTOR point
, OBJECT
*Object
);
54 static CSG
*Copy_CSG (OBJECT
*Object
);
55 static void Translate_CSG (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
56 static void Rotate_CSG (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
57 static void Scale_CSG (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
58 static void Transform_CSG (OBJECT
*Object
, TRANSFORM
*Trans
);
59 static void Destroy_CSG (OBJECT
*Object
);
60 static void Invert_CSG_Union (OBJECT
*Object
);
61 static void Invert_CSG_Intersection (OBJECT
*Object
);
64 /*****************************************************************************
66 ******************************************************************************/
68 METHODS CSG_Union_Methods
=
70 All_CSG_Union_Intersections
,
71 Inside_CSG_Union
, NULL
/*Normal*/,
72 (COPY_METHOD
)Copy_CSG
,
73 Translate_CSG
, Rotate_CSG
,
74 Scale_CSG
, Transform_CSG
, Invert_CSG_Union
, Destroy_CSG
77 METHODS CSG_Merge_Methods
=
79 All_CSG_Merge_Intersections
,
80 Inside_CSG_Union
, NULL
/*Normal*/,
81 (COPY_METHOD
)Copy_CSG
,
82 Translate_CSG
, Rotate_CSG
,
83 Scale_CSG
, Transform_CSG
, Invert_CSG_Union
, Destroy_CSG
86 METHODS CSG_Intersection_Methods
=
88 All_CSG_Intersect_Intersections
,
89 Inside_CSG_Intersection
, NULL
/*Normal*/,
90 (COPY_METHOD
)Copy_CSG
,
91 Translate_CSG
, Rotate_CSG
,
92 Scale_CSG
, Transform_CSG
, Invert_CSG_Intersection
, Destroy_CSG
97 /*****************************************************************************
101 * All_CSG_Union_Intersections
119 * Sep 1994 : Added code to count intersection tests. [DB]
121 ******************************************************************************/
123 static int All_CSG_Union_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
)
126 OBJECT
*Current_Sib
, *Clip
;
128 INTERSECTION
*Sibling_Intersection
;
130 Increase_Counter(stats
[Ray_CSG_Union_Tests
]);
134 /* Use shortcut if no clip. */
136 if ((Clip
= Object
->Clip
) == NULL
)
138 for (Current_Sib
= ((CSG
*)Object
)->Children
; Current_Sib
!= NULL
; Current_Sib
= Current_Sib
->Sibling
)
140 if (Ray_In_Bound (Ray
, Current_Sib
->Bound
))
142 if (All_Intersections (Current_Sib
, Ray
, Depth_Stack
))
151 Local_Stack
= open_istack();
153 for (Current_Sib
= ((CSG
*)Object
)->Children
; Current_Sib
!= NULL
; Current_Sib
= Current_Sib
->Sibling
)
155 if (Ray_In_Bound (Ray
, Current_Sib
->Bound
))
157 if (All_Intersections (Current_Sib
, Ray
, Local_Stack
))
159 while ((Sibling_Intersection
= pop_entry(Local_Stack
)) != NULL
)
161 if (Point_In_Clip (Sibling_Intersection
->IPoint
, Clip
))
163 push_copy (Depth_Stack
, Sibling_Intersection
);
172 close_istack (Local_Stack
);
177 Increase_Counter(stats
[Ray_CSG_Union_Tests_Succeeded
]);
185 /*****************************************************************************
189 * All_CSG_Intersection_Intersections
207 * Sep 1994 : Added code to count intersection tests. [DB]
209 ******************************************************************************/
211 static int All_CSG_Intersect_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
)
213 int Maybe_Found
, Found
;
214 OBJECT
*Current_Sib
, *Inside_Sib
;
216 INTERSECTION
*Sibling_Intersection
;
218 Increase_Counter(stats
[Ray_CSG_Intersection_Tests
]);
220 Local_Stack
= open_istack ();
224 for (Current_Sib
= ((CSG
*)Object
)->Children
; Current_Sib
!= NULL
; Current_Sib
= Current_Sib
->Sibling
)
226 if (Ray_In_Bound (Ray
, Current_Sib
->Bound
))
228 if (All_Intersections (Current_Sib
, Ray
, Local_Stack
))
230 while ((Sibling_Intersection
= pop_entry(Local_Stack
)) != NULL
)
234 for (Inside_Sib
= ((CSG
*)Object
)->Children
; Inside_Sib
!= NULL
; Inside_Sib
= Inside_Sib
->Sibling
)
236 if (Inside_Sib
!= Current_Sib
)
238 if (!Inside_Object (Sibling_Intersection
->IPoint
, Inside_Sib
))
249 if (Point_In_Clip (Sibling_Intersection
->IPoint
, Object
->Clip
))
251 push_copy(Depth_Stack
, Sibling_Intersection
);
261 close_istack (Local_Stack
);
265 Increase_Counter(stats
[Ray_CSG_Intersection_Tests_Succeeded
]);
273 /*****************************************************************************
277 * All_CSG_Merge_Intersections
295 * Sep 1994 : Added code to count intersection tests. [DB]
297 ******************************************************************************/
299 static int All_CSG_Merge_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
)
301 int Found
, inside_flag
;
304 INTERSECTION
*Sibling_Intersection
;
306 Increase_Counter(stats
[Ray_CSG_Merge_Tests
]);
310 Local_Stack
= open_istack ();
312 for (Sib1
= ((CSG
*)Object
)->Children
; Sib1
!= NULL
; Sib1
= Sib1
->Sibling
)
314 if (Ray_In_Bound (Ray
, Sib1
->Bound
))
316 if (All_Intersections (Sib1
, Ray
, Local_Stack
))
318 while ((Sibling_Intersection
= pop_entry (Local_Stack
)) != NULL
)
320 if (Point_In_Clip (Sibling_Intersection
->IPoint
, Object
->Clip
))
324 for (Sib2
= ((CSG
*)Object
)->Children
; Sib2
!= NULL
&& inside_flag
== TRUE
; Sib2
= Sib2
->Sibling
)
328 if (Inside_Object(Sibling_Intersection
->IPoint
, Sib2
))
335 if (inside_flag
== TRUE
)
339 push_copy (Depth_Stack
, Sibling_Intersection
);
347 close_istack (Local_Stack
);
351 Increase_Counter(stats
[Ray_CSG_Merge_Tests_Succeeded
]);
359 /*****************************************************************************
383 ******************************************************************************/
385 static int Inside_CSG_Union (VECTOR IPoint
, OBJECT
*Object
)
389 for (Current_Sib
= ((CSG
*)Object
)->Children
; Current_Sib
!= NULL
; Current_Sib
= Current_Sib
->Sibling
)
391 if (Inside_Object (IPoint
, Current_Sib
))
402 /*****************************************************************************
406 * Inside_CSG_Intersection
426 ******************************************************************************/
428 static int Inside_CSG_Intersection (VECTOR IPoint
, OBJECT
*Object
)
432 for (Current_Sib
= ((CSG
*)Object
)->Children
; Current_Sib
!= NULL
; Current_Sib
= Current_Sib
->Sibling
)
434 if (!Inside_Object (IPoint
, Current_Sib
))
445 /*****************************************************************************
469 ******************************************************************************/
471 static void Translate_CSG (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
475 for (Sib
= ((CSG
*) Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
477 Translate_Object(Sib
, Vector
, Trans
);
480 Recompute_BBox(&Object
->BBox
, Trans
);
485 /*****************************************************************************
509 ******************************************************************************/
511 static void Rotate_CSG (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
515 for (Sib
= ((CSG
*) Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
517 Rotate_Object(Sib
, Vector
, Trans
);
520 Recompute_BBox(&Object
->BBox
, Trans
);
525 /*****************************************************************************
549 ******************************************************************************/
551 static void Scale_CSG (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
555 for (Sib
= ((CSG
*) Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
557 Scale_Object(Sib
, Vector
, Trans
);
560 Recompute_BBox(&Object
->BBox
, Trans
);
565 /*****************************************************************************
589 ******************************************************************************/
591 static void Transform_CSG (OBJECT
*Object
, TRANSFORM
*Trans
)
595 for (Sib
= ((CSG
*) Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
597 Transform_Object (Sib
, Trans
);
600 Recompute_BBox(&Object
->BBox
, Trans
);
605 /*****************************************************************************
629 ******************************************************************************/
631 static void Invert_CSG_Union (OBJECT
*Object
)
635 Object
->Methods
= &CSG_Intersection_Methods
;
637 for (Sib
= ((CSG
*)Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
642 Invert_Flag(Object
, INVERTED_FLAG
);
647 /*****************************************************************************
651 * Invert_CSG_Intersection
671 ******************************************************************************/
673 static void Invert_CSG_Intersection (OBJECT
*Object
)
677 Object
->Methods
= &CSG_Merge_Methods
;
679 for (Sib
= ((CSG
*)Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
684 Invert_Flag(Object
, INVERTED_FLAG
);
689 /*****************************************************************************
713 ******************************************************************************/
715 CSG
*Create_CSG_Union ()
719 New
= (CSG
*)POV_MALLOC(sizeof (CSG
), "union");
721 INIT_OBJECT_FIELDS(New
, UNION_OBJECT
, &CSG_Union_Methods
)
723 New
->Children
= NULL
;
730 /*****************************************************************************
754 ******************************************************************************/
756 CSG
*Create_CSG_Merge ()
760 New
= (CSG
*)POV_MALLOC(sizeof (CSG
), "merge");
762 INIT_OBJECT_FIELDS(New
, MERGE_OBJECT
, &CSG_Merge_Methods
)
764 New
->Children
= NULL
;
771 /*****************************************************************************
775 * Create_CSG_Intersection
795 ******************************************************************************/
797 CSG
*Create_CSG_Intersection ()
801 New
= (CSG
*)POV_MALLOC(sizeof (CSG
), "intersection");
803 INIT_OBJECT_FIELDS(New
, INTERSECTION_OBJECT
, &CSG_Intersection_Methods
)
805 New
->Children
= NULL
;
812 /*****************************************************************************
836 ******************************************************************************/
838 static CSG
*Copy_CSG (OBJECT
*Object
)
841 OBJECT
*Old_Sib
, *New_Sib
, *Prev_Sib
;
843 New
= (CSG
*)POV_MALLOC(sizeof (CSG
), "csg");
845 *New
= *(CSG
*)Object
;
847 New
->Children
= Prev_Sib
= NULL
;
849 for (Old_Sib
= ((CSG
*)Object
)->Children
; Old_Sib
!= NULL
; Old_Sib
= Old_Sib
->Sibling
)
851 New_Sib
= Copy_Object (Old_Sib
);
853 if (New
->Children
== NULL
)
855 New
->Children
= New_Sib
;
858 if (Prev_Sib
!= NULL
)
860 Prev_Sib
->Sibling
= New_Sib
;
871 /*****************************************************************************
895 ******************************************************************************/
897 static void Destroy_CSG (OBJECT
*Object
)
899 Destroy_Object (((CSG
*) Object
)->Children
);
906 /*****************************************************************************
928 * Sep 1994 : Improved bounding of quadrics used in CSG intersections. [DB]
930 ******************************************************************************/
932 void Compute_CSG_BBox (OBJECT
*Object
)
935 DBL Old_Volume
, New_Volume
;
936 VECTOR NewMin
, NewMax
, TmpMin
, TmpMax
, Min
, Max
;
940 if (Object
->Methods
== &CSG_Intersection_Methods
)
943 * Calculate the bounding box of a CSG intersection
944 * by intersecting the bounding boxes of all children.
947 Make_Vector(NewMin
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
948 Make_Vector(NewMax
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
954 /* Process all children. */
956 for (Sib
= ((CSG
*)Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
958 /* Inverted objects and height fields mustn't be considered */
960 if (!Test_Flag(Sib
, INVERTED_FLAG
) && (Sib
->Methods
!= &HField_Methods
))
962 /* Store quadrics since they'll be processed last. */
964 if (Sib
->Methods
== &Quadric_Methods
)
966 Quadrics
= (QUADRIC
**)POV_REALLOC(Quadrics
, (count
+1)*sizeof(QUADRIC
*), "temporary quadric list");
968 Quadrics
[count
++] = (QUADRIC
*)Sib
;
972 if (Sib
->Methods
== &Plane_Methods
)
974 Compute_Plane_Min_Max((PLANE
*)Sib
, TmpMin
, TmpMax
);
978 Make_min_max_from_BBox(TmpMin
, TmpMax
, Sib
->BBox
);
981 NewMin
[X
] = max(NewMin
[X
], TmpMin
[X
]);
982 NewMin
[Y
] = max(NewMin
[Y
], TmpMin
[Y
]);
983 NewMin
[Z
] = max(NewMin
[Z
], TmpMin
[Z
]);
984 NewMax
[X
] = min(NewMax
[X
], TmpMax
[X
]);
985 NewMax
[Y
] = min(NewMax
[Y
], TmpMax
[Y
]);
986 NewMax
[Z
] = min(NewMax
[Z
], TmpMax
[Z
]);
991 /* Process any quadrics. */
993 for (i
= 0; i
< count
; i
++)
995 Assign_Vector(Min
, NewMin
);
996 Assign_Vector(Max
, NewMax
);
998 Compute_Quadric_BBox(Quadrics
[i
], Min
, Max
);
1000 Make_min_max_from_BBox(TmpMin
, TmpMax
, Quadrics
[i
]->BBox
);
1002 NewMin
[X
] = max(NewMin
[X
], TmpMin
[X
]);
1003 NewMin
[Y
] = max(NewMin
[Y
], TmpMin
[Y
]);
1004 NewMin
[Z
] = max(NewMin
[Z
], TmpMin
[Z
]);
1005 NewMax
[X
] = min(NewMax
[X
], TmpMax
[X
]);
1006 NewMax
[Y
] = min(NewMax
[Y
], TmpMax
[Y
]);
1007 NewMax
[Z
] = min(NewMax
[Z
], TmpMax
[Z
]);
1010 if (Quadrics
!= NULL
)
1017 /* Calculate the bounding box of a CSG merge/union object. */
1019 Make_Vector(NewMin
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
1020 Make_Vector(NewMax
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
1022 for (Sib
= ((CSG
*)Object
)->Children
; Sib
!= NULL
; Sib
= Sib
->Sibling
)
1024 Make_min_max_from_BBox(TmpMin
, TmpMax
, Sib
->BBox
);
1026 NewMin
[X
] = min(NewMin
[X
], TmpMin
[X
]);
1027 NewMin
[Y
] = min(NewMin
[Y
], TmpMin
[Y
]);
1028 NewMin
[Z
] = min(NewMin
[Z
], TmpMin
[Z
]);
1029 NewMax
[X
] = max(NewMax
[X
], TmpMax
[X
]);
1030 NewMax
[Y
] = max(NewMax
[Y
], TmpMax
[Y
]);
1031 NewMax
[Z
] = max(NewMax
[Z
], TmpMax
[Z
]);
1035 if ((NewMin
[X
] > NewMax
[X
]) || (NewMin
[Y
] > NewMax
[Y
]) || (NewMin
[Z
] > NewMax
[Z
]))
1037 Warning(0.0, "Degenerate CSG bounding box (not used!).\n");
1041 New_Volume
= (NewMax
[X
] - NewMin
[X
]) * (NewMax
[Y
] - NewMin
[Y
]) * (NewMax
[Z
] - NewMin
[Z
]);
1043 BOUNDS_VOLUME(Old_Volume
, Object
->BBox
);
1045 if (New_Volume
< Old_Volume
)
1047 Make_BBox_from_min_max(Object
->BBox
, NewMin
, NewMax
);
1049 /* Beware of bounding boxes to large. */
1051 if ((Object
->BBox
.Lengths
[X
] > CRITICAL_LENGTH
) ||
1052 (Object
->BBox
.Lengths
[Y
] > CRITICAL_LENGTH
) ||
1053 (Object
->BBox
.Lengths
[Z
] > CRITICAL_LENGTH
))
1055 Make_BBox(Object
->BBox
, -BOUND_HUGE
/2, -BOUND_HUGE
/2, -BOUND_HUGE
/2,
1056 BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);