Esempio n. 1
0
extern int
raymixture(		/* mix modifiers */
	RAY  *r,
	OBJECT  fore,
	OBJECT  back,
	double  coef
)
{
	RAY  fr, br;
	int  foremat, backmat;
	int  i;
					/* bound coefficient */
	if (coef > 1.0)
		coef = 1.0;
	else if (coef < 0.0)
		coef = 0.0;
					/* compute foreground and background */
	foremat = backmat = 0;
					/* foreground */
	fr = *r;
	if (coef > FTINY) {
		fr.rweight *= coef;
		scalecolor(fr.rcoef, coef);
		foremat = rayshade(&fr, fore);
	}
					/* background */
	br = *r;
	if (coef < 1.0-FTINY) {
		br.rweight *= 1.0-coef;
		scalecolor(br.rcoef, 1.0-coef);
		backmat = rayshade(&br, back);
	}
					/* check for transparency */
	if (backmat ^ foremat) {
		if (backmat && coef > FTINY)
			raytrans(&fr);
		else if (foremat && coef < 1.0-FTINY)
			raytrans(&br);
	}
					/* mix perturbations */
	for (i = 0; i < 3; i++)
		r->pert[i] = coef*fr.pert[i] + (1.0-coef)*br.pert[i];
					/* mix pattern colors */
	scalecolor(fr.pcol, coef);
	scalecolor(br.pcol, 1.0-coef);
	copycolor(r->pcol, fr.pcol);
	addcolor(r->pcol, br.pcol);
					/* return value tells if material */
	if (!foremat & !backmat)
		return(0);
					/* mix returned ray values */
	scalecolor(fr.rcol, coef);
	scalecolor(br.rcol, 1.0-coef);
	copycolor(r->rcol, fr.rcol);
	addcolor(r->rcol, br.rcol);
	r->rt = bright(fr.rcol) > bright(br.rcol) ? fr.rt : br.rt;
	return(1);
}
Esempio n. 2
0
static void
dirashik(		/* compute source contribution */
	COLOR  cval,		/* returned coefficient */
	void  *nnp,		/* material data */
	FVECT  ldir,		/* light source direction */
	double  omega		/* light source size */
)
{
	ASHIKDAT *np = nnp;
	double  ldot;
	double  dtmp, dtmp1, dtmp2;
	FVECT  h;
	COLOR  ctmp;

	setcolor(cval, 0.0, 0.0, 0.0);

	ldot = DOT(np->pnorm, ldir);

	if (ldot < 0.0)
		return;		/* wrong side */

	/*
	 *  Compute and add diffuse reflected component to returned
	 *  color.
	 */
	copycolor(ctmp, np->mcolor);
	dtmp = ldot * omega * (1.0/PI) * (1. - schlick_fres(ldot));
	scalecolor(ctmp, dtmp);		
	addcolor(cval, ctmp);

	if ((np->specfl & (SPA_REFL|SPA_BADU)) != SPA_REFL)
		return;
	/*
	 *  Compute specular reflection coefficient
	 */
					/* half vector */
	VSUB(h, ldir, np->rp->rdir);
	normalize(h);
					/* ellipse */
	dtmp1 = DOT(np->u, h);
	dtmp1 *= dtmp1 * np->u_power;
	dtmp2 = DOT(np->v, h);
	dtmp2 *= dtmp2 * np->v_power;
					/* Ashikhmin-Shirley model*/
	dtmp = DOT(np->pnorm, h);
	dtmp = pow(dtmp, (dtmp1+dtmp2)/(1.-dtmp*dtmp));
	dtmp *= sqrt((np->u_power+1.)*(np->v_power+1.));
	dtmp /= 8.*PI * DOT(ldir,h) * MAX(ldot,np->pdot);
					/* worth using? */
	if (dtmp > FTINY) {
		copycolor(ctmp, np->scolor);
		dtmp *= ldot * omega;
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	}
}
Esempio n. 3
0
extern void
rayparticipate(			/* compute ray medium participation */
	RAY  *r
)
{
	COLOR	ce, ca;
	double	re, ge, be;

	if (intens(r->cext) <= 1./FHUGE)
		return;				/* no medium */
	re = r->rot*colval(r->cext,RED);
	ge = r->rot*colval(r->cext,GRN);
	be = r->rot*colval(r->cext,BLU);
	if (r->crtype & SHADOW) {		/* no scattering for sources */
		re *= 1. - colval(r->albedo,RED);
		ge *= 1. - colval(r->albedo,GRN);
		be *= 1. - colval(r->albedo,BLU);
	}
	setcolor(ce,	re<=FTINY ? 1. : re>92. ? 0. : exp(-re),
			ge<=FTINY ? 1. : ge>92. ? 0. : exp(-ge),
			be<=FTINY ? 1. : be>92. ? 0. : exp(-be));
	multcolor(r->rcol, ce);			/* path extinction */
	if (r->crtype & SHADOW || intens(r->albedo) <= FTINY)
		return;				/* no scattering */
	setcolor(ca,
		colval(r->albedo,RED)*colval(ambval,RED)*(1.-colval(ce,RED)),
		colval(r->albedo,GRN)*colval(ambval,GRN)*(1.-colval(ce,GRN)),
		colval(r->albedo,BLU)*colval(ambval,BLU)*(1.-colval(ce,BLU)));
	addcolor(r->rcol, ca);			/* ambient in scattering */
	srcscatter(r);				/* source in scattering */
}
Esempio n. 4
0
extern void
scotscan(		/* apply scotopic color sensitivity loss */
	COLOR	*scan,
	int	xres
)
{
	COLOR	ctmp;
	double	incolor, b, Lw;
	register int	i;

	for (i = 0; i < xres; i++) {
		Lw = plum(scan[i]);
		if (Lw >= TopMesopic)
			incolor = 1.;
		else if (Lw <= BotMesopic)
			incolor = 0.;
		else
			incolor = (Lw - BotMesopic) /
					(TopMesopic - BotMesopic);
		if (incolor < 1.-FTINY) {
			b = (1.-incolor)*slum(scan[i])*inpexp/SWNORM;
			if (lumf == rgblum) b /= WHTEFFICACY;
			setcolor(ctmp, b, b, b);
			if (incolor <= FTINY)
				setcolor(scan[i], 0., 0., 0.);
			else
				scalecolor(scan[i], incolor);
			addcolor(scan[i], ctmp);
		}
	}
}
Esempio n. 5
0
static void
sum_consp(		/* sum in conspicuity result */
	register struct ConspSum	*cdest,
	register struct ConspSum	*cs
)
{
	if ((cdest == NULL) | (cs == NULL))
		return;
	addcolor(cdest->vsum, cs->vsum);
	addcolor(cdest->v2sum, cs->v2sum);
	cdest->nsamp += cs->nsamp;
	cdest->xmsum += cs->xmsum;
	cdest->ymsum += cs->ymsum;
	cdest->npix += cs->npix;
	if (cs->hls > cdest->hls)
		cdest->hls = cs->hls;
}
Esempio n. 6
0
static void
starpoint(		/* pixel is on the star's point */
	COLOR  fcol,
	int  x,
	int  y,
	register HOTPIX	 *hp
)
{
	COLOR  ctmp;
	double	d2;
	
	d2 = (double)(x - hp->x)*(x - hp->x) + (double)(y - hp->y)*(y - hp->y);
	if (d2 > sprdfact) {
		d2 = sprdfact / d2;
		if (d2 < FTINY)
			return;
		copycolor(ctmp, hp->val);
		scalecolor(ctmp, d2);
		addcolor(fcol, ctmp);
	} else if (d2 > FTINY) {
		addcolor(fcol, hp->val);
	}
}
Esempio n. 7
0
FormulaParser::FormulaParser(std::string const& descr, FormatFlags flags, AttributeMap const& values, PowerTag* context)
  : descr(descr)
  , flags(flags)
  , values(values)
  , pos(0)
  , context(context)
{
  if (!preloaded) {
    preloaded = true;
    addcolor("blue");
    addcolor("magic", "blue");
    addcolor("gray");
    addcolor("gold");
    addcolor("green");
    addcolor("orange");
    addcolor("purple");
    addcolor("red");
    addcolor("white");
    addcolor("yellow");
    pretags.emplace("/c", "</span>");
    pretags.emplace("icon:bullet", "<span class=\"tooltip-icon-bullet\"></span>");
  }
}
static void
getpicture(void)				/* load in picture colors */
{
	COLR	*scanln;
	COLOR	pval;
	int	ccount[24];
	double	d;
	int	y, i;
	register int	x;

	scanln = (COLR *)malloc(xmax*sizeof(COLR));
	if (scanln == NULL) {
		perror(progname);
		exit(1);
	}
	for (i = 0; i < 24; i++) {
		setcolor(inpRGB[i], 0., 0., 0.);
		ccount[i] = 0;
	}
	for (y = ymax-1; y >= 0; y--) {
		if (freadcolrs(scanln, xmax, stdin) < 0) {
			fprintf(stderr, "%s: error reading input picture\n",
					progname);
			exit(1);
		}
		for (x = 0; x < xmax; x++)
			if (chartndx(x, y, &i) == RG_CENT) {
				colr_color(pval, scanln[x]);
				addcolor(inpRGB[i], pval);
				ccount[i]++;
			}
	}
	for (i = 0; i < 24; i++) {		/* compute averages */
		if (ccount[i] == 0)
			continue;
		d = 1./ccount[i];
		scalecolor(inpRGB[i], d);
		inpflags |= 1L<<i;
	}
	free((void *)scanln);
}
Esempio n. 9
0
extern void
dobox(			/* simple box filter */
	COLOR  csum,
	int  xcent,
	int  ycent,
	int  c,
	int  r
)
{
	int  wsum;
	double  d;
	int  y;
	register int  x, offs;
	register COLOR	*scan;
	
	wsum = 0;
	setcolor(csum, 0.0, 0.0, 0.0);
	for (y = ycent+1-ybrad; y <= ycent+ybrad; y++) {
		if (y < 0) continue;
		if (y >= yres) break;
		d = y_r < 1.0 ? y_r*y - (r+.5) : (double)(y - ycent);
		if (d < -0.5) continue;
		if (d >= 0.5) break;
		scan = scanin[y%barsize];
		for (x = xcent+1-xbrad; x <= xcent+xbrad; x++) {
			offs = x < 0 ? xres : x >= xres ? -xres : 0;
			if (offs && !wrapfilt)
				continue;
			d = x_c < 1.0 ? x_c*x - (c+.5) : (double)(x - xcent);
			if (d < -0.5) continue;
			if (d >= 0.5) break;
			wsum++;
			addcolor(csum, scan[x+offs]);
		}
	}
	if (wsum > 1) {
		d = 1.0/wsum;
		scalecolor(csum, d);
	}
}
Esempio n. 10
0
void
compavg(				/* recompute averages */
	PNODE	*p
)
{
	int	i, navg;
	
	if (p->kid == NULL)
		return;

	setcolor(p->v, .0, .0, .0);
	navg = 0;
	for (i = 0; i < 4; i++) {
		if (p->kid[i].xmin >= p->kid[i].xmax) continue;
		if (p->kid[i].ymin >= p->kid[i].ymax) continue;
		compavg(p->kid+i);
		addcolor(p->v, p->kid[i].v);
		navg++;
	}
	if (navg > 1)
		scalecolor(p->v, 1./navg);
}
Esempio n. 11
0
extern void
dogauss(		/* gaussian filter */
	COLOR  csum,
	int  xcent,
	int  ycent,
	int  c,
	int  r
)
{
	double  dy, dx, weight, wsum;
	COLOR  ctmp;
	int  y;
	register int  x, offs;
	register COLOR	*scan;

	wsum = FTINY;
	setcolor(csum, 0.0, 0.0, 0.0);
	for (y = ycent-yrad; y <= ycent+yrad; y++) {
		if (y < 0) continue;
		if (y >= yres) break;
		dy = (y_r*(y+.5) - (r+.5))/rad;
		scan = scanin[y%barsize];
		for (x = xcent-xrad; x <= xcent+xrad; x++) {
			offs = x < 0 ? xres : x >= xres ? -xres : 0;
			if (offs && !wrapfilt)
				continue;
			dx = (x_c*(x+.5) - (c+.5))/rad;
			weight = lookgauss(dx*dx + dy*dy);
			wsum += weight;
			copycolor(ctmp, scan[x+offs]);
			scalecolor(ctmp, weight);
			addcolor(csum, ctmp);
		}
	}
	weight = 1.0/wsum;
	scalecolor(csum, weight);
}
Esempio n. 12
0
char *
material(void)			/* get (and print) current material */
{
	char	*mname = "mat";
	COLOR	radrgb, c2;
	double	d;

	if (c_cmname != NULL)
		mname = c_cmname;
	if (!c_cmaterial->clock)
		return(mname);		/* already current */
				/* else update output */
	c_cmaterial->clock = 0;
	if (c_cmaterial->ed > .1) {	/* emitter */
		cvtcolor(radrgb, &c_cmaterial->ed_c,
				emult*c_cmaterial->ed/(PI*WHTEFFICACY));
		if (glowdist < FHUGE) {		/* do a glow */
			fprintf(matfp, "\nvoid glow %s\n0\n0\n", mname);
			fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED),
					colval(radrgb,GRN),
					colval(radrgb,BLU), glowdist);
		} else {
			fprintf(matfp, "\nvoid light %s\n0\n0\n", mname);
			fprintf(matfp, "3 %f %f %f\n", colval(radrgb,RED),
					colval(radrgb,GRN),
					colval(radrgb,BLU));
		}
		return(mname);
	}
	d = c_cmaterial->rd + c_cmaterial->td +
			c_cmaterial->rs + c_cmaterial->ts;
	if ((d < 0.) | (d > 1.))
		return(NULL);
					/* check for glass/dielectric */
	if (c_cmaterial->nr > 1.1 &&
			c_cmaterial->ts > .25 && c_cmaterial->rs <= .125 &&
			c_cmaterial->td <= .01 && c_cmaterial->rd <= .01 &&
			c_cmaterial->rs_a <= .01 && c_cmaterial->ts_a <= .01) {
		cvtcolor(radrgb, &c_cmaterial->ts_c,
				c_cmaterial->ts + c_cmaterial->rs);
		if (c_cmaterial->sided) {		/* dielectric */
			colval(radrgb,RED) = pow(colval(radrgb,RED),
							1./C_1SIDEDTHICK);
			colval(radrgb,GRN) = pow(colval(radrgb,GRN),
							1./C_1SIDEDTHICK);
			colval(radrgb,BLU) = pow(colval(radrgb,BLU),
							1./C_1SIDEDTHICK);
			fprintf(matfp, "\nvoid dielectric %s\n0\n0\n", mname);
			fprintf(matfp, "5 %g %g %g %f 0\n", colval(radrgb,RED),
					colval(radrgb,GRN), colval(radrgb,BLU),
					c_cmaterial->nr);
			return(mname);
		}
							/* glass */
		fprintf(matfp, "\nvoid glass %s\n0\n0\n", mname);
		fprintf(matfp, "4 %f %f %f %f\n", colval(radrgb,RED),
				colval(radrgb,GRN), colval(radrgb,BLU),
				c_cmaterial->nr);
		return(mname);
		}
					/* check for trans */
	if (c_cmaterial->td > .01 || c_cmaterial->ts > .01) {
		double	ts, a5, a6;

		if (c_cmaterial->sided) {
			ts = sqrt(c_cmaterial->ts);	/* approximate */
			a5 = .5;
		} else {
			ts = c_cmaterial->ts;
			a5 = 1.;
		}
						/* average colors */
		d = c_cmaterial->rd + c_cmaterial->td + ts;
		cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd/d);
		cvtcolor(c2, &c_cmaterial->td_c, c_cmaterial->td/d);
		addcolor(radrgb, c2);
		cvtcolor(c2, &c_cmaterial->ts_c, ts/d);
		addcolor(radrgb, c2);
		if (c_cmaterial->rs + ts > .0001)
			a5 = (c_cmaterial->rs*c_cmaterial->rs_a +
					ts*a5*c_cmaterial->ts_a) /
					(c_cmaterial->rs + ts);
		a6 = (c_cmaterial->td + ts) /
				(c_cmaterial->rd + c_cmaterial->td + ts);
		if (a6 < .999)
			d = c_cmaterial->rd/(1. - c_cmaterial->rs)/(1. - a6);
		else
			d = c_cmaterial->td + ts;
		scalecolor(radrgb, d);
		fprintf(matfp, "\nvoid trans %s\n0\n0\n", mname);
		fprintf(matfp, "7 %f %f %f\n", colval(radrgb,RED),
				colval(radrgb,GRN), colval(radrgb,BLU));
		fprintf(matfp, "\t%f %f %f %f\n", c_cmaterial->rs, a5, a6,
				ts/(ts + c_cmaterial->td));
		return(mname);
	}
					/* check for plastic */
	if (c_cmaterial->rs < .1) {
		cvtcolor(radrgb, &c_cmaterial->rd_c,
					c_cmaterial->rd/(1.-c_cmaterial->rs));
		fprintf(matfp, "\nvoid plastic %s\n0\n0\n", mname);
		fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED),
				colval(radrgb,GRN), colval(radrgb,BLU),
				c_cmaterial->rs, c_cmaterial->rs_a);
		return(mname);
	}
					/* else it's metal */
						/* average colors */
	cvtcolor(radrgb, &c_cmaterial->rd_c, c_cmaterial->rd);
	cvtcolor(c2, &c_cmaterial->rs_c, c_cmaterial->rs);
	addcolor(radrgb, c2);
	fprintf(matfp, "\nvoid metal %s\n0\n0\n", mname);
	fprintf(matfp, "5 %f %f %f %f %f\n", colval(radrgb,RED),
			colval(radrgb,GRN), colval(radrgb,BLU),
			c_cmaterial->rs/(c_cmaterial->rd + c_cmaterial->rs),
			c_cmaterial->rs_a);
	return(mname);
}
Esempio n. 13
0
extern void
direct(					/* add direct component */
	RAY  *r,			/* ray that hit surface */
	srcdirf_t *f,			/* direct component coefficient function */
	void  *p			/* data for f */
)
{
	register int  sn;
	register CONTRIB  *scp;
	SRCINDEX  si;
	int  nshadcheck, ncnts;
	int  nhits;
	double  prob, ourthresh, hwt;
	RAY  sr;
			/* NOTE: srccnt and cntord global so no recursion */
	if (nsources <= 0)
		return;		/* no sources?! */
						/* potential contributions */
	initsrcindex(&si);
	for (sn = 0; srcray(&sr, r, &si); sn++) {
		if (sn >= maxcntr) {
			maxcntr = sn + MAXSPART;
			srccnt = (CONTRIB *)realloc((void *)srccnt,
					maxcntr*sizeof(CONTRIB));
			cntord = (CNTPTR *)realloc((void *)cntord,
					maxcntr*sizeof(CNTPTR));
			if ((srccnt == NULL) | (cntord == NULL))
				error(SYSTEM, "out of memory in direct");
		}
		cntord[sn].sndx = sn;
		scp = srccnt + sn;
		scp->sno = sr.rsrc;
						/* compute coefficient */
		(*f)(scp->coef, p, sr.rdir, si.dom);
		cntord[sn].brt = intens(scp->coef);
		if (cntord[sn].brt <= 0.0)
			continue;
#if SHADCACHE
						/* check shadow cache */
		if (si.np == 1 && srcblocked(&sr)) {
			cntord[sn].brt = 0.0;
			continue;
		}
#endif
		VCOPY(scp->dir, sr.rdir);
		copycolor(sr.rcoef, scp->coef);
						/* compute potential */
		sr.revf = srcvalue;
		rayvalue(&sr);
		multcolor(sr.rcol, sr.rcoef);
		copycolor(scp->val, sr.rcol);
		cntord[sn].brt = bright(sr.rcol);
	}
						/* sort contributions */
	qsort(cntord, sn, sizeof(CNTPTR), cntcmp);
	{					/* find last */
		register int  l, m;

		ncnts = l = sn;
		sn = 0;
		while ((m = (sn + ncnts) >> 1) != l) {
			if (cntord[m].brt > 0.0)
				sn = m;
			else
				ncnts = m;
			l = m;
		}
	}
	if (ncnts == 0)
		return;		/* no contributions! */
                                                /* accumulate tail */
        for (sn = ncnts-1; sn > 0; sn--)
                cntord[sn-1].brt += cntord[sn].brt;
						/* compute number to check */
	nshadcheck = pow((double)ncnts, shadcert) + .5;
						/* modify threshold */
	ourthresh = shadthresh / r->rweight;
						/* test for shadows */
	for (nhits = 0, hwt = 0.0, sn = 0; sn < ncnts;
			hwt += (double)source[scp->sno].nhits /
				(double)source[scp->sno].ntests,
			sn++) {
						/* check threshold */
		if ((sn+nshadcheck>=ncnts ? cntord[sn].brt :
				cntord[sn].brt-cntord[sn+nshadcheck].brt)
				< ourthresh*bright(r->rcol))
			break;
		scp = srccnt + cntord[sn].sndx;
						/* test for hit */
		rayorigin(&sr, SHADOW, r, NULL);
		copycolor(sr.rcoef, scp->coef);
		VCOPY(sr.rdir, scp->dir);
		sr.rsrc = scp->sno;
						/* keep statistics */
		if (source[scp->sno].ntests++ > 0xfffffff0) {
			source[scp->sno].ntests >>= 1;
			source[scp->sno].nhits >>= 1;
		}
		if (localhit(&sr, &thescene) &&
				( sr.ro != source[scp->sno].so ||
				source[scp->sno].sflags & SFOLLOW )) {
						/* follow entire path */
			raycont(&sr);
			if (trace != NULL)
				(*trace)(&sr);	/* trace execution */
			if (bright(sr.rcol) <= FTINY) {
#if SHADCACHE
				if ((scp <= srccnt || scp[-1].sno != scp->sno)
						&& (scp >= srccnt+ncnts-1 ||
						    scp[1].sno != scp->sno))
					srcblocker(&sr);
#endif
				continue;	/* missed! */
			}
			rayparticipate(&sr);
			multcolor(sr.rcol, sr.rcoef);
			copycolor(scp->val, sr.rcol);
		} else if (trace != NULL &&
			(source[scp->sno].sflags & (SDISTANT|SVIRTUAL|SFOLLOW))
						== (SDISTANT|SFOLLOW) &&
				sourcehit(&sr) && rayshade(&sr, sr.ro->omod)) {
			(*trace)(&sr);		/* trace execution */
			/* skip call to rayparticipate() & scp->val update */
		}
						/* add contribution if hit */
		addcolor(r->rcol, scp->val);
		nhits++;
		source[scp->sno].nhits++;
	}
Esempio n. 14
0
int
m_dielectric(	/* color a ray which hit a dielectric interface */
	OBJREC  *m,
	RAY  *r
)
{
	double  cos1, cos2, nratio;
	COLOR  ctrans;
	COLOR  talb;
	int  hastexture;
	int	flatsurface;
	double  refl, trans;
	FVECT  dnorm;
	double  d1, d2;
	RAY  p;
	int  i;

	/* PMAP: skip refracted shadow or ambient ray if accounted for in
	   photon map */
	if (shadowRayInPmap(r) || ambRayInPmap(r))
		return(1);
	
	if (m->oargs.nfargs != (m->otype==MAT_DIELECTRIC ? 5 : 8))
		objerror(m, USER, "bad arguments");

	raytexture(r, m->omod);			/* get modifiers */

	if ( (hastexture = DOT(r->pert,r->pert) > FTINY*FTINY) )
		cos1 = raynormal(dnorm, r);	/* perturb normal */
	else {
		VCOPY(dnorm, r->ron);
		cos1 = r->rod;
	}
	flatsurface = r->ro != NULL && isflat(r->ro->otype) &&
			!hastexture | (r->crtype & AMBIENT);

						/* index of refraction */
	if (m->otype == MAT_DIELECTRIC)
		nratio = m->oargs.farg[3] + m->oargs.farg[4]/MLAMBDA;
	else
		nratio = m->oargs.farg[3] / m->oargs.farg[7];
	
	if (cos1 < 0.0) {			/* inside */
		hastexture = -hastexture;
		cos1 = -cos1;
		dnorm[0] = -dnorm[0];
		dnorm[1] = -dnorm[1];
		dnorm[2] = -dnorm[2];
		setcolor(r->cext, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)),
				 -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)),
				 -mylog(m->oargs.farg[2]*colval(r->pcol,BLU)));
		setcolor(r->albedo, 0., 0., 0.);
		r->gecc = 0.;
		if (m->otype == MAT_INTERFACE) {
			setcolor(ctrans,
				-mylog(m->oargs.farg[4]*colval(r->pcol,RED)),
				-mylog(m->oargs.farg[5]*colval(r->pcol,GRN)),
				-mylog(m->oargs.farg[6]*colval(r->pcol,BLU)));
			setcolor(talb, 0., 0., 0.);
		} else {
			copycolor(ctrans, cextinction);
			copycolor(talb, salbedo);
		}
	} else {				/* outside */
		nratio = 1.0 / nratio;

		setcolor(ctrans, -mylog(m->oargs.farg[0]*colval(r->pcol,RED)),
				 -mylog(m->oargs.farg[1]*colval(r->pcol,GRN)),
				 -mylog(m->oargs.farg[2]*colval(r->pcol,BLU)));
		setcolor(talb, 0., 0., 0.);
		if (m->otype == MAT_INTERFACE) {
			setcolor(r->cext,
				-mylog(m->oargs.farg[4]*colval(r->pcol,RED)),
				-mylog(m->oargs.farg[5]*colval(r->pcol,GRN)),
				-mylog(m->oargs.farg[6]*colval(r->pcol,BLU)));
			setcolor(r->albedo, 0., 0., 0.);
			r->gecc = 0.;
		}
	}

	d2 = 1.0 - nratio*nratio*(1.0 - cos1*cos1);	/* compute cos theta2 */

	if (d2 < FTINY)			/* total reflection */

		refl = 1.0;

	else {				/* refraction occurs */
					/* compute Fresnel's equations */
		cos2 = sqrt(d2);
		d1 = cos1;
		d2 = nratio*cos2;
		d1 = (d1 - d2) / (d1 + d2);
		refl = d1 * d1;

		d1 = 1.0 / cos1;
		d2 = nratio / cos2;
		d1 = (d1 - d2) / (d1 + d2);
		refl += d1 * d1;

		refl *= 0.5;
		trans = 1.0 - refl;

		trans *= nratio*nratio;		/* solid angle ratio */

		setcolor(p.rcoef, trans, trans, trans);

		if (rayorigin(&p, REFRACTED, r, p.rcoef) == 0) {

						/* compute refracted ray */
			d1 = nratio*cos1 - cos2;
			for (i = 0; i < 3; i++)
				p.rdir[i] = nratio*r->rdir[i] + d1*dnorm[i];
						/* accidental reflection? */
			if (hastexture &&
				DOT(p.rdir,r->ron)*hastexture >= -FTINY) {
				d1 *= (double)hastexture;
				for (i = 0; i < 3; i++)	/* ignore texture */
					p.rdir[i] = nratio*r->rdir[i] +
							d1*r->ron[i];
				normalize(p.rdir);	/* not exact */
			} else
				checknorm(p.rdir);
#ifdef  DISPERSE
			if (m->otype != MAT_DIELECTRIC
					|| r->rod > 0.0
					|| r->crtype & SHADOW
					|| !directvis
					|| m->oargs.farg[4] == 0.0
					|| !disperse(m, r, p.rdir,
							trans, ctrans, talb))
#endif
			{
				copycolor(p.cext, ctrans);
				copycolor(p.albedo, talb);
				rayvalue(&p);
				multcolor(p.rcol, p.rcoef);
				addcolor(r->rcol, p.rcol);
						/* virtual distance */
				if (flatsurface ||
					(1.-FTINY <= nratio) &
						(nratio <= 1.+FTINY))
					r->rxt = r->rot + raydistance(&p);
			}
		}
	}
	setcolor(p.rcoef, refl, refl, refl);

	if (!(r->crtype & SHADOW) &&
			rayorigin(&p, REFLECTED, r, p.rcoef) == 0) {

					/* compute reflected ray */
		VSUM(p.rdir, r->rdir, dnorm, 2.*cos1);
					/* accidental penetration? */
		if (hastexture && DOT(p.rdir,r->ron)*hastexture <= FTINY)
			VSUM(p.rdir, r->rdir, r->ron, 2.*r->rod);
		checknorm(p.rdir);
		rayvalue(&p);			/* reflected ray value */

		multcolor(p.rcol, p.rcoef);	/* color contribution */
		copycolor(r->mcol, p.rcol);
		addcolor(r->rcol, p.rcol);
						/* virtual distance */
		r->rmt = r->rot;
		if (flatsurface)
			r->rmt += raydistance(&p);
	}
				/* rayvalue() computes absorption */
	return(1);
}
Esempio n. 15
0
static int
disperse(  /* check light sources for dispersion */
	OBJREC  *m,
	RAY  *r,
	FVECT  vt,
	double  tr,
	COLOR  cet,
	COLOR  abt
)
{
	RAY  sray;
	const RAY  *entray;
	FVECT  v1, v2, n1, n2;
	FVECT  dv, v2Xdv;
	double  v2Xdvv2Xdv;
	int  success = 0;
	SRCINDEX  si;
	FVECT  vtmp1, vtmp2;
	double  dtmp1, dtmp2;
	int  l1, l2;
	COLOR  ctmp;
	int  i;
	
	/*
	 *     This routine computes dispersion to the first order using
	 *  the following assumptions:
	 *
	 *	1) The dependency of the index of refraction on wavelength
	 *		is approximated by Hartmann's equation with lambda0
	 *		equal to zero.
	 *	2) The entry and exit locations are constant with respect
	 *		to dispersion.
	 *
	 *     The second assumption permits us to model dispersion without
	 *  having to sample refracted directions.  We assume that the
	 *  geometry inside the material is constant, and concern ourselves
	 *  only with the relationship between the entering and exiting ray.
	 *  We compute the first derivatives of the entering and exiting
	 *  refraction with respect to the index of refraction.  This 
	 *  is then used in a first order Taylor series to determine the
	 *  index of refraction necessary to send the exiting ray to each
	 *  light source.
	 *     If an exiting ray hits a light source within the refraction
	 *  boundaries, we sum all the frequencies over the disc of the
	 *  light source to determine the resulting color.  A smaller light
	 *  source will therefore exhibit a sharper spectrum.
	 */

	if (!(r->crtype & REFRACTED)) {		/* ray started in material */
		VCOPY(v1, r->rdir);
		n1[0] = -r->rdir[0]; n1[1] = -r->rdir[1]; n1[2] = -r->rdir[2];
	} else {
						/* find entry point */
		for (entray = r; entray->rtype != REFRACTED;
				entray = entray->parent)
			;
		entray = entray->parent;
		if (entray->crtype & REFRACTED)		/* too difficult */
			return(0);
		VCOPY(v1, entray->rdir);
		VCOPY(n1, entray->ron);
	}
	VCOPY(v2, vt);			/* exiting ray */
	VCOPY(n2, r->ron);

					/* first order dispersion approx. */
	dtmp1 = 1./DOT(n1, v1);
	dtmp2 = 1./DOT(n2, v2);
	for (i = 0; i < 3; i++)
		dv[i] = v1[i] + v2[i] - n1[i]*dtmp1 - n2[i]*dtmp2;
		
	if (DOT(dv, dv) <= FTINY)	/* null effect */
		return(0);
					/* compute plane normal */
	fcross(v2Xdv, v2, dv);
	v2Xdvv2Xdv = DOT(v2Xdv, v2Xdv);

					/* check sources */
	initsrcindex(&si);
	while (srcray(&sray, r, &si)) {

		if (DOT(sray.rdir, v2) < MINCOS)
			continue;			/* bad source */
						/* adjust source ray */

		dtmp1 = DOT(v2Xdv, sray.rdir) / v2Xdvv2Xdv;
		sray.rdir[0] -= dtmp1 * v2Xdv[0];
		sray.rdir[1] -= dtmp1 * v2Xdv[1];
		sray.rdir[2] -= dtmp1 * v2Xdv[2];

		l1 = lambda(m, v2, dv, sray.rdir);	/* mean lambda */

		if (l1 > MAXLAMBDA || l1 < MINLAMBDA)	/* not visible */
			continue;
						/* trace source ray */
		copycolor(sray.cext, cet);
		copycolor(sray.albedo, abt);
		normalize(sray.rdir);
		rayvalue(&sray);
		if (bright(sray.rcol) <= FTINY)	/* missed it */
			continue;
		
		/*
		 *	Compute spectral sum over diameter of source.
		 *  First find directions for rays going to opposite
		 *  sides of source, then compute wavelengths for each.
		 */
		 
		fcross(vtmp1, v2Xdv, sray.rdir);
		dtmp1 = sqrt(si.dom  / v2Xdvv2Xdv / PI);

							/* compute first ray */
		VSUM(vtmp2, sray.rdir, vtmp1, dtmp1);

		l1 = lambda(m, v2, dv, vtmp2);		/* first lambda */
		if (l1 < 0)
			continue;
							/* compute second ray */
		VSUM(vtmp2, sray.rdir, vtmp1, -dtmp1);

		l2 = lambda(m, v2, dv, vtmp2);		/* second lambda */
		if (l2 < 0)
			continue;
					/* compute color from spectrum */
		if (l1 < l2)
			spec_rgb(ctmp, l1, l2);
		else
			spec_rgb(ctmp, l2, l1);
		multcolor(ctmp, sray.rcol);
		scalecolor(ctmp, tr);
		addcolor(r->rcol, ctmp);
		success++;
	}
	return(success);
}
Esempio n. 16
0
int
m_mist(		/* process a ray entering or leaving some mist */
	OBJREC  *m,
	RAY  *r
)
{
	RAY  p;
	int  *myslist = NULL;
	int  newslist[MAXSLIST+1];
	COLOR  mext;
	double  re, ge, be;
	int  i, j;
					/* check arguments */
	if (m->oargs.nfargs > 7)
		objerror(m, USER, "bad arguments");
					/* get source indices */
	if (m->oargs.nsargs > 0 && (myslist = (int *)m->os) == NULL) {
		if (m->oargs.nsargs > MAXSLIST)
			objerror(m, INTERNAL, "too many sources in list");
		myslist = (int *)malloc((m->oargs.nsargs+1)*sizeof(int));
		if (myslist == NULL)
			goto memerr;
		myslist[0] = 0;			/* size is first in list */
		for (j = 0; j < m->oargs.nsargs; j++) {
			i = nsources;		/* look up each source id */
			while (i--)
				if (srcmatch(source+i, m->oargs.sarg[j]))
					break;
			if (i < 0) {
				sprintf(errmsg, "unknown source \"%s\"",
						m->oargs.sarg[j]);
				objerror(m, WARNING, errmsg);
			} else if (inslist(myslist, i)) {
				sprintf(errmsg, "duplicate source \"%s\"",
						m->oargs.sarg[j]);
				objerror(m, WARNING, errmsg);
			} else
				myslist[++myslist[0]] = i;
		}
		m->os = (char *)myslist;
	}
	if (m->oargs.nfargs > 2) {		/* compute extinction */
		setcolor(mext, m->oargs.farg[0], m->oargs.farg[1],
				m->oargs.farg[2]);
		raytexture(r, m->omod);			/* get modifiers */
		multcolor(mext, r->pcol);
	} else
		setcolor(mext, 0., 0., 0.);
						/* start transmitted ray */
	if (rayorigin(&p, TRANS, r, NULL) < 0)
		return(1);
	VCOPY(p.rdir, r->rdir);
	p.slights = newslist;
	if (r->slights != NULL)			/* copy old list if one */
		for (j = r->slights[0]; j >= 0; j--)
			p.slights[j] = r->slights[j];
	else
		p.slights[0] = 0;
	if (r->rod > 0.) {			/* entering ray */
		addcolor(p.cext, mext);
		if (m->oargs.nfargs > 5)
			setcolor(p.albedo, m->oargs.farg[3],
					m->oargs.farg[4], m->oargs.farg[5]);
		if (m->oargs.nfargs > 6)
			p.gecc = m->oargs.farg[6];
		add2slist(&p, myslist);			/* add to list */
	} else {				/* leaving ray */
		if (myslist != NULL) {			/* delete from list */
			for (j = myslist[0]; j > 0; j--)
				if ( (i = inslist(p.slights, myslist[j])) )
					p.slights[i] = -1;
			for (i = 0, j = 1; j <= p.slights[0]; j++)
				if (p.slights[j] != -1)
					p.slights[++i] = p.slights[j];
			if (p.slights[0] - i < myslist[0]) {	/* fix old */
				addcolor(r->cext, mext);
				if (m->oargs.nfargs > 5)
					setcolor(r->albedo, m->oargs.farg[3],
					m->oargs.farg[4], m->oargs.farg[5]);
				if (m->oargs.nfargs > 6)
					r->gecc = m->oargs.farg[6];
				add2slist(r, myslist);
			}
			p.slights[0] = i;
		}
		if ((re = colval(r->cext,RED) - colval(mext,RED)) <
				colval(cextinction,RED))
			re = colval(cextinction,RED);
		if ((ge = colval(r->cext,GRN) - colval(mext,GRN)) <
				colval(cextinction,GRN))
			ge = colval(cextinction,GRN);
		if ((be = colval(r->cext,BLU) - colval(mext,BLU)) <
				colval(cextinction,BLU))
			be = colval(cextinction,BLU);
		setcolor(p.cext, re, ge, be);
		if (m->oargs.nfargs > 5)
			copycolor(p.albedo, salbedo);
		if (m->oargs.nfargs > 6)
			p.gecc = seccg;
	}
	rayvalue(&p);				/* calls rayparticipate() */
	copycolor(r->rcol, p.rcol);		/* return value */
	r->rt = r->rot + p.rt;
	return(1);
memerr:
	error(SYSTEM, "out of memory in m_mist");
	return 0; /* pro forma return */
}
Esempio n. 17
0
static void
sumans(		/* sum input pixel to output */
	int  px,
	int  py,
	int  rcent,
	int  ccent,
	double  m
)
{
	double  dy2, dx;
	COLOR  pval, ctmp;
	int  ksiz, r, offs;
	double  pc, pr, norm;
	register int  i, c;
	register COLOR	*scan;
	/*
	 * This normalization method fails at the picture borders because
	 * a different number of input pixels contribute there.
	 */
	scan = scanin[py%barsize] + (px < 0 ? xres : px >= xres ? -xres : 0);
	copycolor(pval, scan[px]);
	pc = x_c*(px+.5);
	pr = y_r*(py+.5);
	ksiz = CHECKRAD*m*rad + 1;
	if (ksiz > orad) ksiz = orad;
						/* compute normalization */
	norm = 0.0;
	i = 0;
	for (r = rcent-ksiz; r <= rcent+ksiz; r++) {
		if (r < 0) continue;
		if (r >= nrows) break;
		dy2 = (pr - (r+.5))/(m*rad);
		dy2 *= dy2;
		for (c = ccent-ksiz; c <= ccent+ksiz; c++) {
			if (!wrapfilt) {
				if (c < 0) continue;
				if (c >= ncols) break;
			}
			dx = (pc - (c+.5))/(m*rad);
			norm += warr[i++] = lookgauss(dx*dx + dy2);
		}
	}
	norm = 1.0/norm;
	if (x_c < 1.0) norm *= x_c;
	if (y_r < 1.0) norm *= y_r;
						/* sum pixels */
	i = 0;
	for (r = rcent-ksiz; r <= rcent+ksiz; r++) {
		if (r < 0) continue;
		if (r >= nrows) break;
		scan = scoutbar[r%obarsize];
		for (c = ccent-ksiz; c <= ccent+ksiz; c++) {
			offs = c < 0 ? ncols : c >= ncols ? -ncols : 0;
			if (offs && !wrapfilt)
				continue;
			copycolor(ctmp, pval);
			dx = norm*warr[i++];
			scalecolor(ctmp, dx);
			addcolor(scan[c+offs], ctmp);
		}
	}
}
Esempio n. 18
0
void volumePhotonDensity (PhotonMap *pmap, RAY *ray, COLOR irrad)
/* Photon volume density estimate. Returns irradiance at ray -> rop. */
{
   unsigned                      i;
   float                         r2, gecc2, ph;
   COLOR                         flux;
   Photon                        *photon;
   const PhotonSearchQueueNode   *sqn;

   setcolor(irrad, 0, 0, 0);
   
   if (!pmap -> maxGather) 
      return;
      
   findPhotons(pmap, ray);
   
   /* Need at least 2 photons */
   if (pmap -> squeue.tail < 2) 
      return;

#if 0      
   /* Volume biascomp disabled (probably redundant) */
   if (pmap -> minGather == pmap -> maxGather)
#endif   
   {
      /* No bias compensation. Just do a plain vanilla estimate */
      gecc2 = ray -> gecc * ray -> gecc;
      sqn = pmap -> squeue.node + 1;
      
      /* Average radius^2 between furthest two photons to improve accuracy */      
      r2 = max(sqn -> dist2, (sqn + 1) -> dist2);
      r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2));
      
      /* Skip the extra photon */
      for (i = 1; i < pmap -> squeue.tail; i++, sqn++) {
         photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
         
         /* Compute phase function for inscattering from photon */
         if (gecc2 <= FTINY) 
            ph = 1;
         else {
            ph = DOT(ray -> rdir, photon -> norm) / 127;
            ph = 1 + gecc2 - 2 * ray -> gecc * ph;
            ph = (1 - gecc2) / (ph * sqrt(ph));
         }
         
         getPhotonFlux(photon, flux);
         scalecolor(flux, ph);
         addcolor(irrad, flux);
      }
      
      /* Divide by search volume 4 / 3 * PI * r^3 and phase function
         normalization factor 1 / (4 * PI) */
      scalecolor(irrad, 3 / (16 * PI * PI * r2 * sqrt(r2)));
      return;
   }
