Ejemplo n.º 1
0
/* Add normal direction if missing */
static void
check_normal_incidence(void)
{
	static FVECT		norm_vec = {.0, .0, 1.};
	const int		saved_nprocs = nprocs;
	RBFNODE			*near_rbf, *mir_rbf, *rbf;
	double			bestd;
	int			n;

	if (dsf_list == NULL)
		return;				/* XXX should be error? */
	near_rbf = dsf_list;
	bestd = input_orient*near_rbf->invec[2];
	if (single_plane_incident) {		/* ordered plane incidence? */
		if (bestd >= 1.-2.*FTINY)
			return;			/* already have normal */
	} else {
		switch (inp_coverage) {
		case INP_QUAD1:
		case INP_QUAD2:
		case INP_QUAD3:
		case INP_QUAD4:
			break;			/* quadrilateral symmetry? */
		default:
			return;			/* else we can interpolate */
		}
		for (rbf = dsf_list; rbf != NULL; rbf = rbf->next) {
			const double	d = input_orient*rbf->invec[2];
			if (d >= 1.-2.*FTINY)
				return;		/* seems we have normal */
			if (d > bestd) {
				near_rbf = rbf;
				bestd = d;
			}
		}
	}
	if (mig_list != NULL) {			/* need to be called first */
		fprintf(stderr, "%s: Late call to check_normal_incidence()\n",
				progname);
		exit(1);
	}
#ifdef DEBUG
	fprintf(stderr, "Interpolating normal incidence by mirroring (%.1f,%.1f)\n",
			get_theta180(near_rbf->invec), get_phi360(near_rbf->invec));
#endif
						/* mirror nearest incidence */
	n = sizeof(RBFNODE) + sizeof(RBFVAL)*(near_rbf->nrbf-1);
	mir_rbf = (RBFNODE *)malloc(n);
	if (mir_rbf == NULL)
		goto memerr;
	memcpy(mir_rbf, near_rbf, n);
	mir_rbf->ord = near_rbf->ord - 1;	/* not used, I think */
	mir_rbf->next = NULL;
	mir_rbf->ejl = NULL;
	rev_rbf_symmetry(mir_rbf, MIRROR_X|MIRROR_Y);
	nprocs = 1;				/* compute migration matrix */
	if (create_migration(mir_rbf, near_rbf) == NULL)
		exit(1);			/* XXX should never happen! */
	norm_vec[2] = input_orient;		/* interpolate normal dist. */
	rbf = e_advect_rbf(mig_list, norm_vec, 0);
	nprocs = saved_nprocs;			/* final clean-up */
	free(mir_rbf);
	free(mig_list);
	mig_list = near_rbf->ejl = NULL;
	insert_dsf(rbf);			/* insert interpolated normal */
	return;
memerr:
	fprintf(stderr, "%s: Out of memory in check_normal_incidence()\n",
				progname);
	exit(1);
}
Ejemplo n.º 2
0
/* Read a BSDF mesh interpolant from the given binary stream */
int
load_bsdf_rep(FILE *ifp)
{
	RBFNODE		rbfh;
	int		from_ord, to_ord;
	int		i;

	clear_bsdf_rep();
	if (ifp == NULL)
		return(0);
	if (getheader(ifp, headline, NULL) < 0 || single_plane_incident < 0 |
			!input_orient | !output_orient) {
		fprintf(stderr, "%s: missing/bad format for BSDF interpolant\n",
				progname);
		return(0);
	}
	rbfh.next = NULL;		/* read each DSF */
	rbfh.ejl = NULL;
	while ((rbfh.ord = getint(4, ifp)) >= 0) {
		RBFNODE		*newrbf;

		rbfh.invec[0] = getflt(ifp);
		rbfh.invec[1] = getflt(ifp);
		rbfh.invec[2] = getflt(ifp);
		if (normalize(rbfh.invec) == 0) {
			fprintf(stderr, "%s: zero incident vector\n", progname);
			return(0);
		}
		rbfh.vtotal = getflt(ifp);
		rbfh.nrbf = getint(4, ifp);
		newrbf = (RBFNODE *)malloc(sizeof(RBFNODE) +
					sizeof(RBFVAL)*(rbfh.nrbf-1));
		if (newrbf == NULL)
			goto memerr;
		memcpy(newrbf, &rbfh, sizeof(RBFNODE)-sizeof(RBFVAL));
		for (i = 0; i < rbfh.nrbf; i++) {
			newrbf->rbfa[i].peak = getflt(ifp);
			newrbf->rbfa[i].crad = getint(2, ifp) & 0xffff;
			newrbf->rbfa[i].gx = getint(1, ifp) & 0xff;
			newrbf->rbfa[i].gy = getint(1, ifp) & 0xff;
		}
		if (feof(ifp))
			goto badEOF;
					/* insert in global list */
		if (insert_dsf(newrbf) != rbfh.ord) {
			fprintf(stderr, "%s: error adding DSF\n", progname);
			return(0);
		}
	}
					/* read each migration matrix */
	while ((from_ord = getint(4, ifp)) >= 0 &&
			(to_ord = getint(4, ifp)) >= 0) {
		RBFNODE		*from_rbf = get_dsf(from_ord);
		RBFNODE		*to_rbf = get_dsf(to_ord);
		MIGRATION	*newmig;
		int		n;

		if ((from_rbf == NULL) | (to_rbf == NULL)) {
			fprintf(stderr,
				"%s: bad DSF reference in migration edge\n",
					progname);
			return(0);
		}
		n = from_rbf->nrbf * to_rbf->nrbf;
		newmig = (MIGRATION *)malloc(sizeof(MIGRATION) +
						sizeof(float)*(n-1));
		if (newmig == NULL)
			goto memerr;
		newmig->rbfv[0] = from_rbf;
		newmig->rbfv[1] = to_rbf;
		memset(newmig->mtx, 0, sizeof(float)*n);
		for (i = 0; ; ) {	/* read sparse data */
			int	zc = getint(1, ifp) & 0xff;
			if ((i += zc) >= n)
				break;
			if (zc == 0xff)
				continue;
			newmig->mtx[i++] = getflt(ifp);
		}
		if (feof(ifp))
			goto badEOF;
					/* insert in edge lists */
		newmig->enxt[0] = from_rbf->ejl;
		from_rbf->ejl = newmig;
		newmig->enxt[1] = to_rbf->ejl;
		to_rbf->ejl = newmig;
					/* push onto global list */
		newmig->next = mig_list;
		mig_list = newmig;
	}
	return(1);			/* success! */
memerr:
	fprintf(stderr, "%s: Out of memory in load_bsdf_rep()\n", progname);
	exit(1);
badEOF:
	fprintf(stderr, "%s: Unexpected EOF in load_bsdf_rep()\n", progname);
	return(0);
}
Ejemplo n.º 3
0
/* 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);
}