コード例 #1
0
ファイル: bbox_tree.c プロジェクト: csiga/Eternal-Lands
static __inline__ Uint32 sort_and_split(BBOX_TREE* bbox_tree, Uint32 node, Uint32* index, Uint32 first, Uint32 last)
{
	Uint32 size, i, j, axis[3];
	int best_loc;
	float *area_left, *area_right;
	float best_index, new_index;
#ifdef FASTER_MAP_LOAD
	AABBOX bbox;
#endif

	size = last - first;

	if (size < 1) return -1;

#ifdef FASTER_MAP_LOAD
	find_axis_and_bbox(bbox_tree, first, last, axis, &bbox);
#else
	find_axis(bbox_tree, first, last, axis);
#endif

	best_loc = -1;

	if (size > 8)
	{
		area_left = malloc(size * sizeof(float));
		area_right = malloc(size * sizeof(float));

		for (j = 0; j < 3; j++)
		{
			Axis = axis[j];

			qsort(bbox_tree->items + first, size, sizeof(BBOX_ITEM), compboxes);
			build_area_table(bbox_tree, first, last - 1, area_left);
			build_area_table(bbox_tree, last - 1, first, area_right);

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

			/*
			 * 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;
				}
			}
			if (best_loc >= 0) break;
		}

		free(area_left);
		free(area_right);
	}

#ifdef FASTER_MAP_LOAD
	VAssign(bbox_tree->nodes[node].bbox.bbmin, bbox.bbmin);
	VAssign(bbox_tree->nodes[node].bbox.bbmax, bbox.bbmax);
	VAssign(bbox_tree->nodes[node].orig_bbox.bbmin, bbox.bbmin);
	VAssign(bbox_tree->nodes[node].orig_bbox.bbmax, bbox.bbmax);
#else
	calc_bbox(&bbox_tree->nodes[node].bbox, bbox_tree, first, last);
	VAssign(bbox_tree->nodes[node].orig_bbox.bbmin, bbox_tree->nodes[node].bbox.bbmin);
	VAssign(bbox_tree->nodes[node].orig_bbox.bbmax, bbox_tree->nodes[node].bbox.bbmax);
#endif
	bbox_tree->nodes[node].items_index = first;
	bbox_tree->nodes[node].items_count = size;

	bbox_tree->nodes[node].dynamic_objects.size = 0;
	bbox_tree->nodes[node].dynamic_objects.index = 0;
	bbox_tree->nodes[node].dynamic_objects.items = NULL;

	if (best_loc < 0)
	{
		bbox_tree->nodes[node].nodes[0] = NO_INDEX;
		bbox_tree->nodes[node].nodes[1] = NO_INDEX;
		return 1;
	}
	else
	{
		if (*index+2 >= bbox_tree->nodes_count)
		{
			bbox_tree->nodes_count *= 2;
			bbox_tree->nodes = (BBOX_TREE_NODE*)realloc(bbox_tree->nodes, bbox_tree->nodes_count*sizeof(BBOX_TREE_NODE));
		}
		bbox_tree->nodes[node].nodes[0] = (*index)+0;
		bbox_tree->nodes[node].nodes[1] = (*index)+1;
		*index += 2;
		sort_and_split(bbox_tree, bbox_tree->nodes[node].nodes[0], index, first, best_loc + 1);
		sort_and_split(bbox_tree, bbox_tree->nodes[node].nodes[1], index, best_loc + 1, last);
		return 0;
	}
}
コード例 #2
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);
  }
}
コード例 #3
0
ファイル: bsphere.cpp プロジェクト: acekiller/povray
static int sort_and_split(BSPHERE_TREE **Root, BSPHERE_TREE ***Elements, int *nElem, int first, int last, int& maxelements)
{
	int size, i, best_loc;
	DBL *area_left, *area_right;
	DBL best_index, new_index;
	BSPHERE_TREE *cd;

	int Axis = find_axis(*Elements, 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((void *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements<X>);
			break;
		case Y:
			QSORT((void *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements<Y>);
			break;
		case Z:
			QSORT((void *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements<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 Elements 0 through i and
	 * area_right[i] holds the surface area of the box containing Elements
	 * i through size-1.
	 */

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

	/* Precalculate the areas for speed. */

	build_area_table(*Elements, first, last - 1, area_left);
	build_area_table(*Elements, 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 BRANCHING_FACTOR is reached or
	 * if splitting stops being effective.
	 */

	if ((size <= BRANCHING_FACTOR) || (best_loc < 0))
	{
		cd = (BSPHERE_TREE *)POV_MALLOC(sizeof(BSPHERE_TREE), "blob bounding hierarchy");

		cd->Entries = (short)size;

		cd->Node = (BSPHERE_TREE **)POV_MALLOC(size*sizeof(BSPHERE_TREE *), "blob bounding hierarchy");

		for (i = 0; i < size; i++)
		{
			cd->Node[i] = (*Elements)[first+i];
		}

		recompute_bound(cd);

		*Root = cd;

		if (*nElem >= maxelements)
		{
			/* Prim array overrun, increase array by 50%. */

			maxelements = 1.5 * maxelements;

			/* For debugging only. */

// TODO FIXME			Debug_Info("Reallocing elements to %d\n", maxelements);

			*Elements = (BSPHERE_TREE **)POV_REALLOC(*Elements, maxelements * sizeof(BSPHERE_TREE *), "bounding slabs");
		}

		(*Elements)[*nElem] = cd;

		(*nElem)++;

		return (1);
	}
	else
	{
		sort_and_split(Root, Elements, nElem, first, best_loc + 1, maxelements);

		sort_and_split(Root, Elements, nElem, best_loc + 1, last, maxelements);

		return (0);
	}
}
コード例 #4
0
ファイル: bbox.cpp プロジェクト: SteveShaw/povray
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);
}