int Intersect_Light_Tree(RAY *Ray, PROJECT_TREE_NODE *Tree, int x, int y, INTERSECTION *Best_Intersection, OBJECT **Best_Object, LIGHT_SOURCE * /*Light_Source*/) { INTERSECTION New_Intersection; unsigned short i; int Found; RAYINFO rayinfo; DBL key; BBOX_TREE *BBox_Node; PROJECT_TREE_NODE *Node; /* If there's no vista tree then return. */ if (Tree == NULL) { return(false); } /* Start with an empty priority queue */ New_Intersection.Object = NULL; VLBuffer_Queue->QSize = 0; Found = false; #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueueResets]); #endif /* Traverse the tree. */ Node_Queue->QSize = 0; /* Create the direction vectors for this ray */ Create_Rayinfo(Ray, &rayinfo); /* Fill the priority queue with all possible candidates */ /* Check root */ Increase_Counter(stats[LBuffer_Tests]); if ((x >= Tree->Project.x1) && (x <= Tree->Project.x2) && (y >= Tree->Project.y1) && (y <= Tree->Project.y2)) { Increase_Counter(stats[LBuffer_Tests_Succeeded]); Node_Queue->Queue[(Node_Queue->QSize)++] = Tree; } /* Loop until queue is empty. */ while (Node_Queue->QSize > 0) { Tree = Node_Queue->Queue[--(Node_Queue->QSize)]; if (Tree->is_leaf) { /* Leaf --> test object's bounding box in 3d */ Check_And_Enqueue(VLBuffer_Queue, ((PROJECT_TREE_LEAF *)Tree)->Node, &((PROJECT_TREE_LEAF *)Tree)->Node->BBox, &rayinfo); } else { /* Check siblings of the node in 2d */ for (i = 0; i < Tree->Entries; i++) { Node = Tree->Entry[i]; Increase_Counter(stats[LBuffer_Tests]); if ((x >= Node->Project.x1) && (x <= Node->Project.x2) && (y >= Node->Project.y1) && (y <= Node->Project.y2)) { Increase_Counter(stats[LBuffer_Tests_Succeeded]); /* Reallocate queues if they're too small. */ Reinitialize_VLBuffer_Code(); /* Add node to node queue */ Node_Queue->Queue[(Node_Queue->QSize)++] = Node; } } } } /* Now test the candidates in the priority queue */ while (VLBuffer_Queue->QSize > 0) { Priority_Queue_Delete(VLBuffer_Queue, &key, &BBox_Node); if (key > Best_Intersection->Depth) { break; } if (Intersection(&New_Intersection, (OBJECT *)BBox_Node->Node, Ray)) { if (New_Intersection.Depth < Best_Intersection->Depth && /* NK Feb 6, 2000 - bugfix */ New_Intersection.Depth > Small_Tolerance) { *Best_Intersection = New_Intersection; *Best_Object = (OBJECT *)BBox_Node->Node; Found = true; } } } return(Found); }
bool Intersect_BBox_Tree(BBOX_TREE *Root, RAY *Ray, INTERSECTION *Best_Intersection, OBJECT **Best_Object, bool shadow_flag) { int i, found; DBL Depth; BBOX_TREE *Node; RAYINFO rayinfo; INTERSECTION New_Intersection; /* Create the direction vectors for this ray. */ Create_Rayinfo(Ray, &rayinfo); /* Start with an empty priority queue. */ New_Intersection.Object = NULL; found = false; Frame_Queue->QSize = 0; #ifdef BBOX_EXTRA_STATS Increase_Counter(stats[totalQueueResets]); #endif /* Check top node. */ Check_And_Enqueue(Frame_Queue, Root, &Root->BBox, &rayinfo); /* Check elements in the priority queue. */ while (Frame_Queue->QSize) { Priority_Queue_Delete(Frame_Queue, &Depth, &Node); /* * If current intersection is larger than the best intersection found * so far our task is finished, because all other bounding boxes in * the priority queue are further away. */ if (Depth > Best_Intersection->Depth) { break; } /* Check current node. */ if (Node->Entries) { /* This is a node containing leaves to be checked. */ for (i = 0; i < Node->Entries; i++) { Check_And_Enqueue(Frame_Queue, Node->Node[i], &Node->Node[i]->BBox, &rayinfo); } } else { /* This is a leaf so test contained object. */ /* Add Object-Ray options [ENB 9/97] */ if ( TEST_RAY_FLAGS_SHADOW((OBJECT *)Node->Node) ) { if (Intersection(&New_Intersection, (OBJECT *)Node->Node, Ray)) { if (New_Intersection.Depth < Best_Intersection->Depth) { *Best_Intersection = New_Intersection; *Best_Object = (OBJECT *)Node->Node; found = true; } } } } } return (found); }