예제 #1
0
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);
}
예제 #2
0
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);
}