#if 0
   else 
      /* Apply bias compensation to density estimate */
      volumeBiasComp(pmap, ray, irrad);
#endif      
}
Esempio n. 19
0
static void
diraniso(		/* compute source contribution */
	COLOR  cval,			/* returned coefficient */
	void  *nnp,			/* material data */
	FVECT  ldir,			/* light source direction */
	double  omega			/* light source size */
)
{
	ANISODAT *np = nnp;
	double  ldot;
	double  dtmp, dtmp1, dtmp2;
	FVECT  h;
	double  au2, av2;
	COLOR  ctmp;

	setcolor(cval, 0.0, 0.0, 0.0);

	ldot = DOT(np->pnorm, ldir);

	if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
		return;		/* wrong side */

	if ((ldot > FTINY) & (np->rdiff > FTINY)) {
		/*
		 *  Compute and add diffuse reflected component to returned
		 *  color.  The diffuse reflected component will always be
		 *  modified by the color of the material.
		 */
		copycolor(ctmp, np->mcolor);
		dtmp = ldot * omega * np->rdiff * (1.0/PI);
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	}
	if (ldot > FTINY && np->specfl&SP_REFL) {
		/*
		 *  Compute specular reflection coefficient using
		 *  anisotropic Gaussian distribution model.
		 */
						/* add source width if flat */
		if (np->specfl & SP_FLAT)
			au2 = av2 = omega * (0.25/PI);
		else
			au2 = av2 = 0.0;
		au2 += np->u_alpha*np->u_alpha;
		av2 += np->v_alpha*np->v_alpha;
						/* half vector */
		VSUB(h, ldir, np->rp->rdir);
						/* ellipse */
		dtmp1 = DOT(np->u, h);
		dtmp1 *= dtmp1 / au2;
		dtmp2 = DOT(np->v, h);
		dtmp2 *= dtmp2 / av2;
						/* new W-G-M-D model */
		dtmp = DOT(np->pnorm, h);
		dtmp *= dtmp;
		dtmp1 = (dtmp1 + dtmp2) / dtmp;
		dtmp = exp(-dtmp1) * DOT(h,h) /
				(PI * dtmp*dtmp * sqrt(au2*av2));
						/* worth using? */
		if (dtmp > FTINY) {
			copycolor(ctmp, np->scolor);
			dtmp *= ldot * omega;
			scalecolor(ctmp, dtmp);
			addcolor(cval, ctmp);
		}
	}
	if ((ldot < -FTINY) & (np->tdiff > FTINY)) {
		/*
		 *  Compute diffuse transmission.
		 */
		copycolor(ctmp, np->mcolor);
		dtmp = -ldot * omega * np->tdiff * (1.0/PI);
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	}
	if (ldot < -FTINY && np->specfl&SP_TRAN) {
		/*
		 *  Compute specular transmission.  Specular transmission
		 *  is always modified by material color.
		 */
						/* roughness + source */
		au2 = av2 = omega * (1.0/PI);
		au2 += np->u_alpha*np->u_alpha;
		av2 += np->v_alpha*np->v_alpha;
						/* "half vector" */
		VSUB(h, ldir, np->prdir);
		dtmp = DOT(h,h);
		if (dtmp > FTINY*FTINY) {
			dtmp1 = DOT(h,np->pnorm);
			dtmp = 1.0 - dtmp1*dtmp1/dtmp;
			if (dtmp > FTINY*FTINY) {
				dtmp1 = DOT(h,np->u);
				dtmp1 *= dtmp1 / au2;
				dtmp2 = DOT(h,np->v);
				dtmp2 *= dtmp2 / av2;
				dtmp = (dtmp1 + dtmp2) / dtmp;
			}
		} else
			dtmp = 0.0;
						/* Gaussian */
		dtmp = exp(-dtmp) * (1.0/PI) * sqrt(-ldot/(np->pdot*au2*av2));
						/* worth using? */
		if (dtmp > FTINY) {
			copycolor(ctmp, np->mcolor);
			dtmp *= np->tspec * omega;
			scalecolor(ctmp, dtmp);
			addcolor(cval, ctmp);
		}
	}
}
Esempio n. 20
0
int
m_ashikhmin(			/* shade ray that hit something anisotropic */
	OBJREC  *m,
	RAY  *r
)
{
	ASHIKDAT  nd;
	COLOR  ctmp;
	double	fres;
	int  i;
						/* easy shadow test */
	if (r->crtype & SHADOW)
		return(1);

	if (m->oargs.nfargs != 8)
		objerror(m, USER, "bad number of real arguments");
						/* check for back side */
	if (r->rod < 0.0) {
		if (!backvis) {
			raytrans(r);
			return(1);
		}
		raytexture(r, m->omod);
		flipsurface(r);			/* reorient if backvis */
	} else
		raytexture(r, m->omod);
						/* get material color */
	nd.mp = m;
	nd.rp = r;
	setcolor(nd.mcolor, m->oargs.farg[0],
			   m->oargs.farg[1],
			   m->oargs.farg[2]);
	setcolor(nd.scolor, m->oargs.farg[3],
			   m->oargs.farg[4],
			   m->oargs.farg[5]);
						/* get specular power */
	nd.specfl = 0;
	nd.u_power = m->oargs.farg[6];
	nd.v_power = m->oargs.farg[7];

	nd.pdot = raynormal(nd.pnorm, r);	/* perturb normal */
	if (nd.pdot < .001)
		nd.pdot = .001;			/* non-zero for dirashik() */
	multcolor(nd.mcolor, r->pcol);		/* modify diffuse color */

	if (bright(nd.scolor) > FTINY) {	/* adjust specular color */
		nd.specfl |= SPA_REFL;
						/* check threshold */
		if (specthresh >= bright(nd.scolor)-FTINY)
			nd.specfl |= SPA_RBLT;
		fres = schlick_fres(nd.pdot);	/* Schick's Fresnel approx */
		for (i = 0; i < 3; i++)
			colval(nd.scolor,i) += (1.-colval(nd.scolor,i))*fres;
	}
	if (r->ro != NULL && isflat(r->ro->otype))
		nd.specfl |= SPA_FLAT;
						/* set up coordinates */
	getacoords_as(&nd);
						/* specular sampling? */
	if ((nd.specfl & (SPA_REFL|SPA_RBLT)) == SPA_REFL)
		ashiksamp(&nd);
						/* diffuse interreflection */
	if (bright(nd.mcolor) > FTINY) {
		copycolor(ctmp, nd.mcolor);	/* modified by material color */		
		if (nd.specfl & SPA_RBLT)	/* add in specular as well? */
			addcolor(ctmp, nd.scolor);
		multambient(ctmp, r, nd.pnorm);
		addcolor(r->rcol, ctmp);	/* add to returned color */
	}
	direct(r, dirashik, &nd);		/* add direct component */

	return(1);
}
Esempio n. 21
0
extern double
sumambient(	/* get interpolated ambient value */
	COLOR  acol,
	RAY  *r,
	FVECT  rn,
	int  al,
	AMBTREE	 *at,
	FVECT  c0,
	double	s
)
{
	double	d, e1, e2, wt, wsum;
	COLOR  ct;
	FVECT  ck0;
	int  i;
	int  j;
	AMBVAL	 *av;

	wsum = 0.0;
					/* do this node */
	for (av = at->alist; av != NULL; av = av->next) {
		double	rn_dot = -2.0;
		if (tracktime)
			av->latick = ambclock;
		/*
		 *  Ambient level test.
		 */
		if (av->lvl > al)	/* list sorted, so this works */
			break;
		if (av->weight < 0.9*r->rweight)
			continue;
		/*
		 *  Ambient radius test.
		 */
		VSUB(ck0, av->pos, r->rop);
		e1 = DOT(ck0, ck0) / (av->rad * av->rad);
		if (e1 > ambacc*ambacc*1.21)
			continue;
		/*
		 *  Direction test using closest normal.
		 */
		d = DOT(av->dir, r->ron);
		if (rn != r->ron) {
			rn_dot = DOT(av->dir, rn);
			if (rn_dot > 1.0-FTINY)
				rn_dot = 1.0-FTINY;
			if (rn_dot >= d-FTINY) {
				d = rn_dot;
				rn_dot = -2.0;
			}
		}
		e2 = (1.0 - d) * r->rweight;
		if (e2 < 0.0)
			e2 = 0.0;
		else if (e1 + e2 > ambacc*ambacc*1.21)
			continue;
		/*
		 *  Ray behind test.
		 */
		d = 0.0;
		for (j = 0; j < 3; j++)
			d += (r->rop[j] - av->pos[j]) *
					(av->dir[j] + r->ron[j]);
		if (d*0.5 < -minarad*ambacc-.001)
			continue;
		/*
		 *  Jittering final test reduces image artifacts.
		 */
		e1 = sqrt(e1);
		e2 = sqrt(e2);
		wt = e1 + e2;
		if (wt > ambacc*(.9+.2*urand(9015+samplendx)))
			continue;
		/*
		 *  Recompute directional error using perturbed normal
		 */
		if (rn_dot > 0.0) {
			e2 = sqrt((1.0 - rn_dot)*r->rweight);
			wt = e1 + e2;
		}
		if (wt <= 1e-3)
			wt = 1e3;
		else
			wt = 1.0 / wt;
		wsum += wt;
		extambient(ct, av, r->rop, rn);
		scalecolor(ct, wt);
		addcolor(acol, ct);
	}
	if (at->kid == NULL)
		return(wsum);
					/* do children */
	s *= 0.5;
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 3; j++) {
			ck0[j] = c0[j];
			if (1<<j & i)
				ck0[j] += s;
			if (r->rop[j] < ck0[j] - OCTSCALE*s)
				break;
			if (r->rop[j] > ck0[j] + (1.0+OCTSCALE)*s)
				break;
		}
		if (j == 3)
			wsum += sumambient(acol, r, rn, al,
						at->kid+i, ck0, s);
	}
	return(wsum);
}
Esempio n. 22
0
static void
ashiksamp(		/* sample anisotropic Ashikhmin-Shirley specular */
	ASHIKDAT  *np
)
{
	RAY  sr;
	FVECT  h;
	double  rv[2], dtmp;
	double  cosph, sinph, costh, sinth;
	int  maxiter, ntrials, nstarget, nstaken;
	int  i;

	if (np->specfl & SPA_BADU ||
			rayorigin(&sr, SPECULAR, np->rp, np->scolor) < 0)
		return;

	nstarget = 1;
	if (specjitter > 1.5) {			/* multiple samples? */
		nstarget = specjitter*np->rp->rweight + .5;
		if (sr.rweight <= minweight*nstarget)
			nstarget = sr.rweight/minweight;
		if (nstarget > 1) {
			dtmp = 1./nstarget;
			scalecolor(sr.rcoef, dtmp);
			sr.rweight *= dtmp;
		} else
			nstarget = 1;
	}
	dimlist[ndims++] = (int)(size_t)np->mp;
	maxiter = MAXITER*nstarget;
	for (nstaken = ntrials = 0; nstaken < nstarget &&
					ntrials < maxiter; ntrials++) {
		if (ntrials)
			dtmp = frandom();
		else
			dtmp = urand(ilhash(dimlist,ndims)+647+samplendx);
		multisamp(rv, 2, dtmp);
		dtmp = 2.*PI * rv[0];
		cosph = sqrt(np->v_power + 1.) * tcos(dtmp);
		sinph = sqrt(np->u_power + 1.) * tsin(dtmp);
		dtmp = 1./sqrt(cosph*cosph + sinph*sinph);
		cosph *= dtmp;
		sinph *= dtmp;
		costh = pow(rv[1], 1./(np->u_power*cosph*cosph+np->v_power*sinph*sinph+1.));
		if (costh <= FTINY)
			continue;
		sinth = sqrt(1. - costh*costh);
		for (i = 0; i < 3; i++)
			h[i] = cosph*sinth*np->u[i] + sinph*sinth*np->v[i] + costh*np->pnorm[i];

		if (nstaken)
			rayclear(&sr);
		dtmp = -2.*DOT(h, np->rp->rdir);
		VSUM(sr.rdir, np->rp->rdir, h, dtmp);				
						/* sample rejection test */
		if (DOT(sr.rdir, np->rp->ron) <= FTINY)
			continue;
		checknorm(sr.rdir);
		rayvalue(&sr);
		multcolor(sr.rcol, sr.rcoef);
		addcolor(np->rp->rcol, sr.rcol);
		++nstaken;
	}
	ndims--;
}
Esempio n. 23
0
static int
redirect(		/* compute n'th ray redirection */
	OBJREC  *m,
	RAY  *r,
	int  n
)
{
	MFUNC  *mf;
	EPNODE  **va;
	FVECT  nsdir;
	RAY  nr;
	double  coef;
	int  j;
					/* set up function */
	mf = getdfunc(m);
	setfunc(m, r);
					/* assign direction variable */
	if (r->rsrc >= 0) {
		SRCREC  *sp = source + source[r->rsrc].sa.sv.sn;

		if (sp->sflags & SDISTANT)
			VCOPY(nsdir, sp->sloc);
		else {
			for (j = 0; j < 3; j++)
				nsdir[j] = sp->sloc[j] - r->rop[j];
			normalize(nsdir);
		}
		multv3(nsdir, nsdir, funcxf.xfm);
		varset("DxA", '=', nsdir[0]/funcxf.sca);
		varset("DyA", '=', nsdir[1]/funcxf.sca);
		varset("DzA", '=', nsdir[2]/funcxf.sca);
	} else {
		varset("DxA", '=', 0.0);
		varset("DyA", '=', 0.0);
		varset("DzA", '=', 0.0);
	}
					/* compute coefficient */
	errno = 0;
	va = mf->ep + 4*n;
	coef = evalue(va[0]);
	if ((errno == EDOM) | (errno == ERANGE))
		goto computerr;
	setcolor(nr.rcoef, coef, coef, coef);
	if (rayorigin(&nr, TRANS, r, nr.rcoef) < 0)
		return(0);
	va++;				/* compute direction */
	for (j = 0; j < 3; j++) {
		nr.rdir[j] = evalue(va[j]);
		if (errno == EDOM || errno == ERANGE)
			goto computerr;
	}
	if (mf->fxp != &unitxf)
		multv3(nr.rdir, nr.rdir, mf->fxp->xfm);
	if (r->rox != NULL)
		multv3(nr.rdir, nr.rdir, r->rox->f.xfm);
	if (normalize(nr.rdir) == 0.0)
		goto computerr;
					/* compute value */
	if (r->rsrc >= 0)
		nr.rsrc = source[r->rsrc].sa.sv.sn;
	rayvalue(&nr);
	multcolor(nr.rcol, nr.rcoef);
	addcolor(r->rcol, nr.rcol);
	if (r->ro != NULL && isflat(r->ro->otype))
		r->rt = r->rot + nr.rt;
	return(1);
computerr:
	objerror(m, WARNING, "compute error");
	return(-1);
}
Esempio n. 24
0
static int
ambsample(				/* initial ambient division sample */
	AMBHEMI	*hp,
	int	i,
	int	j,
	int	n
)
{
	AMBSAMP	*ap = &ambsam(hp,i,j);
	RAY	ar;
	int	hlist[3], ii;
	double	spt[2], zd;
					/* generate hemispherical sample */
					/* ambient coefficient for weight */
	if (ambacc > FTINY)
		setcolor(ar.rcoef, AVGREFL, AVGREFL, AVGREFL);
	else
		copycolor(ar.rcoef, hp->acoef);
	if (rayorigin(&ar, AMBIENT, hp->rp, ar.rcoef) < 0)
		return(0);
	if (ambacc > FTINY) {
		multcolor(ar.rcoef, hp->acoef);
		scalecolor(ar.rcoef, 1./AVGREFL);
	}
	hlist[0] = hp->rp->rno;
	hlist[1] = j;
	hlist[2] = i;
	multisamp(spt, 2, urand(ilhash(hlist,3)+n));
resample:
	SDsquare2disk(spt, (j+spt[1])/hp->ns, (i+spt[0])/hp->ns);
	zd = sqrt(1. - spt[0]*spt[0] - spt[1]*spt[1]);
	for (ii = 3; ii--; )
		ar.rdir[ii] =	spt[0]*hp->ux[ii] +
				spt[1]*hp->uy[ii] +
				zd*hp->rp->ron[ii];
	checknorm(ar.rdir);
					/* avoid coincident samples */
	if (!n && ambcollision(hp, i, j, ar.rdir)) {
		spt[0] = frandom(); spt[1] = frandom();
		goto resample;		/* reject this sample */
	}
	dimlist[ndims++] = AI(hp,i,j) + 90171;
	rayvalue(&ar);			/* evaluate ray */
	ndims--;
	zd = raydistance(&ar);
	if (zd <= FTINY)
		return(0);		/* should never happen */
	multcolor(ar.rcol, ar.rcoef);	/* apply coefficient */
	if (zd*ap->d < 1.0)		/* new/closer distance? */
		ap->d = 1.0/zd;
	if (!n) {			/* record first vertex & value */
		if (zd > 10.0*thescene.cusize + 1000.)
			zd = 10.0*thescene.cusize + 1000.;
		VSUM(ap->p, ar.rorg, ar.rdir, zd);
		copycolor(ap->v, ar.rcol);
	} else {			/* else update recorded value */
		hp->acol[RED] -= colval(ap->v,RED);
		hp->acol[GRN] -= colval(ap->v,GRN);
		hp->acol[BLU] -= colval(ap->v,BLU);
		zd = 1.0/(double)(n+1);
		scalecolor(ar.rcol, zd);
		zd *= (double)n;
		scalecolor(ap->v, zd);
		addcolor(ap->v, ar.rcol);
	}
	addcolor(hp->acol, ap->v);	/* add to our sum */
	return(1);
}
Esempio n. 25
0
void photonDensity (PhotonMap *pmap, RAY *ray, COLOR irrad)
/* Photon density estimate. Returns irradiance at ray -> rop. */
{
   unsigned                      i;
   float                         r2;
   COLOR                         flux;
   Photon                        *photon;
   const PhotonSearchQueueNode   *sqn;
 
   setcolor(irrad, 0, 0, 0);

   if (!pmap -> maxGather) 
      return;
      
   /* Ignore sources */
   if (ray -> ro && islight(objptr(ray -> ro -> omod) -> otype)) 
      return;
         
   findPhotons(pmap, ray);
   
   /* Need at least 2 photons */
   if (pmap -> squeue.tail < 2) {
#ifdef PMAP_NONEFOUND   
      sprintf(errmsg, "no photons found on %s at (%.3f, %.3f, %.3f)", 
              ray -> ro ? ray -> ro -> oname : "<null>",
              ray -> rop [0], ray -> rop [1], ray -> rop [2]);
      error(WARNING, errmsg);
#endif      

      return;
   }

   if (pmap -> minGather == pmap -> maxGather) {
      /* No bias compensation. Just do a plain vanilla estimate */
      sqn = pmap -> squeue.node + 1;
      
      /* Average radius^2 between furthest two photons to improve accuracy */
      r2 = max(sqn -> dist2, (sqn + 1) -> dist2);
      r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2));
      
      /* Skip the extra photon */
      for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) {
         photon = getNearestPhoton(&pmap -> squeue, sqn -> idx);
         getPhotonFlux(photon, flux);         
#ifdef PMAP_EPANECHNIKOV
         /* Apply Epanechnikov kernel to photon flux based on photon dist */
         scalecolor(flux, 2 * (1 - sqn -> dist2 / r2));
#endif   
         addcolor(irrad, flux);
      }
      
      /* Divide by search area PI * r^2, 1 / PI required as ambient 
         normalisation factor */         
      scalecolor(irrad, 1 / (PI * PI * r2)); 
      
      return;
   }
   else 
      /* Apply bias compensation to density estimate */
      biasComp(pmap, irrad);
}
Esempio n. 26
0
int
m_brdf(			/* color a ray that hit a BRDTfunc material */
	OBJREC  *m,
	RAY  *r
)
{
	int  hitfront = 1;
	BRDFDAT  nd;
	RAY  sr;
	double  mirtest=0, mirdist=0;
	double  transtest=0, transdist=0;
	int  hasrefl, hastrans;
	int  hastexture;
	COLOR  ctmp;
	FVECT  vtmp;
	double  d;
	MFUNC  *mf;
	int  i;
						/* check arguments */
	if ((m->oargs.nsargs < 10) | (m->oargs.nfargs < 9))
		objerror(m, USER, "bad # arguments");
	nd.mp = m;
	nd.pr = r;
						/* dummy values */
	nd.rspec = nd.tspec = 1.0;
	nd.trans = 0.5;
						/* diffuse reflectance */
	if (r->rod > 0.0)
		setcolor(nd.rdiff, m->oargs.farg[0],
				m->oargs.farg[1],
				m->oargs.farg[2]);
	else
		setcolor(nd.rdiff, m->oargs.farg[3],
				m->oargs.farg[4],
				m->oargs.farg[5]);
						/* diffuse transmittance */
	setcolor(nd.tdiff, m->oargs.farg[6],
			m->oargs.farg[7],
			m->oargs.farg[8]);
						/* get modifiers */
	raytexture(r, m->omod);
	hastexture = DOT(r->pert,r->pert) > FTINY*FTINY;
	if (hastexture) {			/* perturb normal */
		nd.pdot = raynormal(nd.pnorm, r);
	} else {
		VCOPY(nd.pnorm, r->ron);
		nd.pdot = r->rod;
	}
	if (r->rod < 0.0) {			/* orient perturbed values */
		nd.pdot = -nd.pdot;
		for (i = 0; i < 3; i++) {
			nd.pnorm[i] = -nd.pnorm[i];
			r->pert[i] = -r->pert[i];
		}
		hitfront = 0;
	}
	copycolor(nd.mcolor, r->pcol);		/* get pattern color */
	multcolor(nd.rdiff, nd.mcolor);		/* modify diffuse values */
	multcolor(nd.tdiff, nd.mcolor);
	hasrefl = bright(nd.rdiff) > FTINY;
	hastrans = bright(nd.tdiff) > FTINY;
						/* load cal file */
	nd.dp = NULL;
	mf = getfunc(m, 9, 0x3f, 0);
						/* compute transmitted ray */
	setbrdfunc(&nd);
	errno = 0;
	setcolor(ctmp, evalue(mf->ep[3]),
			evalue(mf->ep[4]),
			evalue(mf->ep[5]));
	if ((errno == EDOM) | (errno == ERANGE))
		objerror(m, WARNING, "compute error");
	else if (rayorigin(&sr, TRANS, r, ctmp) == 0) {
		if (!(r->crtype & SHADOW) && hastexture) {
						/* perturb direction */
			VSUM(sr.rdir, r->rdir, r->pert, -.75);
			if (normalize(sr.rdir) == 0.0) {
				objerror(m, WARNING, "illegal perturbation");
				VCOPY(sr.rdir, r->rdir);
			}
		} else {
			VCOPY(sr.rdir, r->rdir);
		}
		rayvalue(&sr);
		multcolor(sr.rcol, sr.rcoef);
		addcolor(r->rcol, sr.rcol);
		if (!hastexture) {
			transtest = 2.0*bright(sr.rcol);
			transdist = r->rot + sr.rt;
		}
	}
	if (r->crtype & SHADOW)			/* the rest is shadow */
		return(1);
						/* compute reflected ray */
	setbrdfunc(&nd);
	errno = 0;
	setcolor(ctmp, evalue(mf->ep[0]),
			evalue(mf->ep[1]),
			evalue(mf->ep[2]));
	if ((errno == EDOM) | (errno == ERANGE))
		objerror(m, WARNING, "compute error");
	else if (rayorigin(&sr, REFLECTED, r, ctmp) == 0) {
		VSUM(sr.rdir, r->rdir, nd.pnorm, 2.*nd.pdot);
		checknorm(sr.rdir);
		rayvalue(&sr);
		multcolor(sr.rcol, sr.rcoef);
		addcolor(r->rcol, sr.rcol);
		if (!hastexture && r->ro != NULL && isflat(r->ro->otype)) {
			mirtest = 2.0*bright(sr.rcol);
			mirdist = r->rot + sr.rt;
		}
	}
						/* compute ambient */
	if (hasrefl) {
		if (!hitfront)
			flipsurface(r);
		copycolor(ctmp, nd.rdiff);
		multambient(ctmp, r, nd.pnorm);
		addcolor(r->rcol, ctmp);	/* add to returned color */
		if (!hitfront)
			flipsurface(r);
	}
	if (hastrans) {				/* from other side */
		if (hitfront)
			flipsurface(r);
		vtmp[0] = -nd.pnorm[0];
		vtmp[1] = -nd.pnorm[1];
		vtmp[2] = -nd.pnorm[2];
		copycolor(ctmp, nd.tdiff);
		multambient(ctmp, r, vtmp);
		addcolor(r->rcol, ctmp);
		if (hitfront)
			flipsurface(r);
	}
	if (hasrefl | hastrans || m->oargs.sarg[6][0] != '0')
		direct(r, dirbrdf, &nd);	/* add direct component */

	d = bright(r->rcol);			/* set effective distance */
	if (transtest > d)
		r->rt = transdist;
	else if (mirtest > d)
		r->rt = mirdist;

	return(1);
}
Esempio n. 27
0
int
m_brdf2(			/* color a ray that hit a BRDF material */
	OBJREC  *m,
	RAY  *r
)
{
	BRDFDAT  nd;
	COLOR  ctmp;
	FVECT  vtmp;
	double  dtmp;
						/* always a shadow */
	if (r->crtype & SHADOW)
		return(1);
						/* check arguments */
	if ((m->oargs.nsargs < (hasdata(m->otype)?4:2)) | (m->oargs.nfargs <
			((m->otype==MAT_TFUNC)|(m->otype==MAT_TDATA)?6:4)))
		objerror(m, USER, "bad # arguments");
						/* check for back side */
	if (r->rod < 0.0) {
		if (!backvis) {
			raytrans(r);
			return(1);
		}
		raytexture(r, m->omod);
		flipsurface(r);			/* reorient if backvis */
	} else
		raytexture(r, m->omod);

	nd.mp = m;
	nd.pr = r;
						/* get material color */
	setcolor(nd.mcolor, m->oargs.farg[0],
			m->oargs.farg[1],
			m->oargs.farg[2]);
						/* get specular component */
	nd.rspec = m->oargs.farg[3];
						/* compute transmittance */
	if ((m->otype == MAT_TFUNC) | (m->otype == MAT_TDATA)) {
		nd.trans = m->oargs.farg[4]*(1.0 - nd.rspec);
		nd.tspec = nd.trans * m->oargs.farg[5];
		dtmp = nd.trans - nd.tspec;
		setcolor(nd.tdiff, dtmp, dtmp, dtmp);
	} else {
		nd.tspec = nd.trans = 0.0;
		setcolor(nd.tdiff, 0.0, 0.0, 0.0);
	}
						/* compute reflectance */
	dtmp = 1.0 - nd.trans - nd.rspec;
	setcolor(nd.rdiff, dtmp, dtmp, dtmp);
	nd.pdot = raynormal(nd.pnorm, r);	/* perturb normal */
	multcolor(nd.mcolor, r->pcol);		/* modify material color */
	multcolor(nd.rdiff, nd.mcolor);
	multcolor(nd.tdiff, nd.mcolor);
						/* load auxiliary files */
	if (hasdata(m->otype)) {
		nd.dp = getdata(m->oargs.sarg[1]);
		getfunc(m, 2, 0, 0);
	} else {
		nd.dp = NULL;
		getfunc(m, 1, 0, 0);
	}
						/* compute ambient */
	if (nd.trans < 1.0-FTINY) {
		copycolor(ctmp, nd.mcolor);	/* modified by material color */
		scalecolor(ctmp, 1.0-nd.trans);
		multambient(ctmp, r, nd.pnorm);
		addcolor(r->rcol, ctmp);	/* add to returned color */
	}
	if (nd.trans > FTINY) {		/* from other side */
		flipsurface(r);
		vtmp[0] = -nd.pnorm[0];
		vtmp[1] = -nd.pnorm[1];
		vtmp[2] = -nd.pnorm[2];
		copycolor(ctmp, nd.mcolor);
		scalecolor(ctmp, nd.trans);
		multambient(ctmp, r, vtmp);
		addcolor(r->rcol, ctmp);
		flipsurface(r);
	}
						/* add direct component */
	direct(r, dirbrdf, &nd);

	return(1);
}
Esempio n. 28
0
static void
dirbrdf(		/* compute source contribution */
	COLOR  cval,			/* returned coefficient */
	void  *nnp,		/* material data */
	FVECT  ldir,			/* light source direction */
	double  omega			/* light source size */
)
{
	BRDFDAT *np = nnp;
	double  ldot;
	double  dtmp;
	COLOR  ctmp;
	FVECT  ldx;
	static double  vldx[5], pt[MAXDIM];
	char	**sa;
	int	i;
#define lddx (vldx+1)

	setcolor(cval, 0.0, 0.0, 0.0);
	
	ldot = DOT(np->pnorm, ldir);

	if (ldot <= FTINY && ldot >= -FTINY)
		return;		/* too close to grazing */

	if (ldot < 0.0 ? np->trans <= FTINY : np->trans >= 1.0-FTINY)
		return;		/* wrong side */

	if (ldot > 0.0) {
		/*
		 *  Compute and add diffuse reflected component to returned
		 *  color.  The diffuse reflected component will always be
		 *  modified by the color of the material.
		 */
		copycolor(ctmp, np->rdiff);
		dtmp = ldot * omega / PI;
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	} else {
		/*
		 *  Diffuse transmitted component.
		 */
		copycolor(ctmp, np->tdiff);
		dtmp = -ldot * omega / PI;
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	}
	if (ldot > 0.0 ? np->rspec <= FTINY : np->tspec <= FTINY)
		return;		/* diffuse only */
					/* set up function */
	setbrdfunc(np);
	sa = np->mp->oargs.sarg;
	errno = 0;
					/* transform light vector */
	multv3(ldx, ldir, funcxf.xfm);
	for (i = 0; i < 3; i++)
		lddx[i] = ldx[i]/funcxf.sca;
	lddx[3] = omega;
					/* compute BRTDF */
	if (np->mp->otype == MAT_BRTDF) {
		if (sa[6][0] == '0')		/* special case */
			colval(ctmp,RED) = 0.0;
		else
			colval(ctmp,RED) = funvalue(sa[6], 4, lddx);
		if (sa[7][0] == '0')
			colval(ctmp,GRN) = 0.0;
		else if (!strcmp(sa[7],sa[6]))
			colval(ctmp,GRN) = colval(ctmp,RED);
		else
			colval(ctmp,GRN) = funvalue(sa[7], 4, lddx);
		if (!strcmp(sa[8],sa[6]))
			colval(ctmp,BLU) = colval(ctmp,RED);
		else if (!strcmp(sa[8],sa[7]))
			colval(ctmp,BLU) = colval(ctmp,GRN);
		else
			colval(ctmp,BLU) = funvalue(sa[8], 4, lddx);
		dtmp = bright(ctmp);
	} else if (np->dp == NULL) {
		dtmp = funvalue(sa[0], 4, lddx);
		setcolor(ctmp, dtmp, dtmp, dtmp);
	} else {
		for (i = 0; i < np->dp->nd; i++)
			pt[i] = funvalue(sa[3+i], 4, lddx);
		vldx[0] = datavalue(np->dp, pt);
		dtmp = funvalue(sa[0], 5, vldx);
		setcolor(ctmp, dtmp, dtmp, dtmp);
	}
	if ((errno == EDOM) | (errno == ERANGE)) {
		objerror(np->mp, WARNING, "compute error");
		return;
	}
	if (dtmp <= FTINY)
		return;
	if (ldot > 0.0) {
		/*
		 *  Compute reflected non-diffuse component.
		 */
		if ((np->mp->otype == MAT_MFUNC) | (np->mp->otype == MAT_MDATA))
			multcolor(ctmp, np->mcolor);
		dtmp = ldot * omega * np->rspec;
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	} else {
		/*
		 *  Compute transmitted non-diffuse component.
		 */
		if ((np->mp->otype == MAT_TFUNC) | (np->mp->otype == MAT_TDATA))
			multcolor(ctmp, np->mcolor);
		dtmp = -ldot * omega * np->tspec;
		scalecolor(ctmp, dtmp);
		addcolor(cval, ctmp);
	}
#undef lddx
}
Esempio n. 29
0
extern void			/* add sources smaller than rad to computed subimage */
drawsources(
	COLOR	*pic[],				/* subimage pixel value array */
	float	*zbf[],				/* subimage distance array (opt.) */
	int	x0,				/* origin and size of subimage */
	int	xsiz,
	int	y0,
	int	ysiz
)
{
	RREAL	spoly[MAXVERT][2], ppoly[MAXVERT][2];
	int	nsv, npv;
	int	xmin, xmax, ymin, ymax, x, y;
	RREAL	cxy[2];
	double	w;
	RAY	sr;
	register SPLIST	*sp;
	register int	i;
					/* check each source in our list */
	for (sp = sphead; sp != NULL; sp = sp->next) {
					/* clip source poly to subimage */
		nsv = box_clip_poly(sp->vl, sp->nv,
				(double)x0/hres, (double)(x0+xsiz)/hres,
				(double)y0/vres, (double)(y0+ysiz)/vres, spoly);
		if (!nsv)
			continue;
					/* find common subimage (BBox) */
		xmin = x0 + xsiz; xmax = x0;
		ymin = y0 + ysiz; ymax = y0;
		for (i = 0; i < nsv; i++) {
			if ((double)xmin/hres > spoly[i][0])
				xmin = spoly[i][0]*hres + FTINY;
			if ((double)xmax/hres < spoly[i][0])
				xmax = spoly[i][0]*hres - FTINY;
			if ((double)ymin/vres > spoly[i][1])
				ymin = spoly[i][1]*vres + FTINY;
			if ((double)ymax/vres < spoly[i][1])
				ymax = spoly[i][1]*vres - FTINY;
		}
					/* evaluate each pixel in BBox */
		for (y = ymin; y <= ymax; y++)
			for (x = xmin; x <= xmax; x++) {
							/* subarea for pixel */
				npv = box_clip_poly(spoly, nsv,
						(double)x/hres, (x+1.)/hres,
						(double)y/vres, (y+1.)/vres,
						ppoly);
				if (!npv)
					continue;	/* no overlap */
				convex_center(ppoly, npv, cxy);
				if ((sr.rmax = viewray(sr.rorg,sr.rdir,&ourview,
						cxy[0],cxy[1])) < -FTINY)
					continue;	/* not in view */
				if (source[sp->sn].sflags & SSPOT &&
						spotout(&sr, source[sp->sn].sl.s))
					continue;	/* outside spot */
				rayorigin(&sr, SHADOW, NULL, NULL);
				sr.rsrc = sp->sn;
				rayvalue(&sr);		/* compute value */
				if (bright(sr.rcol) <= FTINY)
					continue;	/* missed/blocked */
							/* modify pixel */
				w = poly_area(ppoly, npv) * hres * vres;
				if (zbf[y-y0] != NULL &&
						sr.rt < 0.99*zbf[y-y0][x-x0]) {
					zbf[y-y0][x-x0] = sr.rt;
				} else if (!bigdiff(sr.rcol, pic[y-y0][x-x0],
						0.01)) { /* source sample */
					scalecolor(pic[y-y0][x-x0], w);
					continue;
				}
				scalecolor(sr.rcol, w);
				scalecolor(pic[y-y0][x-x0], 1.-w);
				addcolor(pic[y-y0][x-x0], sr.rcol);
			}
	}
}
Esempio n. 30
0
void buildPhotonMap (PhotonMap *pmap, double *photonFlux, 
                     PhotonPrimaryIdx *primaryOfs, unsigned nproc)
{
   unsigned long  n, nCheck = 0;
   unsigned       i;
   Photon         *p;
   COLOR          flux;
   char           nuHeapFname [sizeof(PMAP_TMPFNAME)];
   FILE           *nuHeap;
   /* Need double here to reduce summation errors */
   double         avgFlux [3] = {0, 0, 0}, CoG [3] = {0, 0, 0}, CoGdist = 0;
   FVECT          d;
   
   if (!pmap)
      error(INTERNAL, "undefined photon map in buildPhotonMap");
      
   /* Get number of photons from heapfile size */
   if (fseek(pmap -> heap, 0, SEEK_END) < 0)
      error(SYSTEM, "failed seek to end of photon heap in buildPhotonMap");
   pmap -> numPhotons = ftell(pmap -> heap) / sizeof(Photon);
   
   if (!pmap -> numPhotons)
      error(INTERNAL, "empty photon map in buildPhotonMap");   

   if (!pmap -> heap)
      error(INTERNAL, "no heap in buildPhotonMap");

#ifdef DEBUG_PMAP
   eputs("Checking photon heap consistency...\n");
   checkPhotonHeap(pmap -> heap);
   
   sprintf(errmsg, "Heap contains %ld photons\n", pmap -> numPhotons);
   eputs(errmsg);
#endif

   /* Allocate heap buffa */
   if (!pmap -> heapBuf) {
      pmap -> heapBufSize = PMAP_HEAPBUFSIZE;
      pmap -> heapBuf = calloc(pmap -> heapBufSize, sizeof(Photon));
      if (!pmap -> heapBuf)
         error(SYSTEM, "failed to allocate postprocessed photon heap in" 
               "buildPhotonMap");
   }

   /* We REALLY don't need yet another @%&*! heap just to hold the scaled
    * photons, but can't think of a quicker fix... */
   mktemp(strcpy(nuHeapFname, PMAP_TMPFNAME));
   if (!(nuHeap = fopen(nuHeapFname, "w+b")))
      error(SYSTEM, "failed to open postprocessed photon heap in "
            "buildPhotonMap");
            
   rewind(pmap -> heap);

#ifdef DEBUG_PMAP 
   eputs("Postprocessing photons...\n");
#endif
   
   while (!feof(pmap -> heap)) {   
#ifdef DEBUG_PMAP 
      printf("Reading %lu at %lu... ", pmap -> heapBufSize, ftell(pmap->heap));
#endif      
      pmap -> heapBufLen = fread(pmap -> heapBuf, sizeof(Photon), 
                                 pmap -> heapBufSize, pmap -> heap);
#ifdef DEBUG_PMAP                                 
      printf("Got %lu\n", pmap -> heapBufLen);
#endif      

      if (ferror(pmap -> heap))
         error(SYSTEM, "failed to read photon heap in buildPhotonMap");

      for (n = pmap -> heapBufLen, p = pmap -> heapBuf; n; n--, p++) {
         /* Update min and max pos and set photon flux */
         for (i = 0; i <= 2; i++) {
            if (p -> pos [i] < pmap -> minPos [i]) 
               pmap -> minPos [i] = p -> pos [i];
            else if (p -> pos [i] > pmap -> maxPos [i]) 
               pmap -> maxPos [i] = p -> pos [i];   

            /* Update centre of gravity with photon position */                 
            CoG [i] += p -> pos [i];                  
         }  
         
         if (primaryOfs)
            /* Linearise photon primary index from subprocess index using the
             * per-subprocess offsets in primaryOfs */
            p -> primary += primaryOfs [p -> proc];
         
         /* Scale photon's flux (hitherto normalised to 1 over RGB); in
          * case of a contrib photon map, this is done per light source,
          * and photonFlux is assumed to be an array */
         getPhotonFlux(p, flux);            

         if (photonFlux) {
            scalecolor(flux, photonFlux [isContribPmap(pmap) ? 
                                            photonSrcIdx(pmap, p) : 0]);
            setPhotonFlux(p, flux);
         }

         /* Update average photon flux; need a double here */
         addcolor(avgFlux, flux);
      }
         
      /* Write modified photons to new heap */
      fwrite(pmap -> heapBuf, sizeof(Photon), pmap -> heapBufLen, nuHeap);
                
      if (ferror(nuHeap))
         error(SYSTEM, "failed postprocessing photon flux in "
               "buildPhotonMap");
      
      nCheck += pmap -> heapBufLen;
   }

#ifdef DEBUG_PMAP
   if (nCheck < pmap -> numPhotons)
      error(INTERNAL, "truncated photon heap in buildPhotonMap");
#endif
   
   /* Finalise average photon flux */
   scalecolor(avgFlux, 1.0 / pmap -> numPhotons);
   copycolor(pmap -> photonFlux, avgFlux);

   /* Average photon positions to get centre of gravity */
   for (i = 0; i < 3; i++)
      pmap -> CoG [i] = CoG [i] /= pmap -> numPhotons;
      
   rewind(pmap -> heap);
   
   /* Compute average photon distance to centre of gravity */
   while (!feof(pmap -> heap)) {
      pmap -> heapBufLen = fread(pmap -> heapBuf, sizeof(Photon), 
                                 pmap -> heapBufSize, pmap -> heap);
      
      for (n = pmap -> heapBufLen, p = pmap -> heapBuf; n; n--, p++) {
         VSUB(d, p -> pos, CoG);
         CoGdist += DOT(d, d);
      }
   }   

   pmap -> CoGdist = CoGdist /= pmap -> numPhotons;

   /* Swap heaps, discarding unscaled photons */
   fclose(pmap -> heap);
   unlink(pmap -> heapFname);
   pmap -> heap = nuHeap;
   strcpy(pmap -> heapFname, nuHeapFname);
   
#ifdef PMAP_OOC
   OOC_BuildPhotonMap(pmap, nproc);
#else
   kdT_BuildPhotonMap(pmap);
#endif

   /* Trash heap and its buffa */
   free(pmap -> heapBuf);
   fclose(pmap -> heap);
   unlink(pmap -> heapFname);
   pmap -> heap = NULL;
   pmap -> heapBuf = NULL;
}