// 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; } } }
void CFFD::calc_afine_deform(void* pDest, int nStride) { float fDelX, fDelY, fDelZ, fX, fY, fZ; int nX, nY, nZ; CVector cT, cI1, cI2, cI3, cI4, cI5, cI6; CVector* pTab = m_pVectorTable; CVector* pDeformed = (CVector*)pDest; CVector* pD1; CVector* pD2; calc_bbox(); fDelX = 1.0f/((m_cBMax.fX - m_cBMin.fX)/(float)(m_nDeformResX - 1)); fDelY = 1.0f/((m_cBMax.fY - m_cBMin.fY)/(float)(m_nDeformResY - 1)); fDelZ = 1.0f/((m_cBMax.fZ - m_cBMin.fZ)/(float)(m_nDeformResZ - 1)); for (int nI = 0; nI != m_nElements; nI++) { cT.fX = (pTab->fX - m_cBMin.fX)*fDelX; cT.fY = (pTab->fY - m_cBMin.fY)*fDelY; cT.fZ = (pTab->fZ - m_cBMin.fZ)*fDelZ; nX = (int)cT.fX; nY = (int)cT.fY; nZ = (int)cT.fZ; fX = cT.fX - (float)nX; fY = cT.fY - (float)nY; fZ = cT.fZ - (float)nZ; pD1 = get_deform_point(nX, nY, nZ); pD2 = get_deform_point(nX + 1, nY, nZ); afine_interpolate(pD2, pD1, fX, cI1); pD1 = get_deform_point(nX, nY + 1, nZ); pD2 = get_deform_point(nX + 1, nY + 1, nZ); afine_interpolate(pD2, pD1, fX, cI2); pD1 = get_deform_point(nX, nY, nZ + 1); pD2 = get_deform_point(nX + 1, nY, nZ + 1); afine_interpolate(pD2, pD1, fX, cI3); pD1 = get_deform_point(nX, nY + 1, nZ + 1); pD2 = get_deform_point(nX + 1, nY + 1, nZ + 1); afine_interpolate(pD2, pD1, fX, cI4); afine_interpolate(&cI2, &cI1, fY, cI5); afine_interpolate(&cI4, &cI3, fY, cI6); afine_interpolate(&cI6, &cI5, fZ, *pDeformed); pTab = (CVector*)((char*)pTab + m_nVectorStride); pDeformed = (CVector*)((char*)pDeformed + nStride); } }
void CFFD::calc_spline_deform(void *pDest, int nStride) { float fDelX, fDelY, fDelZ, fX, fY, fZ; int nX, nY, nZ, nI, nQ; CVector cT; CVector* pTab = m_pVectorTable; CVector* pDeformed = (CVector*)pDest; CVector aI1[4][4]; CVector aI2[4]; calc_bbox(); fDelX = 1.0f/((m_cBMax.fX - m_cBMin.fX)/(float)(m_nDeformResX - 1)); fDelY = 1.0f/((m_cBMax.fY - m_cBMin.fY)/(float)(m_nDeformResY - 1)); fDelZ = 1.0f/((m_cBMax.fZ - m_cBMin.fZ)/(float)(m_nDeformResZ - 1)); for (int nS = 0; nS != m_nElements; nS++) { cT.fX = (pTab->fX - m_cBMin.fX)*fDelX; cT.fY = (pTab->fY - m_cBMin.fY)*fDelY; cT.fZ = (pTab->fZ - m_cBMin.fZ)*fDelZ; nX = (int)cT.fX; nY = (int)cT.fY; nZ = (int)cT.fZ; fX = cT.fX - (float)nX; fY = cT.fY - (float)nY; fZ = cT.fZ - (float)nZ; for (nQ = 0; nQ != 4; nQ++) { for (nI = 0; nI != 4; nI++) { spline_interpolate(*get_deform_point(nX - 1, nY - 1 + nI, nZ - 1 + nQ), *get_deform_point(nX , nY - 1 + nI, nZ - 1 + nQ), *get_deform_point(nX + 1, nY - 1 + nI, nZ - 1 + nQ), *get_deform_point(nX + 2, nY - 1 + nI, nZ - 1 + nQ), fX, aI1[nI][nQ]); } } for (nI = 0; nI != 4; nI++) spline_interpolate(aI1[0][nI], aI1[1][nI], aI1[2][nI], aI1[3][nI], fY, aI2[nI]); spline_interpolate(aI2[0], aI2[1], aI2[2], aI2[3], fZ, *pDeformed); pTab = (CVector*)((char*)pTab + m_nVectorStride); pDeformed = (CVector*)((char*)pDeformed + nStride); } }
/* Load a simple database */ void load_database(void) { ssgLoaderOptions *loaderopt = new ssgLoaderOptions(); loaderopt->setCreateBranchCallback(hookNode); Root = ssgLoadAC(InputFileName, loaderopt); fprintf(stderr, "%d branches found\n", BrNb); calc_bbox(); calc_coord(); }
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; } }
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; } } }
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); } }
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); }