Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / csg.c
blob4c825cc4b642b6d71ee47346e5da66b50d2c6982
1 /****************************************************************************
2 * csg.c
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 *****************************************************************************/
24 #include "frame.h"
25 #include "povray.h"
26 #include "vector.h"
27 #include "povproto.h"
28 #include "bbox.h"
29 #include "csg.h"
30 #include "hfield.h"
31 #include "matrices.h"
32 #include "objects.h"
33 #include "planes.h"
34 #include "quadrics.h"
38 /*****************************************************************************
39 * Local preprocessor defines
40 ******************************************************************************/
45 /*****************************************************************************
46 * Static functions
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 /*****************************************************************************
65 * Local variables
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 /*****************************************************************************
99 * FUNCTION
101 * All_CSG_Union_Intersections
103 * INPUT
105 * OUTPUT
107 * RETURNS
109 * AUTHOR
111 * POV-Ray Team
113 * DESCRIPTION
117 * CHANGES
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)
125 int Found;
126 OBJECT *Current_Sib, *Clip;
127 ISTACK *Local_Stack;
128 INTERSECTION *Sibling_Intersection;
130 Increase_Counter(stats[Ray_CSG_Union_Tests]);
132 Found = FALSE;
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))
144 Found = TRUE;
149 else
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);
165 Found = TRUE;
172 close_istack (Local_Stack);
175 if (Found)
177 Increase_Counter(stats[Ray_CSG_Union_Tests_Succeeded]);
180 return (Found);
185 /*****************************************************************************
187 * FUNCTION
189 * All_CSG_Intersection_Intersections
191 * INPUT
193 * OUTPUT
195 * RETURNS
197 * AUTHOR
199 * POV-Ray Team
201 * DESCRIPTION
205 * CHANGES
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;
215 ISTACK *Local_Stack;
216 INTERSECTION *Sibling_Intersection;
218 Increase_Counter(stats[Ray_CSG_Intersection_Tests]);
220 Local_Stack = open_istack ();
222 Found = FALSE;
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)
232 Maybe_Found = TRUE;
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))
240 Maybe_Found = FALSE;
242 break;
247 if (Maybe_Found)
249 if (Point_In_Clip (Sibling_Intersection->IPoint, Object->Clip))
251 push_copy(Depth_Stack, Sibling_Intersection);
253 Found = TRUE;
261 close_istack (Local_Stack);
263 if (Found)
265 Increase_Counter(stats[Ray_CSG_Intersection_Tests_Succeeded]);
268 return (Found);
273 /*****************************************************************************
275 * FUNCTION
277 * All_CSG_Merge_Intersections
279 * INPUT
281 * OUTPUT
283 * RETURNS
285 * AUTHOR
287 * POV-Ray Team
289 * DESCRIPTION
293 * CHANGES
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;
302 OBJECT *Sib1, *Sib2;
303 ISTACK *Local_Stack;
304 INTERSECTION *Sibling_Intersection;
306 Increase_Counter(stats[Ray_CSG_Merge_Tests]);
308 Found = FALSE;
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))
322 inside_flag = TRUE;
324 for (Sib2 = ((CSG *)Object)->Children; Sib2 != NULL && inside_flag == TRUE; Sib2 = Sib2->Sibling)
326 if (Sib1 != Sib2)
328 if (Inside_Object(Sibling_Intersection->IPoint, Sib2))
330 inside_flag = FALSE;
335 if (inside_flag == TRUE)
337 Found = TRUE;
339 push_copy (Depth_Stack, Sibling_Intersection);
347 close_istack (Local_Stack);
349 if (Found)
351 Increase_Counter(stats[Ray_CSG_Merge_Tests_Succeeded]);
354 return (Found);
359 /*****************************************************************************
361 * FUNCTION
363 * Inside_CSG_Union
365 * INPUT
367 * OUTPUT
369 * RETURNS
371 * AUTHOR
373 * POV-Ray Team
375 * DESCRIPTION
379 * CHANGES
383 ******************************************************************************/
385 static int Inside_CSG_Union (VECTOR IPoint, OBJECT *Object)
387 OBJECT *Current_Sib;
389 for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
391 if (Inside_Object (IPoint, Current_Sib))
393 return (TRUE);
397 return (FALSE);
402 /*****************************************************************************
404 * FUNCTION
406 * Inside_CSG_Intersection
408 * INPUT
410 * OUTPUT
412 * RETURNS
414 * AUTHOR
416 * POV-Ray Team
418 * DESCRIPTION
422 * CHANGES
426 ******************************************************************************/
428 static int Inside_CSG_Intersection (VECTOR IPoint, OBJECT *Object)
430 OBJECT *Current_Sib;
432 for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
434 if (!Inside_Object (IPoint, Current_Sib))
436 return (FALSE);
440 return (TRUE);
445 /*****************************************************************************
447 * FUNCTION
449 * Translate_CSG
451 * INPUT
453 * OUTPUT
455 * RETURNS
457 * AUTHOR
459 * POV-Ray Team
461 * DESCRIPTION
465 * CHANGES
469 ******************************************************************************/
471 static void Translate_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
473 OBJECT *Sib;
475 for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
477 Translate_Object(Sib, Vector, Trans);
480 Recompute_BBox(&Object->BBox, Trans);
485 /*****************************************************************************
487 * FUNCTION
489 * Rotate_CSG
491 * INPUT
493 * OUTPUT
495 * RETURNS
497 * AUTHOR
499 * POV-Ray Team
501 * DESCRIPTION
505 * CHANGES
509 ******************************************************************************/
511 static void Rotate_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
513 OBJECT *Sib;
515 for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
517 Rotate_Object(Sib, Vector, Trans);
520 Recompute_BBox(&Object->BBox, Trans);
525 /*****************************************************************************
527 * FUNCTION
529 * Scale_CSG
531 * INPUT
533 * OUTPUT
535 * RETURNS
537 * AUTHOR
539 * POV-Ray Team
541 * DESCRIPTION
545 * CHANGES
549 ******************************************************************************/
551 static void Scale_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
553 OBJECT *Sib;
555 for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
557 Scale_Object(Sib, Vector, Trans);
560 Recompute_BBox(&Object->BBox, Trans);
565 /*****************************************************************************
567 * FUNCTION
569 * Transform_CSG
571 * INPUT
573 * OUTPUT
575 * RETURNS
577 * AUTHOR
579 * POV-Ray Team
581 * DESCRIPTION
585 * CHANGES
589 ******************************************************************************/
591 static void Transform_CSG (OBJECT *Object, TRANSFORM *Trans)
593 OBJECT *Sib;
595 for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
597 Transform_Object (Sib, Trans);
600 Recompute_BBox(&Object->BBox, Trans);
605 /*****************************************************************************
607 * FUNCTION
609 * Invert_CSG_Union
611 * INPUT
613 * OUTPUT
615 * RETURNS
617 * AUTHOR
619 * POV-Ray Team
621 * DESCRIPTION
625 * CHANGES
629 ******************************************************************************/
631 static void Invert_CSG_Union (OBJECT *Object)
633 OBJECT *Sib;
635 Object->Methods = &CSG_Intersection_Methods;
637 for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
639 Invert_Object (Sib);
642 Invert_Flag(Object, INVERTED_FLAG);
647 /*****************************************************************************
649 * FUNCTION
651 * Invert_CSG_Intersection
653 * INPUT
655 * OUTPUT
657 * RETURNS
659 * AUTHOR
661 * POV-Ray Team
663 * DESCRIPTION
667 * CHANGES
671 ******************************************************************************/
673 static void Invert_CSG_Intersection (OBJECT *Object)
675 OBJECT *Sib;
677 Object->Methods = &CSG_Merge_Methods;
679 for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
681 Invert_Object (Sib);
684 Invert_Flag(Object, INVERTED_FLAG);
689 /*****************************************************************************
691 * FUNCTION
693 * Create_CSG_Union
695 * INPUT
697 * OUTPUT
699 * RETURNS
701 * AUTHOR
703 * POV-Ray Team
705 * DESCRIPTION
709 * CHANGES
713 ******************************************************************************/
715 CSG *Create_CSG_Union ()
717 CSG *New;
719 New = (CSG *)POV_MALLOC(sizeof (CSG), "union");
721 INIT_OBJECT_FIELDS(New, UNION_OBJECT, &CSG_Union_Methods)
723 New->Children = NULL;
725 return (New);
730 /*****************************************************************************
732 * FUNCTION
734 * Create_CSG_Merge
736 * INPUT
738 * OUTPUT
740 * RETURNS
742 * AUTHOR
744 * POV-Ray Team
746 * DESCRIPTION
750 * CHANGES
754 ******************************************************************************/
756 CSG *Create_CSG_Merge ()
758 CSG *New;
760 New = (CSG *)POV_MALLOC(sizeof (CSG), "merge");
762 INIT_OBJECT_FIELDS(New, MERGE_OBJECT, &CSG_Merge_Methods)
764 New->Children = NULL;
766 return (New);
771 /*****************************************************************************
773 * FUNCTION
775 * Create_CSG_Intersection
777 * INPUT
779 * OUTPUT
781 * RETURNS
783 * AUTHOR
785 * POV-Ray Team
787 * DESCRIPTION
791 * CHANGES
795 ******************************************************************************/
797 CSG *Create_CSG_Intersection ()
799 CSG *New;
801 New = (CSG *)POV_MALLOC(sizeof (CSG), "intersection");
803 INIT_OBJECT_FIELDS(New, INTERSECTION_OBJECT, &CSG_Intersection_Methods)
805 New->Children = NULL;
807 return (New);
812 /*****************************************************************************
814 * FUNCTION
816 * Copy_CSG
818 * INPUT
820 * OUTPUT
822 * RETURNS
824 * AUTHOR
826 * POV-Ray Team
828 * DESCRIPTION
832 * CHANGES
836 ******************************************************************************/
838 static CSG *Copy_CSG (OBJECT *Object)
840 CSG *New;
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;
863 Prev_Sib = New_Sib;
866 return (New);
871 /*****************************************************************************
873 * FUNCTION
875 * Destroy_CSG
877 * INPUT
879 * OUTPUT
881 * RETURNS
883 * AUTHOR
885 * POV-Ray Team
887 * DESCRIPTION
891 * CHANGES
895 ******************************************************************************/
897 static void Destroy_CSG (OBJECT *Object)
899 Destroy_Object (((CSG *) Object)->Children);
901 POV_FREE (Object);
906 /*****************************************************************************
908 * FUNCTION
910 * Compute_CSG_BBox
912 * INPUT
914 * OUTPUT
916 * RETURNS
918 * AUTHOR
920 * POV-Ray Team
922 * DESCRIPTION
926 * CHANGES
928 * Sep 1994 : Improved bounding of quadrics used in CSG intersections. [DB]
930 ******************************************************************************/
932 void Compute_CSG_BBox (OBJECT *Object)
934 int i, count;
935 DBL Old_Volume, New_Volume;
936 VECTOR NewMin, NewMax, TmpMin, TmpMax, Min, Max;
937 OBJECT *Sib;
938 QUADRIC **Quadrics;
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);
950 count = 0;
952 Quadrics = NULL;
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;
970 else
972 if (Sib->Methods == &Plane_Methods)
974 Compute_Plane_Min_Max((PLANE *)Sib, TmpMin, TmpMax);
976 else
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)
1012 POV_FREE(Quadrics);
1015 else
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");
1039 else
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);