/* ccr.c: determination of constant control radisoity value */ #include "scene.h" #include "mcradP.h" #include "ccr.h" static COLOR *(*get_radiance)(ELEMENT *); static COLOR (*get_scaling)(ELEMENT *); /* intial guess for constant control radiance value */ static void InitialControlRadiosity(COLOR *minRad, COLOR *maxRad, COLOR *fmin, COLOR *fmax) { COLOR totalflux, maxrad; double area=0.; COLORCLEAR(totalflux); COLORCLEAR(maxrad); /* initial interval: 0 ... maxrad */ ForAllPatches(P, Patches) { REC_ForAllSurfaceLeafs(elem, TOPLEVEL_ELEMENT(P)) { COLOR rad = get_radiance(elem)[0]; float warea = elem->area; /* weighted area */ #ifdef IDMCR if (mcr.importance_driven && mcr.method!=RWR) { warea *= (elem->imp - elem->source_imp); /* multiply with received importance */ } #endif /* factor M_PI is omitted everywhere */ COLORADDSCALED(totalflux, /* M_PI* */ warea, rad, totalflux); area += warea; COLORMAX(maxrad, rad, maxrad); } REC_EndForAllSurfaceLeafs; } EndForAll; COLORCLEAR(*minRad); *fmin = totalflux; *maxRad = maxrad; COLORSCALE(area, maxrad, *fmax); COLORSUBTRACT(*fmax, totalflux, *fmax); } #define NRINTERVALS 10 static void RefineComponent(float *minRad, float *maxRad, float *fmin, float *fmax, float *f, float *rad) { int i, imin; /* find subinterval containing the minimum */ *fmax = f[0]; *fmin = f[0], imin=0; for (i=1; i<=NRINTERVALS; i++) { if (f[i] < *fmin) { *fmin = f[i]; imin = i; } if (f[i] > *fmax) { *fmax = f[i]; } } if (imin == 0) { /* first subinterval contains minimum */ *minRad = rad[0]; *maxRad = rad[1]; } else if (imin == NRINTERVALS) { /* last subinterval contains minimum */ *minRad = rad[NRINTERVALS-1]; *maxRad = rad[NRINTERVALS]; } else { if (f[imin-1] < f[imin+1]) { /* subinterval left of imin contains minimum */ *minRad = rad[imin-1]; *maxRad = rad[imin]; } else { /* subinterval right of imin */ *minRad = rad[imin]; *maxRad = rad[imin+1]; } } } /* Finds subinterval containing optimal constant control radiosity value. *. * Uses regular interval subdivision (generalisation of the bisection * method). Does so component wise. */ static void RefineControlRadiosity(COLOR *minRad, COLOR *maxRad, COLOR *fmin, COLOR *fmax) { COLOR color_one; COLOR f[NRINTERVALS+1], rad[NRINTERVALS+1], d; int i, s; COLORSETMONOCHROME(color_one, 1.); /* initialisations. rad[i] = radiosity at boundary i. */ COLORSUBTRACT(*maxRad, *minRad, d); for (i=0; i<=NRINTERVALS; i++) { COLORCLEAR(f[i]); COLORADDSCALED(*minRad, (double)i/(double)NRINTERVALS, d, rad[i]); } /* determine value of F(beta) = sum_i (area_i * fabs(B_i - beta)) on * a regular subdivision of the interval */ ForAllPatches(P, Patches) { REC_ForAllSurfaceLeafs(elem, TOPLEVEL_ELEMENT(P)) { COLOR B = get_radiance(elem)[0]; COLOR s = get_scaling ? get_scaling(elem) : color_one; float warea = elem->area; /* weighted area */ #ifdef IDMCR if (mcr.importance_driven && mcr.method!=RWR) { warea *= (elem->imp - elem->source_imp); /* multiply with received importance */ } #endif for (i=0; i<=NRINTERVALS; i++) { COLOR t; COLORPROD(s, rad[i], t); COLORSUBTRACT(B, t, t); COLORABS(t, t); COLORADDSCALED(f[i], warea, t, f[i]); } } REC_EndForAllSurfaceLeafs; } EndForAll; /* find sub-interval containing optimal control radiosity (component-wise) */ for (s=0; sspec[s]), &(maxRad->spec[s]), &(fmin->spec[s]), &(fmax->spec[s]), fc, radc); } } #undef NRINTERVALS COLOR DetermineControlRadiosity(COLOR *(*GetRadiance)(ELEMENT *), COLOR (*GetScaling)(ELEMENT *)) { COLOR minRad, maxRad, fmin, fmax, beta, delta, f_orig; float eps = 0.001; int sweep = 0; get_radiance = GetRadiance; get_scaling = GetScaling; COLORCLEAR(beta); if (!get_radiance) return beta; fprintf(stderr, "Determining optimal control radiosity value ... "); InitialControlRadiosity(&minRad, &maxRad, &fmin, &fmax); f_orig = fmin; /* initial minRad=0, f/f_orig will determine * possible efficiency gain */ COLORSUBTRACT(fmax, fmin, delta); COLORADDSCALED(delta, (-eps), fmin, delta); while ((COLORMAXCOMPONENT(delta) > 0.) || sweep<4) { sweep++; /* fprintf(stderr, "Sweep %d: beta in [", sweep); ColorPrint(stderr, minRad); fprintf(stderr, "; "); ColorPrint(stderr, maxRad); fprintf(stderr, "] ... "); fflush(stderr); */ RefineControlRadiosity(&minRad, &maxRad, &fmin, &fmax); /* fprintf(stderr, "F in ["); ColorPrint(stderr, fmin); fprintf(stderr, "; "); ColorPrint(stderr, fmax); fprintf(stderr, "]\n"); */ COLORSUBTRACT(fmax, fmin, delta); COLORADDSCALED(delta, (-eps), fmin, delta); } COLORADD(minRad, maxRad, beta); COLORSCALE(0.5, beta, beta); /* fprintf(stderr, "Solution: beta = "); */ ColorPrint(stderr, beta); fprintf(stderr, " (%g lux)", M_PI * ColorLuminance(beta)); /* fprintf(stderr, ", F approx "); ColorPrint(stderr, fmin); fprintf(stderr, " (%g lux)", M_PI * ColorLuminance(fmin)); fprintf(stderr, " cfr. F(0) = "); ColorPrint(stderr, f_orig); fprintf(stderr, " (%g lux)", M_PI * ColorLuminance(f_orig)); */ fprintf(stderr, "\n"); /* PlotBeta(); */ return beta; }