/* Releases all unfree'd memory from current memory pool */ void mem_release() { #if defined(MEM_RECLAIM) OStream *f = NULL; MEMNODE *p, *tmp; size_t totsize; p = memlist; totsize = 0; #if defined(MEM_TRACE) if (p != NULL && (p->poolno == poolno)) f = New_OStream(MEM_LOG_FNAME, POV_File_Data_LOG, true); #endif /* MEM_TRACE */ while (p != NULL && (p->poolno == poolno)) { #if defined(MEM_TRACE) #if defined(MEM_TAG) if (!mem_check_tag(p)) Debug_Info("mem_release(): Memory pointer corrupt!\n"); #endif /* MEM_TAG */ totsize += (p->size - NODESIZE - (MEM_GUARD_SIZE * 2)); if (!leak_msg) { Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME); leak_msg = true; } if (f != NULL) f->printf("File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size - NODESIZE - (MEM_GUARD_SIZE * 2))); #endif /* MEM_TRACE */ #if defined(MEM_STATS) mem_stats_free(p->size); #endif tmp = p; p = p->next; remove_node(tmp); FREE(tmp); } if (f != NULL) delete f; if (totsize > 0) Debug_Info("%lu bytes reclaimed (pool #%d)\n", totsize, poolno); if (poolno > 0) poolno--; #if defined(MEM_STATS) /* reinitialize the stats structure for next time through */ mem_stats_init(); #endif #endif /* MEM_RECLAIM */ }
/* Released all unfree'd memory from all pools */ void mem_release_all() { #if defined(MEM_RECLAIM) OStream *f = NULL; MEMNODE *p, *tmp; size_t totsize; // Send_Progress("Reclaiming memory", PROGRESS_RECLAIMING_MEMORY); p = memlist; totsize = 0; #if defined(MEM_TRACE) if (p != NULL) f = New_OStream(MEM_LOG_FNAME, POV_File_Data_LOG, true); #endif while (p != NULL) { #if defined(MEM_TRACE) #if defined(MEM_TAG) if (!mem_check_tag(p)) Debug_Info("mem_release_all(): Memory pointer corrupt!\n"); #endif /* MEM_TAG */ totsize += (p->size - NODESIZE - (MEM_GUARD_SIZE * 2)); if (!leak_msg) { Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME); leak_msg = true; } if (f != NULL) f->printf("File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size - NODESIZE - (MEM_GUARD_SIZE * 2))); #endif #if defined(MEM_STATS) /* This is after we have printed stats, and this may slow us down a little, */ /* so we may want to simply re-initialize the mem-stats at the end of this loop. */ mem_stats_free(p->size); #endif tmp = p; p = p->next; remove_node(tmp); FREE(tmp); } if (f != NULL) delete f; // if (totsize > 0) // Debug_Info("\n%lu bytes reclaimed\n", totsize); poolno = 0; memlist = NULL; #endif #if defined(MEM_STATS) /* reinitialize the stats structure for next time through */ mem_stats_init(); #endif }
void Destroy_IsoSurface(OBJECT* Object) { ISOSURFACE *Isosrf = (ISOSURFACE *)Object; ISO_Max_Gradient *mginfo = Isosrf->mginfo; mginfo->refcnt--; mginfo->gradient = max(Isosrf->gradient, mginfo->gradient); mginfo->max_gradient = max(Isosrf->max_gradient, mginfo->max_gradient); if((Stage == STAGE_SHUTDOWN) && (mginfo->refcnt == 0)) { FunctionCode *fn = POVFPU_GetFunction(*(Isosrf->Function)); if(fn != NULL) { if(Isosrf->eval == false) { // Only show the warning if necessary! // BTW, not being too picky here is a feature and not a bug ;-) [trf] if((mginfo->gradient > EPSILON) && (mginfo->max_gradient > EPSILON)) { DBL diff = mginfo->max_gradient - mginfo->gradient; DBL prop = fabs(mginfo->max_gradient / mginfo->gradient); if(((prop <= 0.9) && (diff <= -0.5)) || (((prop <= 0.95) || (diff <= -0.1)) && (mginfo->max_gradient < 10.0))) { WarningAt(0, fn->filename, fn->filepos.lineno, fn->filepos.offset, "The maximum gradient found was %0.3f, but max_gradient of the\n" "isosurface was set to %0.3f. The isosurface may contain holes!\n" "Adjust max_gradient to get a proper rendering of the isosurface.", (float)(mginfo->gradient), (float)(mginfo->max_gradient)); } else if((diff >= 10.0) || ((prop >= 1.1) && (diff >= 0.5))) { WarningAt(0, fn->filename, fn->filepos.lineno, fn->filepos.offset, "The maximum gradient found was %0.3f, but max_gradient of\n" "the isosurface was set to %0.3f. Adjust max_gradient to\n" "get a faster rendering of the isosurface.", (float)(mginfo->gradient), (float)(mginfo->max_gradient)); } } } else { DBL diff = (mginfo->eval_max / max(mginfo->eval_max - mginfo->eval_var, EPSILON)); if((Isosrf->eval_param[0] > mginfo->eval_max) || (Isosrf->eval_param[1] > diff)) { mginfo->eval_cnt = max(mginfo->eval_cnt, 1.0); // make sure it won't be zero WarningAt(0, fn->filename, fn->filepos.lineno, fn->filepos.offset, "Evaluate found a maximum gradient of %0.3f and an average\n" "gradient of %0.3f. The maximum gradient variation was %0.3f.\n", (float)(mginfo->eval_max), (float)(mginfo->eval_gradient_sum / mginfo->eval_cnt), (float)(mginfo->eval_var)); if(opts.Options & VERBOSE) { diff = max(diff, 1.0); // prevent contradicting output Debug_Info("It is recommended to adjust the parameters of 'evaluate' to:\n" "First parameter less than %0.3f\n" "Second parameter less than %0.3f and greater than 1.0\n" "Third parameter greater than %0.3f and less than 1.0\n", (float)(mginfo->eval_max), (float)(diff), (float)(1.0 / diff)); } } } } } if(mginfo->refcnt == 0) POV_FREE(mginfo); Destroy_Function(Isosrf->Function); Destroy_Transform(Isosrf->Trans); POV_FREE(Object); }
void ot_index_box(const Vector3d& min_point, const Vector3d& max_point, OT_ID *id) { // TODO OPTIMIZE DBL dx, dy, dz, desiredSize; DBL bsized, maxord; POW2OP_DECLARE() // Calculate the absolute minimum required size of the node, assuming it is perfectly centered within the node; // Node size must be a power of 2, and be large enough to accomodate box's biggest dimensions with maximum overhang to all sides // compute ideal size of the node for a perfect fit without any overhang dx = max_point.x() - min_point.x(); dy = max_point.y() - min_point.y(); dz = max_point.z() - min_point.z(); desiredSize = max3(dx, dy, dz); // compute ideal size of the node for a perfect fit with full overhang to all sides // desiredSize /= (1 + 2 * 0.5); // compute best-matching power-of-two size for a perfect fit with overhang // (Note: theoretically this might pick a size larger than required if desiredSize is already a power of two) // desiredSize *= 2.0; POW2OP_FLOOR(bsized,desiredSize) // avoid divisions by zero if(bsized == 0.0) bsized = 1.0; #ifdef SAFE_METHOD // This block checks for the case where the node id would cause integer // overflow, since it is a small buffer far away maxord = max3(fabs(min_point[X]), fabs(min_point[Y]), fabs(min_point[Z])); maxord += OT_BIAS; while (maxord / bsized > 1000000000.0) { #ifdef RADSTATS overflows++; #endif bsized *= 2.0; } #endif // SAFE_METHOD // The node we chose so far would be ideal for a box of identical size positioned at the node's center, // but the actual box is probably somewhat off-center and therefore may have excessive overhang in some directions; // check and possibly fix this. Vector3d center = (min_point + max_point) / 2; id->x = (int) floor((center[X] + OT_BIAS) / bsized); id->y = (int) floor((center[Y] + OT_BIAS) / bsized); id->z = (int) floor((center[Z] + OT_BIAS) / bsized); POW2OP_ENCODE(id->Size, bsized) #ifdef RADSTATS thisloops = 0; #endif while (!ot_point_in_node(min_point, id) || !ot_point_in_node(max_point, id)) { // Debug_Info("looping %d,%d,%d,%d min=%d, max=%d\n", test_id.x, test_id.y, // test_id.z, test_id.Size, ot_point_in_node(min_point, &test_id), // ot_point_in_node(max_point, &test_id)); ot_parent(id, id); #ifdef RADSTATS totloops++; thisloops++; #endif } #ifdef RADSTATS if (thisloops < minloops) minloops = thisloops; if (thisloops > maxloops) maxloops = thisloops; #endif #ifdef OT_DEBUG if (id->Size > 139) { Debug_Info("unusually large id, maxdel=%.4f, bsized=%.4f, isize=%d\n", maxdel, bsized, id->Size); } #endif }
static int sort_and_split(BSPHERE_TREE **Root, BSPHERE_TREE ***Elements, int *nElem, int first, int last) { int size, i, best_loc; DBL *area_left, *area_right; DBL best_index, new_index; BSPHERE_TREE *cd; Axis = find_axis(*Elements, 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 *)(*Elements + first), size, sizeof(BSPHERE_TREE *), comp_elements); /* * 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. */ 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); sort_and_split(Root, Elements, nElem, best_loc + 1, last); return (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); } }