Пример #1
0
// Create a bounding box hierarchy from a given list of finite and
// infinite elements. Each element consists of
//
// - an infinite flag
// - a bounding box enclosing the element
// - a pointer to the structure representing the element (e.g an object)
void Build_BBox_Tree(BBOX_TREE **Root, size_t numOfFiniteObjects, BBOX_TREE **&Finite, size_t numOfInfiniteObjects, BBOX_TREE **Infinite, size_t& maxfinitecount)
{
    ptrdiff_t low, high;
    BBOX_TREE *cd, *root;

    // This is a resonable guess at the number of finites needed.
    // This array will be reallocated as needed if it isn't.
    maxfinitecount = 2 * numOfFiniteObjects;

    // Now do a sort on the objects, with the end result being
    // a tree of objects sorted along the x, y, and z axes.
    if(numOfFiniteObjects > 0)
    {
        low = 0;
        high = numOfFiniteObjects;

        while(sort_and_split(Root, Finite, &numOfFiniteObjects, low, high, maxfinitecount) == 0)
        {
            low = high;
            high = numOfFiniteObjects;
        }

        // Move infinite objects in the first leaf of Root.
        if(numOfInfiniteObjects > 0)
        {
            root = *Root;
            root->Node = reinterpret_cast<BBOX_TREE **>(POV_REALLOC(root->Node, (root->Entries + 1) * sizeof(BBOX_TREE *), "composite"));
            POV_MEMMOVE(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *));
            root->Entries++;
            cd = create_bbox_node(numOfInfiniteObjects);
            for(size_t i = 0; i < numOfInfiniteObjects; i++)
                cd->Node[i] = Infinite[i];

            calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects);
            root->Node[0] = cd;
            calc_bbox(&(root->BBox), root->Node, 0, root->Entries);

            // Root and first node are infinite.
            root->Infinite = true;
            root->Node[0]->Infinite = true;
        }
    }
    else
    {
        // There are no finite objects and no Root was created.
        // Create it now and put all infinite objects into it.

        if(numOfInfiniteObjects > 0)
        {
            cd = create_bbox_node(numOfInfiniteObjects);
            for(size_t i = 0; i < numOfInfiniteObjects; i++)
                cd->Node[i] = Infinite[i];
            calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects);
            *Root = cd;
            (*Root)->Infinite = true;
        }
    }
}
Пример #2
0
void Build_Bounding_Slabs(BBOX_TREE **Root)
{
  long i, iFinite, iInfinite;
  BBOX_TREE **Finite, **Infinite;
  OBJECT *Object, *Temp;

  /* Count frame level and infinite objects. */

  Object = Frame.Objects;

  numberOfFiniteObjects = numberOfInfiniteObjects = numberOfLightSources = 0;

  while (Object != NULL)
  {
    if (Object->Type & LIGHT_SOURCE_OBJECT)
    {
      Temp = ((LIGHT_SOURCE *)Object)->Children;
      numberOfLightSources++;
    }
    else
    {
      Temp = Object;
    }

    if (Temp != NULL)
    {
      if (Test_Flag(Temp, INFINITE_FLAG))
      {
        numberOfInfiniteObjects++;
      }
      else
      {
        numberOfFiniteObjects++;
      }
    }

    Object = Object->Sibling;
  }

  /* If bounding boxes aren't used we can return. */

  if (!opts.Use_Slabs ||
      !(numberOfFiniteObjects + numberOfInfiniteObjects >= opts.BBox_Threshold) ||
      (numberOfFiniteObjects + numberOfInfiniteObjects < 1))
  {
    opts.Use_Slabs = false; 

    return;
  }

  opts.Use_Slabs = true;

  /*
   * This is a resonable guess at the number of finites needed.
   * This array will be reallocated as needed if it isn't.
   */

  maxfinitecount = 2 * numberOfFiniteObjects;

  /*
   * Now allocate an array to hold references to these finites and
   * any new composite objects we may generate.
   */

  Finite = Infinite = NULL;

  if (numberOfFiniteObjects > 0)
  {
    Finite = (BBOX_TREE **)POV_MALLOC(maxfinitecount*sizeof(BBOX_TREE *), "bounding boxes");
  }

  /* Create array to hold pointers to infinite objects. */

  if (numberOfInfiniteObjects > 0)
  {
    Infinite = (BBOX_TREE **)POV_MALLOC(numberOfInfiniteObjects*sizeof(BBOX_TREE *), "bounding boxes");
  }

  /* Init lists. */

  for (i = 0; i < numberOfFiniteObjects; i++)
  {
    Finite[i] = create_bbox_node(0);
  }

  for (i = 0; i < numberOfInfiniteObjects; i++)
  {
    Infinite[i] = create_bbox_node(0);
  }

  /* Set up finite and infinite object lists. */

  iFinite = iInfinite = 0;

  for (Object = Frame.Objects; Object != NULL; Object = Object->Sibling)
  {
    if (Object->Type & LIGHT_SOURCE_OBJECT)
    {
      Temp = ((LIGHT_SOURCE *)Object)->Children;
    }
    else
    {
      Temp = Object;
    }

    if (Temp != NULL)
    {
      /* Add object to the appropriate list. */

      if (Test_Flag(Temp, INFINITE_FLAG))
      {
        Infinite[iInfinite]->Infinite = true;
        Infinite[iInfinite]->BBox     = Temp->BBox;
        Infinite[iInfinite]->Node     = (BBOX_TREE **)Temp;

        iInfinite++;
      }
      else
      {
        Finite[iFinite]->BBox = Temp->BBox;
        Finite[iFinite]->Node = (BBOX_TREE **)Temp;

        iFinite++;
      }
    }
  }

  /*
   * Now build the bounding box tree.
   */

  Build_BBox_Tree(Root, numberOfFiniteObjects, Finite, numberOfInfiniteObjects, Infinite);

  /* Get rid of the Finite and Infinite arrays and just use Root. */

  if (Finite != NULL)
  {
    POV_FREE(Finite);
  }

  if (Infinite != NULL)
  {
    POV_FREE(Infinite);
  }
}
Пример #3
0
void Build_BBox_Tree(BBOX_TREE **Root, long numOfFiniteObjects, BBOX_TREE **&Finite, long  numOfInfiniteObjects, BBOX_TREE  **Infinite)
{
  short i;
  long low, high;
  BBOX_TREE *cd, *root;

  /*
   * This is a resonable guess at the number of finites needed.
   * This array will be reallocated as needed if it isn't.
   */

  maxfinitecount = 2 * numOfFiniteObjects;

  /*
   * Now do a sort on the objects, with the end result being
   * a tree of objects sorted along the x, y, and z axes.
   */

  if (numOfFiniteObjects > 0)
  {
    low = 0;
    high = numOfFiniteObjects;

    while (sort_and_split(Root, Finite, &numOfFiniteObjects, low, high) == 0)
    {
      low = high;
      high = numOfFiniteObjects;

      Do_Cooperate(0);
    }

    /* Move infinite objects in the first leaf of Root. */

    if (numOfInfiniteObjects > 0)
    {
      root = (BBOX_TREE *)(*Root);

      root->Node = (BBOX_TREE **)POV_REALLOC(root->Node, (root->Entries + 1) * sizeof(BBOX_TREE *), "composite");

      POV_MEMMOVE(&(root->Node[1]), &(root->Node[0]), root->Entries * sizeof(BBOX_TREE *));

      root->Entries++;

      cd = create_bbox_node(numOfInfiniteObjects);

      for (i = 0; i < numOfInfiniteObjects; i++)
      {
        cd->Node[i] = Infinite[i];
      }

      calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects);

      root->Node[0] = (BBOX_TREE *)cd;

      calc_bbox(&(root->BBox), root->Node, 0, root->Entries);

      /* Root and first node are infinite. */

      root->Infinite = true;

      root->Node[0]->Infinite = true;
    }
  }
  else
  {
    /*
     * There are no finite objects and no Root was created.
     * Create it now and put all infinite objects into it.
     */

    if (numOfInfiniteObjects > 0)
    {
      cd = create_bbox_node(numOfInfiniteObjects);

      for (i = 0; i < numOfInfiniteObjects; i++)
      {
        cd->Node[i] = Infinite[i];
      }

      calc_bbox(&(cd->BBox), Infinite, 0, numOfInfiniteObjects);

      *Root = (BBOX_TREE *)cd;

      (*Root)->Infinite = true;
    }
  }
}
Пример #4
0
static int sort_and_split(BBOX_TREE **Root, BBOX_TREE **&Finite, long *numOfFiniteObjects, long  first, long  last)
{
  BBOX_TREE *cd;
  long size, i, best_loc;
  DBL *area_left, *area_right;
  DBL best_index, new_index;

  Axis = find_axis(Finite, first, last);

  size = last - first;

  if (size <= 0)
  {
    return (1);
  }

  Do_Cooperate(1);

  /*
   * Actually, we could do this faster in several ways. We could use a
   * logn algorithm to find the median along the given axis, and then a
   * linear algorithm to partition along the axis. Oh well.
   */

  QSORT((void *)(&Finite[first]), (unsigned long)size, sizeof(BBOX_TREE *), compboxes);

  /*
   * area_left[] and area_right[] hold the surface areas of the bounding
   * boxes to the left and right of any given point. E.g. area_left[i] holds
   * the surface area of the bounding box containing Finite 0 through i and
   * area_right[i] holds the surface area of the box containing Finite
   * i through size-1.
   */

  area_left = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes");
  area_right = (DBL *)POV_MALLOC(size * sizeof(DBL), "bounding boxes");

  /* Precalculate the areas for speed. */

  build_area_table(Finite, first, last - 1, area_left);
  build_area_table(Finite, last - 1, first, area_right);

  best_index = area_right[0] * (size - 3.0);

  best_loc = -1;

  /*
   * Find the most effective point to split. The best location will be
   * the one that minimizes the function N1*A1 + N2*A2 where N1 and N2
   * are the number of objects in the two groups and A1 and A2 are the
   * surface areas of the bounding boxes of the two groups.
   */

  for (i = 0; i < size - 1; i++)
  {
    new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1];

    if (new_index < best_index)
    {
      best_index = new_index;
      best_loc = i + first;
    }
  }

  POV_FREE(area_left);
  POV_FREE(area_right);

  /*
   * Stop splitting if the BUNCHING_FACTOR is reached or
   * if splitting stops being effective.
   */

  if ((size <= BUNCHING_FACTOR) || (best_loc < 0))
  {
    cd = create_bbox_node(size);
      
    for (i = 0; i < size; i++)
    {
      cd->Node[i] = Finite[first+i];
    }

    calc_bbox(&(cd->BBox), Finite, first, last);

    *Root = (BBOX_TREE *)cd;

    if (*numOfFiniteObjects > maxfinitecount)
    {
      /* Prim array overrun, increase array by 50%. */

      maxfinitecount = 1.5 * maxfinitecount;

      /* For debugging only. */

      Debug_Info("Reallocing Finite to %d\n", maxfinitecount);

      Finite = (BBOX_TREE **)POV_REALLOC(Finite, maxfinitecount * sizeof(BBOX_TREE *), "bounding boxes");
    }

    Finite[*numOfFiniteObjects] = cd;

    (*numOfFiniteObjects)++;

    return (1);
  }
  else
  {
    sort_and_split(Root, Finite, numOfFiniteObjects, first, best_loc + 1);

    sort_and_split(Root, Finite, numOfFiniteObjects, best_loc + 1, last);

    return (0);
  }
}
Пример #5
0
int sort_and_split(BBOX_TREE **Root, BBOX_TREE **&Finite, size_t *numOfFiniteObjects, ptrdiff_t first, ptrdiff_t last, size_t& maxfinitecount)
{
    BBOX_TREE *cd;
    ptrdiff_t size, i, best_loc;
    DBL *area_left, *area_right;
    DBL best_index, new_index;

    int Axis = find_axis(Finite, first, last);
    size = last - first;
    if(size <= 0)
        return (1);

    // Actually, we could do this faster in several ways. We could use a
    // logn algorithm to find the median along the given axis, and then a
    // linear algorithm to partition along the axis. Oh well.

    switch(Axis)
    {
        case X:
            QSORT(reinterpret_cast<void *>(&Finite[first]), size, sizeof(BBOX_TREE *), compboxes<X>);
            break;
        case Y:
            QSORT(reinterpret_cast<void *>(&Finite[first]), size, sizeof(BBOX_TREE *), compboxes<Y>);
            break;
        case Z:
            QSORT(reinterpret_cast<void *>(&Finite[first]), size, sizeof(BBOX_TREE *), compboxes<Z>);
            break;
    }

    // area_left[] and area_right[] hold the surface areas of the bounding
    // boxes to the left and right of any given point. E.g. area_left[i] holds
    // the surface area of the bounding box containing Finite 0 through i and
    // area_right[i] holds the surface area of the box containing Finite
    // i through size-1.

    area_left  = new DBL[size];
    area_right = new DBL[size];

    // Precalculate the areas for speed.
    build_area_table(Finite, first, last - 1, area_left);
    build_area_table(Finite, last - 1, first, area_right);
    best_index = area_right[0] * (size - 3.0);
    best_loc = -1;

    // Find the most effective point to split. The best location will be
    // the one that minimizes the function N1*A1 + N2*A2 where N1 and N2
    // are the number of objects in the two groups and A1 and A2 are the
    // surface areas of the bounding boxes of the two groups.

    for(i = 0; i < size - 1; i++)
    {
        new_index = (i + 1) * area_left[i] + (size - 1 - i) * area_right[i + 1];

        if(new_index < best_index)
        {
            best_index = new_index;
            best_loc = i + first;
        }
    }

    delete[] area_left;
    delete[] area_right;

    // Stop splitting if the BUNCHING_FACTOR is reached or
    // if splitting stops being effective.
    if((size <= BUNCHING_FACTOR) || (best_loc < 0))
    {
        cd = create_bbox_node(size);

        for(i = 0; i < size; i++)
            cd->Node[i] = Finite[first+i];

        calc_bbox(&(cd->BBox), Finite, first, last);
        *Root = cd;
        if(*numOfFiniteObjects >= maxfinitecount)
        {
            // Prim array overrun, increase array by 50%.
            maxfinitecount = 1.5 * maxfinitecount;

            // For debugging only.
            // TODO MESSAGE      Debug_Info("Reallocing Finite to %d\n", maxfinitecount);
            Finite = reinterpret_cast<BBOX_TREE **>(POV_REALLOC(Finite, maxfinitecount * sizeof(BBOX_TREE *), "bounding boxes"));
        }

        Finite[*numOfFiniteObjects] = cd;
        (*numOfFiniteObjects)++;

        return (1);
    }

    sort_and_split(Root, Finite, numOfFiniteObjects, first, best_loc + 1, maxfinitecount);
    sort_and_split(Root, Finite, numOfFiniteObjects, best_loc + 1, last, maxfinitecount);

    return (0);
}
Пример #6
0
void Build_Bounding_Slabs(BBOX_TREE **Root, vector<ObjectPtr>& objects, unsigned int& numberOfFiniteObjects, unsigned int& numberOfInfiniteObjects, unsigned int& numberOfLightSources)
{
    ptrdiff_t iFinite, iInfinite;
    BBOX_TREE **Finite, **Infinite;
    ObjectPtr Temp;
    size_t maxfinitecount = 0;

    // Count frame level and infinite objects.
    numberOfFiniteObjects = numberOfInfiniteObjects = numberOfLightSources = 0;

    for(vector<ObjectPtr>::iterator i(objects.begin()); i != objects.end(); i++)
    {
        if((*i)->Type & LIGHT_SOURCE_OBJECT)
        {
            if((reinterpret_cast<LightSource *>(*i))->children.size() > 0)
            {
                Temp = (reinterpret_cast<LightSource *>(*i))->children[0];
                numberOfLightSources++;
            }
            else
                Temp = NULL;
        }
        else
            Temp = (*i);

        if(Temp != NULL)
        {
            if(Test_Flag(Temp, INFINITE_FLAG))
                numberOfInfiniteObjects++;
            else
                numberOfFiniteObjects++;
        }
    }

    // If bounding boxes aren't used we can return.
    if(numberOfFiniteObjects + numberOfInfiniteObjects < 1)
        return;

    // This is a resonable guess at the number of finites needed.
    // This array will be reallocated as needed if it isn't.
    maxfinitecount = 2 * numberOfFiniteObjects;

    // Now allocate an array to hold references to these finites and
    // any new composite objects we may generate.
    Finite = Infinite = NULL;

    if(numberOfFiniteObjects > 0)
        Finite = new BBOX_TREE* [maxfinitecount];

    // Create array to hold pointers to infinite objects.
    if(numberOfInfiniteObjects > 0)
        Infinite = new BBOX_TREE* [numberOfInfiniteObjects];

    // Init lists.
    for(int i = 0; i < numberOfFiniteObjects; i++)
        Finite[i] = create_bbox_node(0);

    for(int i = 0; i < numberOfInfiniteObjects; i++)
        Infinite[i] = create_bbox_node(0);

    // Set up finite and infinite object lists.
    iFinite = iInfinite = 0;

    for(vector<ObjectPtr>::iterator i(objects.begin()); i != objects.end(); i++)
    {
        if((*i)->Type & LIGHT_SOURCE_OBJECT)
        {
            if((reinterpret_cast<LightSource *>(*i))->children.size() > 0)
                Temp = (reinterpret_cast<LightSource *>(*i))->children[0];
            else
                Temp = NULL;
        }
        else
            Temp = (*i);

        if(Temp != NULL)
        {
            // Add object to the appropriate list.
            if(Test_Flag(Temp, INFINITE_FLAG))
            {
                Infinite[iInfinite]->Infinite = true;
                Infinite[iInfinite]->BBox     = Temp->BBox;
                Infinite[iInfinite]->Node     = reinterpret_cast<BBOX_TREE **>(Temp);

                iInfinite++;
            }
            else
            {
                Finite[iFinite]->BBox = Temp->BBox;
                Finite[iFinite]->Node = reinterpret_cast<BBOX_TREE **>(Temp);

                iFinite++;
            }
        }
    }

    // Now build the bounding box tree.
    Build_BBox_Tree(Root, numberOfFiniteObjects, Finite, numberOfInfiniteObjects, Infinite, maxfinitecount);

    // Get rid of the Finite and Infinite arrays and just use Root.
    if(Finite != NULL)
        delete[] Finite;

    if(Infinite != NULL)
        delete[] Infinite;
}