コード例 #1
0
ファイル: bsdfmesh.c プロジェクト: NREL/Radiance
/* Compute normalized distribution scattering functions for comparison */
static void
compute_nDSFs(const RBFNODE *rbf0, const RBFNODE *rbf1)
{
	const double	nf0 = (GRIDRES*GRIDRES) / rbf0->vtotal;
	const double	nf1 = (GRIDRES*GRIDRES) / rbf1->vtotal;
	int		x, y;
	FVECT		dv;

	for (x = GRIDRES; x--; )
	    for (y = GRIDRES; y--; ) {
		ovec_from_pos(dv, x, y);	/* cube root (brightness) */
		dsf_grid[x][y].val[0] = pow(nf0*eval_rbfrep(rbf0, dv), .3333);
		dsf_grid[x][y].val[1] = pow(nf1*eval_rbfrep(rbf1, dv), .3333);
	    }
}	
コード例 #2
0
ファイル: bsdfmesh.c プロジェクト: NREL/Radiance
/* Estimate single-lobe radius for DSF at the given outgoing angle */
static double
est_DSFrad(const RBFNODE *rbf, const FVECT outvec)
{
	const double	rad_epsilon = 0.01;
	const double	DSFtarget = 0.60653066 * eval_rbfrep(rbf,outvec) *
							COSF(outvec[2]);
	double		inside_rad = rad_epsilon;
	double		outside_rad = 0.5;
	double		DSFinside = eval_DSFsurround(rbf, outvec, inside_rad);
	double		DSFoutside = eval_DSFsurround(rbf, outvec, outside_rad);
#define	interp_rad	inside_rad + (outside_rad-inside_rad) * \
				(DSFtarget-DSFinside) / (DSFoutside-DSFinside)
						/* Newton's method (sort of) */
	do {
		double	test_rad = interp_rad;
		double	DSFtest;
		if ((test_rad >= outside_rad) | (test_rad <= inside_rad))
			test_rad = .5*(inside_rad + outside_rad);
		DSFtest = eval_DSFsurround(rbf, outvec, test_rad);
		if (DSFtest > DSFtarget) {
			inside_rad = test_rad;
			DSFinside = DSFtest;
		} else {
			outside_rad = test_rad;
			DSFoutside = DSFtest;
		}
	} while (outside_rad-inside_rad > rad_epsilon);

	return(.5*(inside_rad + outside_rad));
#undef interp_rad
}
コード例 #3
0
ファイル: bsdfmesh.c プロジェクト: NREL/Radiance
/* Compute average DSF value at the given radius from central vector */
static double
eval_DSFsurround(const RBFNODE *rbf, const FVECT outvec, const double rad)
{
	const int	ninc = 12;
	const double	phinc = 2.*M_PI/ninc;
	double		sum = 0;
	int		n = 0;
	FVECT		tvec;
	int		i;
						/* compute initial vector */
	if (output_orient*outvec[2] >= 1.-FTINY) {
		tvec[0] = tvec[2] = 0;
		tvec[1] = 1;
	} else {
		tvec[0] = tvec[1] = 0;
		tvec[2] = 1;
	}
	geodesic(tvec, outvec, tvec, rad, GEOD_RAD);
						/* average surrounding DSF */
	for (i = 0; i < ninc; i++) {
		if (i) spinvector(tvec, tvec, outvec, phinc);
		if (tvec[2] > 0 ^ output_orient > 0)
			continue;
		sum += eval_rbfrep(rbf, tvec) * COSF(tvec[2]);
		++n;
	}
	if (n < 2)				/* should never happen! */
		return(sum);
	return(sum/(double)n);
}
コード例 #4
0
ファイル: bsdfmesh.c プロジェクト: NREL/Radiance
/* Conservative estimate of average BSDF value from current DSF's */
static void
comp_bsdf_spec(void)
{
	double		vmod_sum = 0;
	double		rad_sum = 0;
	int		n = 0;
	double		*cost_list = NULL;
	double		max_cost = 1.;
	RBFNODE		*rbf;
	FVECT		sdv;
						/* sort by incident altitude */
	for (rbf = dsf_list; rbf != NULL; rbf = rbf->next)
		n++;
	if (n >= 10)
		cost_list = (double *)malloc(sizeof(double)*n);
	if (cost_list == NULL) {
		bsdf_spec_val = 0;
		bsdf_spec_rad = 0;
		return;
	}
	n = 0;
	for (rbf = dsf_list; rbf != NULL; rbf = rbf->next)
		cost_list[n++] = rbf->invec[2]*input_orient;
	qsort(cost_list, n, sizeof(double), dbl_cmp);
	max_cost = cost_list[(n+3)/4];		/* accept 25% nearest grazing */
	free(cost_list);
	n = 0;
	for (rbf = dsf_list; rbf != NULL; rbf = rbf->next) {
		double	this_rad, cosfact, vest;
		if (rbf->invec[2]*input_orient > max_cost)
			continue;
		sdv[0] = -rbf->invec[0];
		sdv[1] = -rbf->invec[1];
		sdv[2] = rbf->invec[2]*(2*(input_orient==output_orient) - 1);
		cosfact = COSF(sdv[2]);
		this_rad = est_DSFrad(rbf, sdv);
		vest = eval_rbfrep(rbf, sdv) * cosfact *
				(2.*M_PI) * this_rad*this_rad;
		if (vest > rbf->vtotal)		/* don't over-estimate energy */
			vest = rbf->vtotal;
		vmod_sum += vest / cosfact;	/* remove cosine factor */
		rad_sum += this_rad;
		++n;
	}
	bsdf_spec_rad = rad_sum/(double)n;
	bsdf_spec_val = vmod_sum/(2.*M_PI*n*bsdf_spec_rad*bsdf_spec_rad);
}
コード例 #5
0
ファイル: bsdf2klems.c プロジェクト: Pizookies/Radiance
/* Interpolate and output a radial basis function BSDF representation */
static void
eval_rbf(void)
{
	ANGLE_BASIS	*abp = get_basis(kbasis);
	float		bsdfarr[MAXPATCHES*MAXPATCHES];
	FVECT		vin, vout;
	RBFNODE		*rbf;
	double		sum;
	int		i, j, n;
						/* sanity check */
	if (abp->nangles > MAXPATCHES) {
		fprintf(stderr, "%s: too many patches!\n", progname);
		exit(1);
	}
	data_prologue();			/* begin output */
	for (i = 0; i < abp->nangles; i++) {
	    if (input_orient > 0)		/* use incident patch center */
		fi_getvec(vin, i+.5*(i>0), abp);
	    else
		bi_getvec(vin, i+.5*(i>0), abp);

	    rbf = advect_rbf(vin);		/* compute radial basis func */

	    for (j = 0; j < abp->nangles; j++) {
	        sum = 0;			/* sample over exiting patch */
		for (n = npsamps; n--; ) {
		    if (output_orient > 0)
			fo_getvec(vout, j+(n+frandom())/npsamps, abp);
		    else
			bo_getvec(vout, j+(n+frandom())/npsamps, abp);

		    sum += eval_rbfrep(rbf, vout) / vout[2];
		}
		bsdfarr[j*abp->nangles + i] = sum*output_orient/npsamps;
	    }
	    if (rbf != NULL)
		free(rbf);
	}
	n = 0;					/* write out our matrix */
	for (j = 0; j < abp->nangles; j++) {
	    for (i = 0; i < abp->nangles; i++)
		printf("\t%.3e\n", bsdfarr[n++]);
	    putchar('\n');
	}
	data_epilogue();			/* finish output */
}
コード例 #6
0
ファイル: bsdfrbf.c プロジェクト: Pizookies/Radiance
/* Count up filled nodes and build RBF representation from current grid */ 
RBFNODE *
make_rbfrep(void)
{
	int	niter = 16;
	double	lastVar, thisVar = 100.;
	int	nn;
	RBFNODE	*newnode;
	RBFVAL	*itera;
	int	i, j;
				/* compute RBF radii */
	compute_radii();
				/* coagulate lobes */
	cull_values();
	nn = 0;			/* count selected bins */
	for (i = 0; i < GRIDRES; i++)
	    for (j = 0; j < GRIDRES; j++)
		nn += dsf_grid[i][j].nval;
				/* compute minimum BSDF */
	comp_bsdf_min();
				/* allocate RBF array */
	newnode = (RBFNODE *)malloc(sizeof(RBFNODE) + sizeof(RBFVAL)*(nn-1));
	if (newnode == NULL)
		goto memerr;
	newnode->ord = -1;
	newnode->next = NULL;
	newnode->ejl = NULL;
	newnode->invec[2] = sin((M_PI/180.)*theta_in_deg);
	newnode->invec[0] = cos((M_PI/180.)*phi_in_deg)*newnode->invec[2];
	newnode->invec[1] = sin((M_PI/180.)*phi_in_deg)*newnode->invec[2];
	newnode->invec[2] = input_orient*sqrt(1. - newnode->invec[2]*newnode->invec[2]);
	newnode->vtotal = 0;
	newnode->nrbf = nn;
	nn = 0;			/* fill RBF array */
	for (i = 0; i < GRIDRES; i++)
	    for (j = 0; j < GRIDRES; j++)
		if (dsf_grid[i][j].nval) {
			newnode->rbfa[nn].peak = dsf_grid[i][j].vsum;
			newnode->rbfa[nn].crad = RSCA*dsf_grid[i][j].crad + .5;
			newnode->rbfa[nn].gx = i;
			newnode->rbfa[nn].gy = j;
			++nn;
		}
				/* iterate to improve interpolation accuracy */
	itera = (RBFVAL *)malloc(sizeof(RBFVAL)*newnode->nrbf);
	if (itera == NULL)
		goto memerr;
	memcpy(itera, newnode->rbfa, sizeof(RBFVAL)*newnode->nrbf);
	do {
		double	dsum = 0, dsum2 = 0;
		nn = 0;
		for (i = 0; i < GRIDRES; i++)
		    for (j = 0; j < GRIDRES; j++)
			if (dsf_grid[i][j].nval) {
				FVECT	odir;
				double	corr;
				ovec_from_pos(odir, i, j);
				itera[nn++].peak *= corr =
					dsf_grid[i][j].vsum /
						eval_rbfrep(newnode, odir);
				dsum += 1. - corr;
				dsum2 += (1.-corr)*(1.-corr);
			}
		memcpy(newnode->rbfa, itera, sizeof(RBFVAL)*newnode->nrbf);
		lastVar = thisVar;
		thisVar = dsum2/(double)nn;
#ifdef DEBUG
		fprintf(stderr, "Avg., RMS error: %.1f%%  %.1f%%\n",
					100.*dsum/(double)nn,
					100.*sqrt(thisVar));
#endif
	} while (--niter > 0 && lastVar-thisVar > 0.02*lastVar);

	free(itera);
	nn = 0;			/* compute sum for normalization */
	while (nn < newnode->nrbf)
		newnode->vtotal += rbf_volume(&newnode->rbfa[nn++]);
#ifdef DEBUG
	fprintf(stderr, "Integrated DSF at (%.1f,%.1f) deg. is %.2f\n",
			get_theta180(newnode->invec), get_phi360(newnode->invec),
			newnode->vtotal);
#endif
	insert_dsf(newnode);

	return(newnode);
memerr:
	fprintf(stderr, "%s: Out of memory in make_rbfrep()\n", progname);
	exit(1);
}