1 /*****************************************************************************
4 * This module implements the bounding box calculations.
5 * This file was written by Alexander Enzmann. He wrote the code for
6 * POV-Ray's bounding boxes and generously provided us these enhancements.
7 * The box intersection code was further hacked by Eric Haines to speed it up.
9 * Just so everyone knows where this came from, the code is VERY heavily
10 * based on the slab code from Mark VandeWettering's MTV raytracer.
11 * POV-Ray is just joining the crowd of admirers of Mark's contribution to
12 * the public domain. [ARE]
14 * from Persistence of Vision(tm) Ray Tracer
15 * Copyright 1996,1999 Persistence of Vision Team
16 *---------------------------------------------------------------------------
17 * NOTICE: This source code file is provided so that users may experiment
18 * with enhancements to POV-Ray and to port the software to platforms other
19 * than those supported by the POV-Ray Team. There are strict rules under
20 * which you are permitted to use this file. The rules are in the file
21 * named POVLEGAL.DOC which should be distributed with this file.
22 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
23 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
24 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
26 * This program is based on the popular DKB raytracer version 2.12.
27 * DKBTrace was originally written by David K. Buck.
28 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
30 *****************************************************************************/
43 /*****************************************************************************
44 * Local preprocessor defines
45 ******************************************************************************/
47 #define BUNCHING_FACTOR 4
49 /* Initial number of entries in a priority queue. */
51 #define INITIAL_PRIORITY_QUEUE_SIZE 256
55 /*****************************************************************************
57 ******************************************************************************/
61 /*****************************************************************************
63 ******************************************************************************/
65 static BBOX_TREE
*create_bbox_node (int size
);
67 static int find_axis (BBOX_TREE
**Finite
, long first
, long last
);
68 static void calc_bbox (BBOX
*BBox
, BBOX_TREE
**Finite
, long first
, long last
);
69 static void build_area_table (BBOX_TREE
**Finite
, long a
, long b
, DBL
*areas
);
70 static int sort_and_split (BBOX_TREE
**Root
, BBOX_TREE
**Finite
, long *nFinite
, long first
, long last
);
72 static void priority_queue_insert (PRIORITY_QUEUE
*Queue
, DBL Depth
, BBOX_TREE
*Node
);
74 static int CDECL
compboxes (CONST
void *in_a
, CONST
void *in_b
);
77 /*****************************************************************************
79 ******************************************************************************/
81 /* Current axis to sort along. */
85 /* Number of finite elements. */
87 static long maxfinitecount
= 0;
89 /* Priority queue used for frame level bouning box hierarchy. */
91 static PRIORITY_QUEUE
*Frame_Queue
;
93 /* Top node of bounding hierarchy. */
95 BBOX_TREE
*Root_Object
;
99 /*****************************************************************************
103 * Initialize_BBox_Code
117 * Initialize bbox specific variables.
121 * Jul 1995 : Creation.
123 ******************************************************************************/
125 void Initialize_BBox_Code()
127 Frame_Queue
= Create_Priority_Queue(INITIAL_PRIORITY_QUEUE_SIZE
);
132 /*****************************************************************************
136 * Deinitialize_BBox_Code
150 * Deinitialize bbox specific variables.
154 * Jul 1995 : Creation.
156 ******************************************************************************/
158 void Deinitialize_BBox_Code()
160 if (Frame_Queue
!= NULL
)
162 Destroy_Priority_Queue(Frame_Queue
);
170 /*****************************************************************************
174 * Create_Priority_Queue
178 * QSize - initial size of priority queue
184 * PRIORITY_QUEUE * - priority queue
192 * Create a priority queue.
196 * Feb 1995 : Creation.
198 ******************************************************************************/
200 PRIORITY_QUEUE
*Create_Priority_Queue(unsigned QSize
)
204 New
= (PRIORITY_QUEUE
*)POV_MALLOC(sizeof(PRIORITY_QUEUE
), "priority queue");
206 New
->Queue
= (QELEM
*)POV_MALLOC(QSize
*sizeof(QELEM
), "priority queue");
210 New
->Max_QSize
= QSize
;
217 /*****************************************************************************
221 * Destroy_Priority_Queue
225 * Queue - Priority queue
237 * Destroy a priority queue.
241 * Feb 1995 : Creation.
243 ******************************************************************************/
245 void Destroy_Priority_Queue(PRIORITY_QUEUE
*Queue
)
249 POV_FREE(Queue
->Queue
);
257 /*****************************************************************************
265 * Node - Node to destroy
277 * Recursively destroy a bounding box tree.
283 ******************************************************************************/
285 void Destroy_BBox_Tree(BBOX_TREE
*Node
)
291 if (Node
->Entries
> 0)
293 for (i
= 0; i
< Node
->Entries
; i
++)
295 Destroy_BBox_Tree(Node
->Node
[i
]);
298 POV_FREE(Node
->Node
);
311 /*****************************************************************************
319 * trans - Transformation
323 * bbox - Bounding box
333 * Recalculate a bounding box after a transformation.
339 ******************************************************************************/
341 void Recompute_BBox(BBOX
*bbox
, TRANSFORM
*trans
)
344 VECTOR lower_left
, lengths
, corner
;
352 Assign_BBox_Vect(lower_left
, bbox
->Lower_Left
);
353 Assign_BBox_Vect(lengths
, bbox
->Lengths
);
355 Make_Vector(mins
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
356 Make_Vector(maxs
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
358 for (i
= 1; i
<= 8; i
++)
360 Assign_Vector(corner
, lower_left
);
362 corner
[X
] += ((i
& 1) ? lengths
[X
] : 0.0);
363 corner
[Y
] += ((i
& 2) ? lengths
[Y
] : 0.0);
364 corner
[Z
] += ((i
& 4) ? lengths
[Z
] : 0.0);
366 MTransPoint(corner
, corner
, trans
);
368 if (corner
[X
] < mins
[X
]) { mins
[X
] = corner
[X
]; }
369 if (corner
[X
] > maxs
[X
]) { maxs
[X
] = corner
[X
]; }
370 if (corner
[Y
] < mins
[Y
]) { mins
[Y
] = corner
[Y
]; }
371 if (corner
[Y
] > maxs
[Y
]) { maxs
[Y
] = corner
[Y
]; }
372 if (corner
[Z
] < mins
[Z
]) { mins
[Z
] = corner
[Z
]; }
373 if (corner
[Z
] > maxs
[Z
]) { maxs
[Z
] = corner
[Z
]; }
376 /* Clip bounding box at the largest allowed bounding box. */
378 if (mins
[X
] < -BOUND_HUGE
/ 2) { mins
[X
] = -BOUND_HUGE
/ 2; }
379 if (mins
[Y
] < -BOUND_HUGE
/ 2) { mins
[Y
] = -BOUND_HUGE
/ 2; }
380 if (mins
[Z
] < -BOUND_HUGE
/ 2) { mins
[Z
] = -BOUND_HUGE
/ 2; }
381 if (maxs
[X
] > BOUND_HUGE
/ 2) { maxs
[X
] = BOUND_HUGE
/ 2; }
382 if (maxs
[Y
] > BOUND_HUGE
/ 2) { maxs
[Y
] = BOUND_HUGE
/ 2; }
383 if (maxs
[Z
] > BOUND_HUGE
/ 2) { maxs
[Z
] = BOUND_HUGE
/ 2; }
385 Make_BBox_from_min_max(*bbox
, mins
, maxs
);
390 /*****************************************************************************
394 * Recompute_Inverse_BBox
398 * trans - Transformation
402 * bbox - Bounding box
412 * Recalculate a bounding box after a transformation.
418 ******************************************************************************/
420 void Recompute_Inverse_BBox(BBOX
*bbox
, TRANSFORM
*trans
)
423 VECTOR lower_left
, lengths
, corner
;
431 Assign_BBox_Vect(lower_left
, bbox
->Lower_Left
);
432 Assign_BBox_Vect(lengths
, bbox
->Lengths
);
434 Make_Vector(mins
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
435 Make_Vector(maxs
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
437 for (i
= 1; i
<= 8; i
++)
439 Assign_Vector(corner
, lower_left
);
441 corner
[X
] += ((i
& 1) ? lengths
[X
] : 0.0);
442 corner
[Y
] += ((i
& 2) ? lengths
[Y
] : 0.0);
443 corner
[Z
] += ((i
& 4) ? lengths
[Z
] : 0.0);
445 MInvTransPoint(corner
, corner
, trans
);
447 if (corner
[X
] < mins
[X
]) { mins
[X
] = corner
[X
]; }
448 if (corner
[X
] > maxs
[X
]) { maxs
[X
] = corner
[X
]; }
449 if (corner
[Y
] < mins
[Y
]) { mins
[Y
] = corner
[Y
]; }
450 if (corner
[Y
] > maxs
[Y
]) { maxs
[Y
] = corner
[Y
]; }
451 if (corner
[Z
] < mins
[Z
]) { mins
[Z
] = corner
[Z
]; }
452 if (corner
[Z
] > maxs
[Z
]) { maxs
[Z
] = corner
[Z
]; }
455 /* Clip bounding box at the largest allowed bounding box. */
457 if (mins
[X
] < -BOUND_HUGE
/ 2) { mins
[X
] = -BOUND_HUGE
/ 2; }
458 if (mins
[Y
] < -BOUND_HUGE
/ 2) { mins
[Y
] = -BOUND_HUGE
/ 2; }
459 if (mins
[Z
] < -BOUND_HUGE
/ 2) { mins
[Z
] = -BOUND_HUGE
/ 2; }
460 if (maxs
[X
] > BOUND_HUGE
/ 2) { maxs
[X
] = BOUND_HUGE
/ 2; }
461 if (maxs
[Y
] > BOUND_HUGE
/ 2) { maxs
[Y
] = BOUND_HUGE
/ 2; }
462 if (maxs
[Z
] > BOUND_HUGE
/ 2) { maxs
[Z
] = BOUND_HUGE
/ 2; }
464 Make_BBox_from_min_max(*bbox
, mins
, maxs
);
469 /*****************************************************************************
487 * Create a bounding box hierarchy from a given list of finite and
488 * infinite elements. Each element consists of
491 * - a bounding box enclosing the element
492 * - a pointer to the structure representing the element (e.g an object)
496 * Feb 1995 : Creation. (Extracted from Build_Bounding_Slabs)
497 * Sep 1995 : Changed to allow use of memcpy if memmove isn't available. [AED]
498 * Jul 1996 : Changed to use POV_MEMMOVE, which can be memmove or pov_memmove
500 ******************************************************************************/
502 void Build_BBox_Tree(BBOX_TREE
**Root
, long nFinite
, BBOX_TREE
**Finite
, long nInfinite
, BBOX_TREE
**Infinite
)
506 BBOX_TREE
*cd
, *root
;
509 * This is a resonable guess at the number of finites needed.
510 * This array will be reallocated as needed if it isn't.
513 maxfinitecount
= 2 * nFinite
;
516 * Now do a sort on the objects, with the end result being
517 * a tree of objects sorted along the x, y, and z axes.
525 while (sort_and_split(Root
, Finite
, &nFinite
, low
, high
) == 0)
531 /* Move infinite objects in the first leaf of Root. */
535 root
= (BBOX_TREE
*)(*Root
);
537 root
->Node
= (BBOX_TREE
**)POV_REALLOC(root
->Node
, (root
->Entries
+ 1) * sizeof(BBOX_TREE
*), "composite");
539 POV_MEMMOVE(&(root
->Node
[1]), &(root
->Node
[0]), root
->Entries
* sizeof(BBOX_TREE
*));
543 cd
= create_bbox_node(nInfinite
);
545 for (i
= 0; i
< nInfinite
; i
++)
547 cd
->Node
[i
] = Infinite
[i
];
550 calc_bbox(&(cd
->BBox
), Infinite
, 0, nInfinite
);
552 root
->Node
[0] = (BBOX_TREE
*)cd
;
554 calc_bbox(&(root
->BBox
), root
->Node
, 0, root
->Entries
);
556 /* Root and first node are infinite. */
558 root
->Infinite
= TRUE
;
560 root
->Node
[0]->Infinite
= TRUE
;
566 * There are no finite objects and no Root was created.
567 * Create it now and put all infinite objects into it.
572 cd
= create_bbox_node(nInfinite
);
574 for (i
= 0; i
< nInfinite
; i
++)
576 cd
->Node
[i
] = Infinite
[i
];
579 calc_bbox(&(cd
->BBox
), Infinite
, 0, nInfinite
);
581 *Root
= (BBOX_TREE
*)cd
;
583 (*Root
)->Infinite
= TRUE
;
590 /*****************************************************************************
594 * Build_Bounding_Slabs
608 * Create the bounding box hierarchy for all objects in the scene.
612 * Sep 1994 : Added allocation of priority queue. [DB]
614 * Sep 1994 : Added code to put all infinite objects in the first node
615 * of the root. Thus the hierarchy won't be messed up. [DB]
617 * Sep 1994 : Fixed nIfinite=0 bug. [DB]
619 * Feb 1995 : Moved code to actually build the hierarchy. [DB]
621 ******************************************************************************/
623 void Build_Bounding_Slabs(BBOX_TREE
**Root
)
625 long i
, nFinite
, nInfinite
, iFinite
, iInfinite
;
626 BBOX_TREE
**Finite
, **Infinite
;
627 OBJECT
*Object
, *Temp
;
629 /* Count frame level and infinite objects. */
631 Object
= Frame
.Objects
;
633 nFinite
= nInfinite
= 0;
635 while (Object
!= NULL
)
637 if (Object
->Type
& LIGHT_SOURCE_OBJECT
)
639 Temp
= ((LIGHT_SOURCE
*)Object
)->Children
;
648 if (Test_Flag(Temp
, INFINITE_FLAG
))
658 Object
= Object
->Sibling
;
661 /* We want to know how many objects there are. */
663 Render_Info("\nScene contains %ld frame level objects; %ld infinite.\n",
664 nFinite
+ nInfinite
, nInfinite
);
666 /* If bounding boxes aren't used we can return. */
668 if (!opts
.Use_Slabs
|| !(nFinite
+ nInfinite
>= opts
.BBox_Threshold
))
670 opts
.Use_Slabs
= FALSE
;
675 opts
.Use_Slabs
= TRUE
;
678 * This is a resonable guess at the number of finites needed.
679 * This array will be reallocated as needed if it isn't.
682 maxfinitecount
= 2 * nFinite
;
685 * Now allocate an array to hold references to these finites and
686 * any new composite objects we may generate.
689 Finite
= Infinite
= NULL
;
693 Finite
= (BBOX_TREE
**)POV_MALLOC(maxfinitecount
*sizeof(BBOX_TREE
*), "bounding boxes");
696 /* Create array to hold pointers to infinite objects. */
700 Infinite
= (BBOX_TREE
**)POV_MALLOC(nInfinite
*sizeof(BBOX_TREE
*), "bounding boxes");
705 for (i
= 0; i
< nFinite
; i
++)
707 Finite
[i
] = create_bbox_node(0);
710 for (i
= 0; i
< nInfinite
; i
++)
712 Infinite
[i
] = create_bbox_node(0);
715 /* Set up finite and infinite object lists. */
717 iFinite
= iInfinite
= 0;
719 for (Object
= Frame
.Objects
; Object
!= NULL
; Object
= Object
->Sibling
)
721 if (Object
->Type
& LIGHT_SOURCE_OBJECT
)
723 Temp
= ((LIGHT_SOURCE
*)Object
)->Children
;
732 /* Add object to the appropriate list. */
734 if (Test_Flag(Temp
, INFINITE_FLAG
))
736 Infinite
[iInfinite
]->Infinite
= TRUE
;
737 Infinite
[iInfinite
]->BBox
= Temp
->BBox
;
738 Infinite
[iInfinite
]->Node
= (BBOX_TREE
**)Temp
;
744 Finite
[iFinite
]->BBox
= Temp
->BBox
;
745 Finite
[iFinite
]->Node
= (BBOX_TREE
**)Temp
;
753 * Now build the bounding box tree.
756 Build_BBox_Tree(Root
, nFinite
, Finite
, nInfinite
, Infinite
);
758 /* Get rid of the Finite and Infinite arrays and just use Root. */
765 if (Infinite
!= NULL
)
773 /*****************************************************************************
777 * Destroy_Bounding_Slabs
791 * Destroy the bounding box hierarchy and the priority queue.
795 * Sep 1994 : Added freeing of priority queue. [DB]
797 ******************************************************************************/
799 void Destroy_Bounding_Slabs()
801 if (Root_Object
!= NULL
)
803 Destroy_BBox_Tree(Root_Object
);
811 /*****************************************************************************
815 * Intersect_BBox_Tree
819 * Root - Root node of the bbox tree
824 * Best_Intersection - Nearest intersection found
825 * Best_Object - Nearest object found
829 * int - TRUE if an intersection was found
837 * Intersect a ray with a bounding box tree.
841 * Sep 1994 : Moved priority queue allocation/freeing out of here. [DB]
843 ******************************************************************************/
845 int Intersect_BBox_Tree(BBOX_TREE
*Root
, RAY
*Ray
, INTERSECTION
*Best_Intersection
, OBJECT
**Best_Object
)
851 INTERSECTION New_Intersection
;
853 /* Create the direction vectors for this ray. */
855 Create_Rayinfo(Ray
, &rayinfo
);
857 /* Start with an empty priority queue. */
861 Frame_Queue
->QSize
= 0;
863 #ifdef BBOX_EXTRA_STATS
864 Increase_Counter(stats
[totalQueueResets
]);
867 /* Check top node. */
869 Check_And_Enqueue(Frame_Queue
, Root
, &Root
->BBox
, &rayinfo
);
871 /* Check elements in the priority queue. */
873 while (Frame_Queue
->QSize
)
875 Priority_Queue_Delete(Frame_Queue
, &Depth
, &Node
);
878 * If current intersection is larger than the best intersection found
879 * so far our task is finished, because all other bounding boxes in
880 * the priority queue are further away.
883 if (Depth
> Best_Intersection
->Depth
)
888 /* Check current node. */
892 /* This is a node containing leaves to be checked. */
894 for (i
= 0; i
< Node
->Entries
; i
++)
896 Check_And_Enqueue(Frame_Queue
, Node
->Node
[i
], &Node
->Node
[i
]->BBox
, &rayinfo
);
901 /* This is a leaf so test contained object. */
903 if (Intersection(&New_Intersection
, (OBJECT
*)Node
->Node
, Ray
))
905 if (New_Intersection
.Depth
< Best_Intersection
->Depth
)
907 *Best_Intersection
= New_Intersection
;
909 *Best_Object
= (OBJECT
*)Node
->Node
;
922 /*****************************************************************************
926 * priority_queue_insert
940 * Insert an element in the priority queue.
944 * Sep 1994 : Added code for resizing the priority queue. [DB]
946 ******************************************************************************/
948 static void priority_queue_insert(PRIORITY_QUEUE
*Queue
, DBL Depth
, BBOX_TREE
*Node
)
954 #ifdef BBOX_EXTRA_STATS
955 Increase_Counter(stats
[totalQueues
]);
962 /* Reallocate priority queue if it's too small. */
964 if (size
>= Queue
->Max_QSize
)
966 if (size
>= INT_MAX
/2)
968 Error("Priority queue overflow.\n");
971 #ifdef BBOX_EXTRA_STATS
972 Increase_Counter(stats
[totalQueueResizes
]);
975 Queue
->Max_QSize
*= 2;
977 Queue
->Queue
= (QELEM
*)POV_REALLOC(Queue
->Queue
, Queue
->Max_QSize
*sizeof(QELEM
), "priority queue");
982 List
[size
].Depth
= Depth
;
983 List
[size
].Node
= Node
;
987 while (i
> 1 && List
[i
].Depth
< List
[i
/ 2].Depth
)
991 List
[i
] = List
[i
/ 2];
1001 /*****************************************************************************
1005 * Priority_Queue_Delete
1019 * Get an element from the priority queue.
1021 * NOTE: This element will always be the one closest to the ray origin.
1027 ******************************************************************************/
1029 void Priority_Queue_Delete(PRIORITY_QUEUE
*Queue
, DBL
*Depth
, BBOX_TREE
**Node
)
1035 if (Queue
->QSize
== 0)
1037 Error("priority queue is empty.\n");
1040 List
= Queue
->Queue
;
1042 *Depth
= List
[1].Depth
;
1043 *Node
= List
[1].Node
;
1045 List
[1] = List
[Queue
->QSize
];
1049 size
= Queue
->QSize
;
1053 while (2 * i
<= (int)size
)
1055 if (2 * i
== (int)size
)
1061 if (List
[2*i
].Depth
< List
[2*i
+1].Depth
)
1071 if (List
[i
].Depth
> List
[j
].Depth
)
1090 /*****************************************************************************
1108 * If a given ray intersect the object's bounding box then add it
1109 * to the priority queue.
1113 * Sep 1994 : Pass bounding box seperately.
1114 * This is needed for the vista/light buffer. [DB]
1116 * Sep 1994 : Added code to insert infinte objects without testing. [DB]
1118 ******************************************************************************/
1120 void Check_And_Enqueue(PRIORITY_QUEUE
*Queue
, BBOX_TREE
*Node
, BBOX
*BBox
, RAYINFO
*rayinfo
)
1127 /* Set intersection depth to -Max_Distance. */
1129 dmin
= -Max_Distance
;
1133 Increase_Counter(stats
[nChecked
]);
1135 if (rayinfo
->nonzero
[X
])
1137 if (rayinfo
->positive
[X
])
1139 dmin
= (BBox
->Lower_Left
[X
] - rayinfo
->slab_num
[X
]) * rayinfo
->slab_den
[X
];
1141 dmax
= dmin
+ (BBox
->Lengths
[X
] * rayinfo
->slab_den
[X
]);
1143 if (dmax
< EPSILON
) return;
1147 dmax
= (BBox
->Lower_Left
[X
] - rayinfo
->slab_num
[X
]) * rayinfo
->slab_den
[X
];
1149 if (dmax
< EPSILON
) return;
1151 dmin
= dmax
+ (BBox
->Lengths
[X
] * rayinfo
->slab_den
[X
]);
1154 if (dmin
> dmax
) return;
1158 if ((rayinfo
->slab_num
[X
] < BBox
->Lower_Left
[X
]) ||
1159 (rayinfo
->slab_num
[X
] > BBox
->Lengths
[X
] + BBox
->Lower_Left
[X
]))
1168 if (rayinfo
->nonzero
[Y
])
1170 if (rayinfo
->positive
[Y
])
1172 tmin
= (BBox
->Lower_Left
[Y
] - rayinfo
->slab_num
[Y
]) * rayinfo
->slab_den
[Y
];
1174 tmax
= tmin
+ (BBox
->Lengths
[Y
] * rayinfo
->slab_den
[Y
]);
1178 tmax
= (BBox
->Lower_Left
[Y
] - rayinfo
->slab_num
[Y
]) * rayinfo
->slab_den
[Y
];
1180 tmin
= tmax
+ (BBox
->Lengths
[Y
] * rayinfo
->slab_den
[Y
]);
1184 * Unwrap the logic - do the dmin and dmax checks only when tmin and
1185 * tmax actually affect anything, also try to escape ASAP. Better
1186 * yet, fold the logic below into the two branches above so as to
1187 * compute only what is needed.
1191 * You might even try tmax < EPSILON first (instead of second) for an
1197 if (tmax
< EPSILON
) return;
1199 /* check bbox only if tmax changes dmax */
1203 if (tmin
> tmax
) return;
1205 /* do this last in case it's not needed! */
1211 if (dmin
> tmax
) return;
1214 /* do this last in case it's not needed! */
1222 if (tmin
> dmax
) return;
1224 /* do this last in case it's not needed! */
1229 /* else nothing needs to happen, since dmin and dmax did not change! */
1234 if ((rayinfo
->slab_num
[Y
] < BBox
->Lower_Left
[Y
]) ||
1235 (rayinfo
->slab_num
[Y
] > BBox
->Lengths
[Y
] + BBox
->Lower_Left
[Y
]))
1241 if (rayinfo
->nonzero
[Z
])
1243 if (rayinfo
->positive
[Z
])
1245 tmin
= (BBox
->Lower_Left
[Z
] - rayinfo
->slab_num
[Z
]) * rayinfo
->slab_den
[Z
];
1247 tmax
= tmin
+ (BBox
->Lengths
[Z
] * rayinfo
->slab_den
[Z
]);
1251 tmax
= (BBox
->Lower_Left
[Z
] - rayinfo
->slab_num
[Z
]) * rayinfo
->slab_den
[Z
];
1253 tmin
= tmax
+ (BBox
->Lengths
[Z
] * rayinfo
->slab_den
[Z
]);
1258 if (tmax
< EPSILON
) return;
1260 /* check bbox only if tmax changes dmax */
1264 if (tmin
> tmax
) return;
1266 /* do this last in case it's not needed! */
1272 if (dmin
> tmax
) return;
1279 if (tmin
> dmax
) return;
1281 /* do this last in case it's not needed! */
1286 /* else nothing needs to happen, since dmin and dmax did not change! */
1291 if ((rayinfo
->slab_num
[Z
] < BBox
->Lower_Left
[Z
]) ||
1292 (rayinfo
->slab_num
[Z
] > BBox
->Lengths
[Z
] + BBox
->Lower_Left
[Z
]))
1298 Increase_Counter(stats
[nEnqueued
]);
1301 priority_queue_insert(Queue
, dmin
, Node
);
1306 /*****************************************************************************
1315 * rayinfo - Rayinfo structure
1329 * Calculate the rayinfo structure for a given ray. It's need for
1330 * intersection the ray with bounding boxes.
1334 * May 1994 : Creation. (Extracted from Intersect_BBox_Tree)
1336 ******************************************************************************/
1338 void Create_Rayinfo(RAY
*Ray
, RAYINFO
*rayinfo
)
1342 /* Create the direction vectors for this ray */
1344 Assign_Vector(rayinfo
->slab_num
, Ray
->Initial
);
1346 if ((rayinfo
->nonzero
[X
] = ((t
= Ray
->Direction
[X
]) != 0.0)) != 0)
1348 rayinfo
->slab_den
[X
] = 1.0 / t
;
1350 rayinfo
->positive
[X
] = (Ray
->Direction
[X
] > 0.0);
1353 if ((rayinfo
->nonzero
[Y
] = ((t
= Ray
->Direction
[Y
]) != 0.0)) != 0)
1355 rayinfo
->slab_den
[Y
] = 1.0 / t
;
1357 rayinfo
->positive
[Y
] = (Ray
->Direction
[Y
] > 0.0);
1360 if ((rayinfo
->nonzero
[Z
] = ((t
= Ray
->Direction
[Z
]) != 0.0)) != 0)
1362 rayinfo
->slab_den
[Z
] = 1.0 / t
;
1364 rayinfo
->positive
[Z
] = (Ray
->Direction
[Z
] > 0.0);
1370 /*****************************************************************************
1378 * size - Number of subnodes
1384 * BBOX_TREE * - New node
1398 ******************************************************************************/
1400 static BBOX_TREE
*create_bbox_node(int size
)
1404 New
= (BBOX_TREE
*)POV_MALLOC(sizeof(BBOX_TREE
), "bounding box node");
1406 New
->Infinite
= FALSE
;
1408 New
->Entries
= size
;
1410 Make_BBox(New
->BBox
, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
1414 New
->Node
= (BBOX_TREE
**)POV_MALLOC(size
*sizeof(BBOX_TREE
*), "bounding box node");
1426 /*****************************************************************************
1434 * in_a, in_b - Elements to compare
1440 * int - result of comparison
1452 * Sep 1994 : Removed test for infinite objects because it's obsolete. [DB]
1454 ******************************************************************************/
1456 static int CDECL
compboxes(CONST
void *in_a
, CONST
void *in_b
)
1461 a
= &((*(BBOX_TREE
**)in_a
)->BBox
);
1462 b
= &((*(BBOX_TREE
**)in_b
)->BBox
);
1464 am
= 2.0 * a
->Lower_Left
[Axis
] + a
->Lengths
[Axis
];
1465 bm
= 2.0 * b
->Lower_Left
[Axis
] + b
->Lengths
[Axis
];
1486 /*****************************************************************************
1494 * Finite - Array of finite elements
1495 * first, last - Position of elements
1501 * int - Axis to sort along
1509 * Find the axis along which the elements will be sorted.
1513 * Sep 1994 : Initialize local variable which. [DB]
1515 ******************************************************************************/
1517 static int find_axis(BBOX_TREE
**Finite
, long first
, long last
)
1521 DBL e
, d
= -BOUND_HUGE
;
1525 Make_Vector(mins
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
1526 Make_Vector(maxs
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
1528 for (i
= first
; i
< last
; i
++)
1530 bbox
= &(Finite
[i
]->BBox
);
1532 if (bbox
->Lower_Left
[X
] < mins
[X
])
1534 mins
[X
] = bbox
->Lower_Left
[X
];
1537 if (bbox
->Lower_Left
[X
] + bbox
->Lengths
[X
] > maxs
[X
])
1539 maxs
[X
] = bbox
->Lower_Left
[X
];
1542 if (bbox
->Lower_Left
[Y
] < mins
[Y
])
1544 mins
[Y
] = bbox
->Lower_Left
[Y
];
1547 if (bbox
->Lower_Left
[Y
] + bbox
->Lengths
[Y
] > maxs
[Y
])
1549 maxs
[Y
] = bbox
->Lower_Left
[Y
];
1552 if (bbox
->Lower_Left
[Z
] < mins
[Z
])
1554 mins
[Z
] = bbox
->Lower_Left
[Z
];
1557 if (bbox
->Lower_Left
[Z
] + bbox
->Lengths
[Z
] > maxs
[Z
])
1559 maxs
[Z
] = bbox
->Lower_Left
[Z
];
1563 e
= maxs
[X
] - mins
[X
];
1570 e
= maxs
[Y
] - mins
[Y
];
1577 e
= maxs
[Z
] - mins
[Z
];
1589 /*****************************************************************************
1607 * Calculate the bounding box containing Finite[first] through Finite[last-1].
1613 ******************************************************************************/
1615 static void calc_bbox(BBOX
*BBox
, BBOX_TREE
**Finite
, long first
, long last
)
1624 Make_Vector(bmin
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
1625 Make_Vector(bmax
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
1627 for (i
= first
; i
< last
; i
++)
1629 bbox
= &(Finite
[i
]->BBox
);
1631 tmin
= bbox
->Lower_Left
[X
];
1632 tmax
= tmin
+ bbox
->Lengths
[X
];
1634 if (tmin
< bmin
[X
]) { bmin
[X
] = tmin
; }
1635 if (tmax
> bmax
[X
]) { bmax
[X
] = tmax
; }
1637 tmin
= bbox
->Lower_Left
[Y
];
1638 tmax
= tmin
+ bbox
->Lengths
[Y
];
1640 if (tmin
< bmin
[Y
]) { bmin
[Y
] = tmin
; }
1641 if (tmax
> bmax
[Y
]) { bmax
[Y
] = tmax
; }
1643 tmin
= bbox
->Lower_Left
[Z
];
1644 tmax
= tmin
+ bbox
->Lengths
[Z
];
1646 if (tmin
< bmin
[Z
]) { bmin
[Z
] = tmin
; }
1647 if (tmax
> bmax
[Z
]) { bmax
[Z
] = tmax
; }
1650 Make_BBox_from_min_max(*BBox
, bmin
, bmax
);
1655 /*****************************************************************************
1673 * Generates a table of bound box surface areas.
1679 ******************************************************************************/
1681 static void build_area_table(BBOX_TREE
**Finite
, long a
, long b
, DBL
*areas
)
1685 VECTOR bmin
, bmax
, len
;
1697 Make_Vector(bmin
, BOUND_HUGE
, BOUND_HUGE
, BOUND_HUGE
);
1698 Make_Vector(bmax
, -BOUND_HUGE
, -BOUND_HUGE
, -BOUND_HUGE
);
1700 for (i
= a
; i
!= (b
+ dir
); i
+= dir
)
1702 bbox
= &(Finite
[i
]->BBox
);
1704 tmin
= bbox
->Lower_Left
[X
];
1705 tmax
= tmin
+ bbox
->Lengths
[X
];
1707 if (tmin
< bmin
[X
]) { bmin
[X
] = tmin
; }
1708 if (tmax
> bmax
[X
]) { bmax
[X
] = tmax
; }
1710 tmin
= bbox
->Lower_Left
[Y
];
1711 tmax
= tmin
+ bbox
->Lengths
[Y
];
1713 if (tmin
< bmin
[Y
]) { bmin
[Y
] = tmin
; }
1714 if (tmax
> bmax
[Y
]) { bmax
[Y
] = tmax
; }
1716 tmin
= bbox
->Lower_Left
[Z
];
1717 tmax
= tmin
+ bbox
->Lengths
[Z
];
1719 if (tmin
< bmin
[Z
]) { bmin
[Z
] = tmin
; }
1720 if (tmax
> bmax
[Z
]) { bmax
[Z
] = tmax
; }
1722 VSub(len
, bmax
, bmin
);
1724 areas
[i
- imin
] = len
[X
] * (len
[Y
] + len
[Z
]) + len
[Y
] * len
[Z
];
1730 /*****************************************************************************
1754 ******************************************************************************/
1756 static int sort_and_split(BBOX_TREE
**Root
, BBOX_TREE
**Finite
, long *nFinite
, long first
, long last
)
1759 long size
, i
, best_loc
;
1760 DBL
*area_left
, *area_right
;
1761 DBL best_index
, new_index
;
1763 Axis
= find_axis(Finite
, first
, last
);
1765 size
= last
- first
;
1773 * Actually, we could do this faster in several ways. We could use a
1774 * logn algorithm to find the median along the given axis, and then a
1775 * linear algorithm to partition along the axis. Oh well.
1778 QSORT((void *)(&Finite
[first
]), (unsigned long)size
, sizeof(BBOX_TREE
*), compboxes
);
1781 * area_left[] and area_right[] hold the surface areas of the bounding
1782 * boxes to the left and right of any given point. E.g. area_left[i] holds
1783 * the surface area of the bounding box containing Finite 0 through i and
1784 * area_right[i] holds the surface area of the box containing Finite
1788 area_left
= (DBL
*)POV_MALLOC(size
* sizeof(DBL
), "bounding boxes");
1789 area_right
= (DBL
*)POV_MALLOC(size
* sizeof(DBL
), "bounding boxes");
1791 /* Precalculate the areas for speed. */
1793 build_area_table(Finite
, first
, last
- 1, area_left
);
1794 build_area_table(Finite
, last
- 1, first
, area_right
);
1796 best_index
= area_right
[0] * (size
- 3.0);
1801 * Find the most effective point to split. The best location will be
1802 * the one that minimizes the function N1*A1 + N2*A2 where N1 and N2
1803 * are the number of objects in the two groups and A1 and A2 are the
1804 * surface areas of the bounding boxes of the two groups.
1807 for (i
= 0; i
< size
- 1; i
++)
1809 new_index
= (i
+ 1) * area_left
[i
] + (size
- 1 - i
) * area_right
[i
+ 1];
1811 if (new_index
< best_index
)
1813 best_index
= new_index
;
1814 best_loc
= i
+ first
;
1818 POV_FREE(area_left
);
1819 POV_FREE(area_right
);
1822 * Stop splitting if the BUNCHING_FACTOR is reached or
1823 * if splitting stops being effective.
1826 if ((size
<= BUNCHING_FACTOR
) || (best_loc
< 0))
1828 cd
= create_bbox_node(size
);
1830 for (i
= 0; i
< size
; i
++)
1832 cd
->Node
[i
] = Finite
[first
+i
];
1835 calc_bbox(&(cd
->BBox
), Finite
, first
, last
);
1837 *Root
= (BBOX_TREE
*)cd
;
1839 if (*nFinite
> maxfinitecount
)
1841 /* Prim array overrun, increase array by 50%. */
1843 maxfinitecount
= 1.5 * maxfinitecount
;
1845 /* For debugging only. */
1847 Debug_Info("Reallocing Finite to %d\n", maxfinitecount
);
1849 Finite
= (BBOX_TREE
**)POV_REALLOC(Finite
, maxfinitecount
* sizeof(BBOX_TREE
*), "bounding boxes");
1852 Finite
[*nFinite
] = cd
;
1860 sort_and_split(Root
, Finite
, nFinite
, first
, best_loc
+ 1);
1862 sort_and_split(Root
, Finite
, nFinite
, best_loc
+ 1, last
);