Ejemplo n.º 1
0
int
o_face(		/* determine if face intersects cube */
	OBJREC  *o,
	CUBE  *cu
)
{
	FVECT  cumin, cumax;
	FVECT  v1, v2;
	double  d1, d2;
	int  vloc;
	register FACE  *f;
	register int  i, j;
				/* get face arguments */
	f = getface(o);
	if (f->area == 0.0)		/* empty face */
		return(O_MISS);
					/* compute cube boundaries */
	for (j = 0; j < 3; j++)
		cumax[j] = (cumin[j] = cu->cuorg[j]-FTINY)
				+ cu->cusize + 2.0*FTINY;

	vloc = ABOVE | BELOW;		/* check vertices */
	for (i = 0; i < f->nv; i++)
		if ( (j = plocate(VERTEX(f,i), cumin, cumax)) )
			vloc &= j;
		else
			return(O_HIT);	/* vertex inside */

	if (vloc)			/* all to one side */
		return(O_MISS);
	
	for (i = 0; i < f->nv; i++) {	/* check edges */
		if ((j = i + 1) >= f->nv)
			j = 0;			/* wrap around */
		VCOPY(v1, VERTEX(f,i));		/* clip modifies */
		VCOPY(v2, VERTEX(f,j));		/* the vertices! */
		if (clip(v1, v2, cumin, cumax))
			return(O_HIT);		/* edge inside */
	}
					/* see if cube cuts plane */
	for (j = 0; j < 3; j++)
		if (f->norm[j] > 0.0) {
			v1[j] = cumin[j];
			v2[j] = cumax[j];
		} else {
			v1[j] = cumax[j];
			v2[j] = cumin[j];
		}
	if ((d1 = DOT(v1, f->norm) - f->offset) > FTINY)
		return(O_MISS);
	if ((d2 = DOT(v2, f->norm) - f->offset) < -FTINY)
		return(O_MISS);
					/* intersect face */
	for (j = 0; j < 3; j++)
		v1[j] = (v1[j]*d2 - v2[j]*d1)/(d2 - d1);
	if (inface(v1, f))
		return(O_HIT);
	
	return(O_MISS);		/* no intersection */
}
Ejemplo n.º 2
0
static int				/* cast source ray to first blocker */
castshadow(int sn, FVECT rorg, FVECT rdir)
{
	RAY     rt;
	
	VCOPY(rt.rorg, rorg);
	VCOPY(rt.rdir, rdir);
	rt.rmax = 0;
	rayorigin(&rt, PRIMARY, NULL, NULL);
					/* check for intersection */
	while (localhit(&rt, &thescene)) {
		RAY	rt1 = rt;	/* pretend we were aimed at source */
		rt1.crtype |= rt1.rtype = SHADOW;
		rt1.rdir[0] = -rt.rdir[0];
		rt1.rdir[1] = -rt.rdir[1];
		rt1.rdir[2] = -rt.rdir[2];
		rt1.rod = -rt.rod;
		VSUB(rt1.rorg, rt.rop, rt.rdir);
		rt1.rot = 1.;
		rt1.rsrc = sn;
					/* record blocker */
		if (srcblocker(&rt1))
			return(1);
					/* move past failed blocker */
		VSUM(rt.rorg, rt.rop, rt.rdir, FTINY);
		rayclear(&rt);		/* & try again... */
	}
	return(0);			/* found no blockers */
}
Ejemplo n.º 3
0
/* Get a vector from stdin */
int
getvec(FVECT vec)
{
	float	vf[3];
	double	vd[3];
	char	buf[32];
	int	i;

	switch (inpfmt) {
	case 'a':					/* ascii */
		for (i = 0; i < 3; i++) {
			if (fgetword(buf, sizeof(buf), stdin) == NULL ||
					!isflt(buf))
				return(-1);
			vec[i] = atof(buf);
		}
		break;
	case 'f':					/* binary float */
		if (fread((char *)vf, sizeof(float), 3, stdin) != 3)
			return(-1);
		VCOPY(vec, vf);
		break;
	case 'd':					/* binary double */
		if (fread((char *)vd, sizeof(double), 3, stdin) != 3)
			return(-1);
		VCOPY(vec, vd);
		break;
	default:
		error(CONSISTENCY, "botched input format");
	}
	return(0);
}
Ejemplo n.º 4
0
int
getinterest(		/* get area of interest */
	char  *s,
	int  direc,
	FVECT  vec,
	double  *mp
)
{
	int  x, y;
	RAY  thisray;
	int  i;

	if (sscanf(s, "%lf", mp) != 1)
		*mp = 1.0;
	else if (*mp < -FTINY)		/* negative zoom is reduction */
		*mp = -1.0 / *mp;
	else if (*mp <= FTINY) {	/* too small */
		error(COMMAND, "illegal magnification");
		return(-1);
	}
	if (!sscanvec(sskip(s), vec)) {
		if (dev->getcur == NULL)
			return(-1);
		(*dev->comout)("Pick view center\n");
		if ((*dev->getcur)(&x, &y) == ABORT)
			return(-1);
		if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir,
			&ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) {
			error(COMMAND, "not on image");
			return(-1);
		}
		if (!direc || ourview.type == VT_PAR) {
			rayorigin(&thisray, PRIMARY, NULL, NULL);
			if (!localhit(&thisray, &thescene)) {
				error(COMMAND, "not a local object");
				return(-1);
			}
		}
		if (direc)
			if (ourview.type == VT_PAR)
				for (i = 0; i < 3; i++)
					vec[i] = thisray.rop[i] - ourview.vp[i];
			else
				VCOPY(vec, thisray.rdir);
		else
			VCOPY(vec, thisray.rop);
	} else if (direc) {
		for (i = 0; i < 3; i++)
			vec[i] -= ourview.vp[i];
		if (normalize(vec) == 0.0) {
			error(COMMAND, "point at view origin");
			return(-1);
		}
	}
	return(0);
}
Ejemplo n.º 5
0
extern int
o_face(		/* compute intersection with polygonal face */
	OBJREC  *o,
	register RAY  *r
)
{
	double  rdot;		/* direction . normal */
	double  t;		/* distance to intersection */
	FVECT  pisect;		/* intersection point */
	register FACE  *f;	/* face record */

	f = getface(o);
		
	/*
	 *  First, we find the distance to the plane containing the
	 *  face.  If this distance is less than zero or greater
	 *  than a previous intersection, we return.  Otherwise,
	 *  we determine whether in fact the ray intersects the
	 *  face.  The ray intersects the face if the
	 *  point of intersection with the plane of the face
	 *  is inside the face.
	 */
						/* compute dist. to plane */
	rdot = -DOT(r->rdir, f->norm);
	if (rdot <= FTINY && rdot >= -FTINY)	/* ray parallels plane */
		t = FHUGE;
	else
		t = (DOT(r->rorg, f->norm) - f->offset) / rdot;
	
	if (t <= FTINY || t >= r->rot)		/* not good enough */
		return(0);
						/* compute intersection */
	VSUM(pisect, r->rorg, r->rdir, t);

	if (!inface(pisect, f))			/* ray intersects face? */
		return(0);

	r->ro = o;
	r->rot = t;
	VCOPY(r->rop, pisect);
	VCOPY(r->ron, f->norm);
	r->rod = rdot;
	r->pert[0] = r->pert[1] = r->pert[2] = 0.0;
	r->uv[0] = r->uv[1] = 0.0;
	r->rox = NULL;

	return(1);				/* hit */
}
Ejemplo n.º 6
0
/* Returns photon position as sorting key for OOC_Octree & friends (notably
 * for Morton code generation).
 * !!! Uses type conversion from float via TEMPORARY storage; 
 * !!! THIS IS NOT THREAD SAFE!
 * !!! RETURNED KEY PERSISTS ONLY IF COPIED BEFORE NEXT CALL! */
RREAL *OOC_PhotonKey (const void *p)
{
   static FVECT photonPos; /* Temp storage for type conversion */
   
   VCOPY(photonPos, ((Photon*)p) -> pos);
   return photonPos;
}
Ejemplo n.º 7
0
void OOC_Find1Photon (struct PhotonMap* pmap, const FVECT pos, 
                      const FVECT norm, Photon *photon)
{
   OOC_SearchFilter     filt;
   OOC_FilterData       filtData;
   float                n [3];
   
   /* Lazily init OOC cache */
   if (!pmap -> store.cache)
      OOC_InitPhotonCache(pmap);
   
   /* Set up filter callback */
   filtData.pmap = pmap;
   if (norm)
      VCOPY(n, norm);
   filtData.norm = norm ? n : NULL;   
   filt.data = &filtData;
   filt.func = OOC_FilterPhoton;
   
   pmap -> maxDist2 = OOC_Find1Nearest(&pmap -> store, 
                                       OOC_ROOT(&pmap -> store), 0, 
                                       pmap -> store.org, pmap -> store.size,
                                       pos, &filt, photon, pmap -> maxDist2);

   if (pmap -> maxDist2 < 0)
      error(INTERNAL, "failed 1-NN photon lookup in OOC_Find1Photon");
}
Ejemplo n.º 8
0
extern double
raynormal(		/* compute perturbed normal for ray */
	FVECT  norm,
	RAY  *r
)
{
	double  newdot;
	int  i;

	/*	The perturbation is added to the surface normal to obtain
	 *  the new normal.  If the new normal would affect the surface
	 *  orientation wrt. the ray, a correction is made.  The method is
	 *  still fraught with problems since reflected rays and similar
	 *  directions calculated from the surface normal may spawn rays behind
	 *  the surface.  The only solution is to curb textures at high
	 *  incidence (namely, keep DOT(rdir,pert) < Rdot).
	 */

	for (i = 0; i < 3; i++)
		norm[i] = r->ron[i] + r->pert[i];

	if (normalize(norm) == 0.0) {
		objerror(r->ro, WARNING, "illegal normal perturbation");
		VCOPY(norm, r->ron);
		return(r->rod);
	}
	newdot = -DOT(norm, r->rdir);
	if ((newdot > 0.0) != (r->rod > 0.0)) {		/* fix orientation */
		for (i = 0; i < 3; i++)
			norm[i] += 2.0*newdot*r->rdir[i];
		newdot = -newdot;
	}
	return(newdot);
}
Ejemplo n.º 9
0
/* Compute anisotropic radii and eigenvector directions */
static void
eigenvectors(FVECT uv[2], float ra[2], FVECT hessian[3])
{
	double	hess2[2][2];
	FVECT	a, b;
	double	evalue[2], slope1, xmag1;
	int	i;
					/* project Hessian to sample plane */
	for (i = 3; i--; ) {
		a[i] = DOT(hessian[i], uv[0]);
		b[i] = DOT(hessian[i], uv[1]);
	}
	hess2[0][0] = DOT(uv[0], a);
	hess2[0][1] = DOT(uv[0], b);
	hess2[1][0] = DOT(uv[1], a);
	hess2[1][1] = DOT(uv[1], b);
					/* compute eigenvalue(s) */
	i = quadratic(evalue, 1.0, -hess2[0][0]-hess2[1][1],
			hess2[0][0]*hess2[1][1]-hess2[0][1]*hess2[1][0]);
	if (i == 1)			/* double-root (circle) */
		evalue[1] = evalue[0];
	if (!i || ((evalue[0] = fabs(evalue[0])) <= FTINY*FTINY) |
			((evalue[1] = fabs(evalue[1])) <= FTINY*FTINY) ) {
		ra[0] = ra[1] = maxarad;
		return;
	}
	if (evalue[0] > evalue[1]) {
		ra[0] = sqrt(sqrt(4.0/evalue[0]));
		ra[1] = sqrt(sqrt(4.0/evalue[1]));
		slope1 = evalue[1];
	} else {
		ra[0] = sqrt(sqrt(4.0/evalue[1]));
		ra[1] = sqrt(sqrt(4.0/evalue[0]));
		slope1 = evalue[0];
	}
					/* compute unit eigenvectors */
	if (fabs(hess2[0][1]) <= FTINY)
		return;			/* uv OK as is */
	slope1 = (slope1 - hess2[0][0]) / hess2[0][1];
	xmag1 = sqrt(1.0/(1.0 + slope1*slope1));
	for (i = 3; i--; ) {
		b[i] = xmag1*uv[0][i] + slope1*xmag1*uv[1][i];
		a[i] = slope1*xmag1*uv[0][i] - xmag1*uv[1][i];
	}
	VCOPY(uv[0], a);
	VCOPY(uv[1], b);
}
Ejemplo n.º 10
0
Archivo: rv2.c Proyecto: NREL/Radiance
void
getorigin(				/* origin viewpoint */
	char  *s
)
{
	VIEW	nv = ourview;
	double	d;
					/* get new view origin */
	if (sscanf(s, "%lf %lf", &d, &d) == 1) {
					/* just moving some distance */
		VSUM(nv.vp, nv.vp, nv.vdir, d);
	} else if (!sscanvec(s, nv.vp)) {
		int	x, y;		/* need to pick origin */
		RAY	thisray;
		if (dev->getcur == NULL)
			return;
		(*dev->comout)("Pick point on surface for new origin\n");
		if ((*dev->getcur)(&x, &y) == ABORT)
			return;
		if ((thisray.rmax = viewray(thisray.rorg, thisray.rdir,
			&ourview, (x+.5)/hresolu, (y+.5)/vresolu)) < -FTINY) {
			error(COMMAND, "not on image");
			return;
		}
		rayorigin(&thisray, PRIMARY, NULL, NULL);
		if (!localhit(&thisray, &thescene)) {
			error(COMMAND, "not a local object");
			return;
		}
		if (thisray.rod < 0.0)	/* don't look through other side */
			flipsurface(&thisray);
		VSUM(nv.vp, thisray.rop, thisray.ron, 20.0*FTINY);
		VCOPY(nv.vdir, thisray.ron);
	} else if (!sscanvec(sskip2(s,3), nv.vdir) || normalize(nv.vdir) == 0.0)
		VCOPY(nv.vdir, ourview.vdir);

	d = DOT(nv.vdir, nv.vup);	/* need different up vector? */
	if (d*d >= 1.-2.*FTINY) {
		int	i;
		nv.vup[0] = nv.vup[1] = nv.vup[2] = 0.0;
		for (i = 3; i--; )
			if (nv.vdir[i]*nv.vdir[i] < 0.34)
				break;
		nv.vup[i] = 1.;
	}
	newview(&nv);
}
Ejemplo n.º 11
0
void
xf_xfmvect(FVECT v1, FVECT v2)	/* transform a vector using current matrix */
{
	if (xf_context == NULL) {
		VCOPY(v1, v2);
		return;
	}
	multv3(v1, v2, xf_context->xf.xfm);
}
Ejemplo n.º 12
0
void
xf_xfmpoint(FVECT v1, FVECT v2)	/* transform a point by the current matrix */
{
	if (xf_context == NULL) {
		VCOPY(v1, v2);
		return;
	}
	multp3(v1, v2, xf_context->xf.xfm);
}
Ejemplo n.º 13
0
void OOC_BuildPhotonMap (struct PhotonMap *pmap, unsigned numProc)
{
   FILE        *leafFile;
   char        leafFname [1024];
   FVECT       d, octOrg;
   int         i;
   RREAL       octSize = 0;
   
   /* Determine octree size and origin from pmap extent and init octree */
   VCOPY(octOrg, pmap -> minPos);
   VSUB(d, pmap -> maxPos, pmap -> minPos);
   for (i = 0; i < 3; i++)
      if (octSize < d [i])
         octSize = d [i];
         
   if (octSize < FTINY)
      error(INTERNAL, "zero octree size in OOC_BuildPhotonMap");
            
   /* Derive leaf filename from photon map and open file */
   strncpy(leafFname, pmap -> fileName, sizeof(leafFname));
   strncat(leafFname, PMAP_OOC_LEAFSUFFIX, 
           sizeof(leafFname) - strlen(leafFname) - 1);   
   if (!(leafFile = fopen(leafFname, "w+b")))
      error(SYSTEM, "failed to open leaf file in OOC_BuildPhotonMap");

#ifdef DEBUG_OOC
   eputs("Sorting photons by Morton code...\n");
#endif
   
   /* Sort photons in heapfile by Morton code and write to leaf file */
   if (OOC_Sort(pmap -> heap, leafFile, PMAP_OOC_NUMBLK, PMAP_OOC_BLKSIZE,
                numProc, sizeof(Photon), octOrg, octSize, OOC_PhotonKey))
      error(INTERNAL, "failed out-of-core photon sort in OOC_BuildPhotonMap");

   /* Init and build octree */   
   OOC_Init(&pmap -> store, sizeof(Photon), octOrg, octSize, OOC_PhotonKey, 
            leafFile);
            
#ifdef DEBUG_OOC
   eputs("Checking leaf file consistency...\n");
   OOC_CheckKeys(leafFile, &pmap -> store);
   
   eputs("Building out-of-core octree...\n");
#endif   
            
   if (!OOC_Build(&pmap -> store, PMAP_OOC_LEAFMAX, PMAP_OOC_MAXDEPTH))
      error(INTERNAL, "failed out-of-core octree build in OOC_BuildPhotonMap");
      
#ifdef DEBUG_OOC
   eputs("Checking out-of-core octree consistency...\n");
   if (OOC_Check(&pmap -> store, OOC_ROOT(&pmap -> store), 
                 octOrg, octSize, 0))
      error(INTERNAL, "inconsistent out-of-core octree; Time4Harakiri");
#endif
}
Ejemplo n.º 14
0
/* Transform and normalize direction (column) vector */
SDError
SDmapDir(FVECT resVec, RREAL vMtx[3][3], const FVECT inpVec)
{
	FVECT	vTmp;

	if ((resVec == NULL) | (inpVec == NULL))
		return SDEargument;
	if (vMtx == NULL) {		/* assume they just want to normalize */
		if (resVec != inpVec)
			VCOPY(resVec, inpVec);
		return (normalize(resVec) > 0) ? SDEnone : SDEargument;
	}
	vTmp[0] = DOT(vMtx[0], inpVec);
	vTmp[1] = DOT(vMtx[1], inpVec);
	vTmp[2] = DOT(vMtx[2], inpVec);
	if (normalize(vTmp) == 0)
		return SDEargument;
	VCOPY(resVec, vTmp);
	return SDEnone;
}
Ejemplo n.º 15
0
int
nonplanar(			/* are vertices non-planar? */
	int	ac,
	char	**av
)
{
	VNDX	vi;
	RREAL	*p0, *p1;
	FVECT	v1, v2, nsum, newn;
	double	d;
	int	i;

	if (!cvtndx(vi, av[0]))
		return(0);
	if (!flatten && vi[2] >= 0)
		return(1);		/* has interpolated normals */
	if (ac < 4)
		return(0);		/* it's a triangle! */
					/* set up */
	p0 = vlist[vi[0]];
	if (!cvtndx(vi, av[1]))
		return(0);		/* error gets caught later */
	nsum[0] = nsum[1] = nsum[2] = 0.;
	p1 = vlist[vi[0]];
	fvsum(v2, p1, p0, -1.0);
	for (i = 2; i < ac; i++) {
		VCOPY(v1, v2);
		if (!cvtndx(vi, av[i]))
			return(0);
		p1 = vlist[vi[0]];
		fvsum(v2, p1, p0, -1.0);
		fcross(newn, v1, v2);
		if (normalize(newn) == 0.0) {
			if (i < 3)
				return(1);	/* can't deal with this */
			fvsum(nsum, nsum, nsum, 1./(i-2));
			continue;
		}
		d = fdot(newn,nsum);
		if (d >= 0) {
			if (d < (1.0-FTINY)*(i-2))
				return(1);
			fvsum(nsum, nsum, newn, 1.0);
		} else {
			if (d > -(1.0-FTINY)*(i-2))
				return(1);
			fvsum(nsum, nsum, newn, -1.0);
		}
	}
	return(0);
}
Ejemplo n.º 16
0
extern double
makeambient(		/* make a new ambient value for storage */
	COLOR  acol,
	RAY  *r,
	FVECT  rn,
	int  al
)
{
	AMBVAL	amb;
	FVECT	gp, gd;
	int	i;

	amb.weight = 1.0;			/* compute weight */
	for (i = al; i-- > 0; )
		amb.weight *= AVGREFL;
	if (r->rweight < 0.1*amb.weight)	/* heuristic override */
		amb.weight = 1.25*r->rweight;
	setcolor(acol, AVGREFL, AVGREFL, AVGREFL);
						/* compute ambient */
	amb.rad = doambient(acol, r, amb.weight, gp, gd);
	if (amb.rad <= FTINY) {
		setcolor(acol, 0.0, 0.0, 0.0);
		return(0.0);
	}
	scalecolor(acol, 1./AVGREFL);		/* undo assumed reflectance */
						/* store value */
	VCOPY(amb.pos, r->rop);
	VCOPY(amb.dir, r->ron);
	amb.lvl = al;
	copycolor(amb.val, acol);
	VCOPY(amb.gpos, gp);
	VCOPY(amb.gdir, gd);
						/* insert into tree */
	avsave(&amb);				/* and save to file */
	if (rn != r->ron)
		extambient(acol, &amb, r->rop, rn);	/* texture */
	return(amb.rad);
}
Ejemplo n.º 17
0
/* Compute World->BSDF transform from surface normal and up (Y) vector */
SDError	
SDcompXform(RREAL vMtx[3][3], const FVECT sNrm, const FVECT uVec)
{
	if ((vMtx == NULL) | (sNrm == NULL) | (uVec == NULL))
		return SDEargument;
	VCOPY(vMtx[2], sNrm);
	if (normalize(vMtx[2]) == 0)
		return SDEargument;
	fcross(vMtx[0], uVec, vMtx[2]);
	if (normalize(vMtx[0]) == 0)
		return SDEargument;
	fcross(vMtx[1], vMtx[2], vMtx[0]);
	return SDEnone;
}
Ejemplo n.º 18
0
extern void
raytrans(			/* transmit ray as is */
	RAY  *r
)
{
	RAY  tr;

	if (rayorigin(&tr, TRANS, r, NULL) == 0) {
		VCOPY(tr.rdir, r->rdir);
		rayvalue(&tr);
		copycolor(r->rcol, tr.rcol);
		r->rt = r->rot + tr.rt;
	}
}
Ejemplo n.º 19
0
void
hdcell(		/* compute cell coordinates */
	FVECT	cp[4],	/* returned (may be passed as FVECT cp[2][2]) */
	HOLO	*hp,
	GCOORD	*gc
)
{
	RREAL	*v;
	double	d;
					/* compute common component */
	VCOPY(cp[0], hp->orig);
	if (gc->w & 1) {
		v = hp->xv[gc->w>>1];
		cp[0][0] += v[0]; cp[0][1] += v[1]; cp[0][2] += v[2];
	}
Ejemplo n.º 20
0
static int
moveview(	/* move our view */
	int	dx,
	int	dy,
	int	mov,
	int	orb
)
{
	VIEW	nv;
	FVECT	odir, v1, wp;
	double	d;
				/* start with old view */
	nv = thisview;
				/* change view direction */
	if ((d = viewray(v1, odir, &thisview,
			(dx+.5)/hres, (dy+.5)/vres)) < -FTINY)
		return(0);		/* outside view */
	if (mov | orb) {
		if (!getintersect(wp, v1, odir, d))
			return(0);
		VSUM(odir, wp, nv.vp, -1.);
	} else
		VCOPY(nv.vdir, odir);
	if (orb && mov) {		/* orbit left/right */
		spinvector(odir, odir, nv.vup, d=MOVDEG*PI/180.*mov);
		VSUM(nv.vp, wp, odir, -1.);
		spinvector(nv.vdir, nv.vdir, nv.vup, d);
	} else if (orb) {		/* orbit up/down */
		if (geodesic(odir, odir, nv.vup,
				d=MOVDEG*PI/180.*orb, GEOD_RAD) == 0.0)
			return(0);
		VSUM(nv.vp, wp, odir, -1.);
		geodesic(nv.vdir, nv.vdir, nv.vup, d, GEOD_RAD);
	} else if (mov) {		/* move forward/backward */
		d = MOVPCT/100. * mov;
		VSUM(nv.vp, nv.vp, odir, d);
	}
	if (!mov ^ !orb && headlocked) {	/* restore head height */
		VSUM(v1, thisview.vp, nv.vp, -1.);
		d = DOT(v1, thisview.vup);
		VSUM(nv.vp, nv.vp, thisview.vup, d);
	}
	if (setview(&nv) != NULL)
		return(0);	/* illegal view */
	dev_view(&nv);
	return(1);
}
Ejemplo n.º 21
0
static PhotonPrimaryIdx newPhotonPrimary (PhotonMap *pmap, 
                                          const RAY *primRay, 
                                          FILE *primHeap)
/* Add primary ray for emitted photon and save light source index, origin on
 * source, and emitted direction; used by contrib photons. The current
 * primary is stored in pmap -> lastPrimary.  If the previous primary
 * contributed photons (has srcIdx >= 0), it's appended to primHeap.  If
 * primRay == NULL, the current primary is still flushed, but no new primary
 * is set.  Returns updated primary counter pmap -> numPrimary.  */
{
   if (!pmap || !primHeap)
      return 0;
      
   /* Check if last primary ray has spawned photons (srcIdx >= 0, see
    * newPhoton()), in which case we save it to the primary heap file
    * before clobbering it */
   if (pmap -> lastPrimary.srcIdx >= 0) {
      if (!fwrite(&pmap -> lastPrimary, sizeof(PhotonPrimary), 1, primHeap))
         error(SYSTEM, "failed writing photon primary in newPhotonPrimary");
         
      pmap -> numPrimary++;
      if (pmap -> numPrimary > PMAP_MAXPRIMARY)
         error(INTERNAL, "photon primary overflow in newPhotonPrimary");
   }

   /* Mark unused with negative source index until path spawns a photon (see
    * newPhoton()) */
   pmap -> lastPrimary.srcIdx = -1;
     
   if (primRay) { 
      FVECT dvec;

#ifdef PMAP_PRIMARYDIR            
      /* Reverse incident direction to point to light source */
      dvec [0] = -primRay -> rdir [0];
      dvec [1] = -primRay -> rdir [1];
      dvec [2] = -primRay -> rdir [2];
      pmap -> lastPrimary.dir = encodedir(dvec);
#endif      
#ifdef PMAP_PRIMARYPOS      
      VCOPY(pmap -> lastPrimary.pos, primRay -> rop);
#endif      
   }
   
   return pmap -> numPrimary;
}
Ejemplo n.º 22
0
/* Sample an individual BSDF component */
SDError
SDsampComponent(SDValue *sv, FVECT ioVec, double randX, SDComponent *sdc)
{
	float		coef[SDmaxCh];
	SDError		ec;
	FVECT		inVec;
	const SDCDst	*cd;
	double		d;
	int		n;
					/* check arguments */
	if ((sv == NULL) | (ioVec == NULL) | (sdc == NULL))
		return SDEargument;
					/* get cumulative distribution */
	VCOPY(inVec, ioVec);
	cd = (*sdc->func->getCDist)(inVec, sdc);
	if (cd == NULL)
		return SDEmemory;
	if (cd->cTotal <= 1e-6) {	/* anything to sample? */
		sv->spec = c_dfcolor;
		sv->cieY = .0;
		memset(ioVec, 0, 3*sizeof(double));
		return SDEnone;
	}
	sv->cieY = cd->cTotal;
					/* compute sample direction */
	ec = (*sdc->func->sampCDist)(ioVec, randX, cd);
	if (ec)
		return ec;
					/* get BSDF color */
	n = (*sdc->func->getBSDFs)(coef, ioVec, inVec, sdc);
	if (n <= 0) {
		strcpy(SDerrorDetail, "BSDF sample value error");
		return SDEinternal;
	}
	sv->spec = sdc->cspec[0];
	d = coef[0];
	while (--n) {
		c_cmix(&sv->spec, d, &sv->spec, coef[n], &sdc->cspec[n]);
		d += coef[n];
	}
					/* make sure everything is set */
	c_ccvt(&sv->spec, C_CSXY+C_CSSPEC);
	return SDEnone;
}
Ejemplo n.º 23
0
char *
getvertid(		/* get/set vertex ID for this point */
	char	*vname,
	FVECT	vp
)
{
	static char	vkey[VKLEN];
	register LUENT	*lp;
	register int	i, vndx;

	vclock++;			/* increment counter */
	mkvkey(vkey, vp);
	if ((lp = lu_find(&vertab, vkey)) == NULL)
		goto memerr;
	if (lp->data == NULL) {		/* allocate new vertex entry */
		if (lp->key != NULL)		/* reclaim deleted entry */
			vertab.ndel--;
		else {
			if ((lp->key = (char *)malloc(VKLEN)) == NULL)
				goto memerr;
			strcpy(lp->key, vkey);
		}
		vndx = 0;			/* find oldest vertex */
		for (i = 1; i < NVERTS; i++)
			if (vert[i].lused < vert[vndx].lused)
				vndx = i;
		if (vert[vndx].lused) {		/* free old entry first */
			mkvkey(vkey, vert[vndx].p);
			lu_delete(&vertab, vkey);
		}
		VCOPY(vert[vndx].p, vp);			/* assign it */
		printf("v v%d =\n\tp %.15g %.15g %.15g\n",	/* print it */
				vndx, vp[0], vp[1], vp[2]);
		lp->data = (char *)&vert[vndx];			/* set it */
	} else
		vndx = (struct vert *)lp->data - vert;
	vert[vndx].lused = vclock;		/* record this use */
	sprintf(vname, "v%d", vndx);
	return(vname);
memerr:
	fputs("Out of memory in getvertid!\n", stderr);
	exit(1);
}
Ejemplo n.º 24
0
/* Rotate RBF to correspond to given incident vector */
void
rotate_rbf(RBFNODE *rbf, const FVECT invec)
{
	static const FVECT	vnorm = {.0, .0, 1.};
	const double		phi = atan2(invec[1],invec[0]) -
					atan2(rbf->invec[1],rbf->invec[0]);
	FVECT			outvec;
	int			pos[2];
	int			n;

	for (n = ((-.01 > phi) | (phi > .01))*rbf->nrbf; n-- > 0; ) {
		ovec_from_pos(outvec, rbf->rbfa[n].gx, rbf->rbfa[n].gy);
		spinvector(outvec, outvec, vnorm, phi);
		pos_from_vec(pos, outvec);
		rbf->rbfa[n].gx = pos[0];
		rbf->rbfa[n].gy = pos[1];
	}
	VCOPY(rbf->invec, invec);
}
Ejemplo n.º 25
0
R8 V1AIpart( const IX nv, const VERTEX3D p2[],
           const VERTEX3D *p1, const DIRCOS *u1 )
/*  nv   number of vertices/edges of surface (polygon) P2
 *  p2   coordinates of vertices of surface (polygon) P2
 *  p1   coordinates of surface (point) P1
 *  u1   components of unit vector normal to surface P1 */
  {
  IX n;  /* edge number */
  VECTOR3D A,  /* A = vector from P1 to P2[n-1]; |A| > 0 */
           B,  /* B = vector from P1 to P2[n]; |B| > 0 */
           C;  /* C = vector cross product of A and B */
  R8 UdotC; /* dot product of U and C; always >= 0 */
  R8 sum=0; /* sum of line integrals */

                            /* Initialization */
  n = nv - 1;
  VECTOR( p1, (p2+n), (&B) );           /* vector B */
                            /* For all edges of polygon p2: */
  for( n=0; n<nv; n++ )
    {
    VCOPY( (&B), (&A) );                /* A = old B */
    VECTOR( p1, (p2+n), (&B) );         /* vector B */
    VCROSS( (&A), (&B), (&C) );         /* C = A cross B */
    UdotC = VDOT( u1, (&C) );           /* U dot C */
    if( fabs(UdotC) > EPS2 )
      {
      R8 Clen = VLEN( (&C) );           /* | C | */
      if( Clen > EPS2 )
        {   /* gamma = angle between A and B; 0 < gamma < 180 */
        R8 gamma = PId2 - atan( VDOT( (&A), (&B) ) / Clen );
        sum += UdotC * gamma / Clen;
        }
      else
        error( 3, __FILE__, __LINE__, "View1AI failed, call George", "" );
      }
    }  /* end edge loop */

  sum *= PIt2inv;                 /* Divide by 2*pi */

  return sum;

  }  /* end of V1AIpart
Ejemplo n.º 26
0
static void
add_holo(		/* register a new holodeck section */
	HDGRID	*hdg,
	char	*gfn,
	char	*pfn
)
{
	VIEW	nv;
	double	d;
	register int	hd;

	for (hd = 0; hd < HDMAX && hdlist[hd] != NULL; hd++)
		;
	if (hd >= HDMAX)
		error(INTERNAL, "too many holodeck sections in add_holo");
	hdlist[hd] = (HOLO *)malloc(sizeof(HOLO));
	if (hdlist[hd] == NULL)
		error(SYSTEM, "out of memory in add_holo");
	memcpy((void *)hdlist[hd], (void *)hdg, sizeof(HDGRID));
	hdcompgrid(hdlist[hd]);
	hdgfn[hd] = savestr(gfn);
	hdpfn[hd] = pfn && *pfn ? savestr(pfn) : (char *)NULL;
	if (hd)
		return;
					/* set initial viewpoint */
	nv = odev.v;
	VSUM(nv.vp, hdlist[0]->orig, hdlist[0]->xv[0], 0.5);
	VSUM(nv.vp, nv.vp, hdlist[0]->xv[1], 0.5);
	VSUM(nv.vp, nv.vp, hdlist[0]->xv[2], 0.5);
	fcross(nv.vdir, hdlist[0]->xv[1], hdlist[0]->xv[2]);
	VCOPY(nv.vup, hdlist[0]->xv[2]);
	if (do_outside) {
		normalize(nv.vdir);
		d = VLEN(hdlist[0]->xv[1]);
		d += VLEN(hdlist[0]->xv[2]);
		VSUM(nv.vp, nv.vp, nv.vdir, -d);
	}
	new_view(&nv);
}
Ejemplo n.º 27
0
static void
avinsert(				/* insert ambient value in our tree */
	void *av
)
{
	AMBTREE  *at;
	AMBVAL  *ap;
	AMBVAL  avh;
	FVECT  ck0;
	double	s;
	int  branch;
	int  i;

	if (((AMBVAL*)av)->rad <= FTINY)
		error(CONSISTENCY, "zero ambient radius in avinsert");
	at = &atrunk;
	VCOPY(ck0, thescene.cuorg);
	s = thescene.cusize;
	while (s*(OCTSCALE/2) > ((AMBVAL*)av)->rad*ambacc) {
		if (at->kid == NULL)
			if ((at->kid = newambtree()) == NULL)
				error(SYSTEM, "out of memory in avinsert");
		s *= 0.5;
		branch = 0;
		for (i = 0; i < 3; i++)
			if (((AMBVAL*)av)->pos[i] > ck0[i] + s) {
				ck0[i] += s;
				branch |= 1 << i;
			}
		at = at->kid + branch;
	}
	avh.next = at->alist;		/* order by increasing level */
	for (ap = &avh; ap->next != NULL; ap = ap->next)
		if (ap->next->lvl >= ((AMBVAL*)av)->lvl)
			break;
	((AMBVAL*)av)->next = ap->next;
	ap->next = (AMBVAL*)av;
	at->alist = avh.next;
}
Ejemplo n.º 28
0
static int
o_cube(			/* determine if cubes intersect */
	CUBE  *cu1,
	FULLXF  *fxf,
	CUBE  *cu
)
{
	static int  vstart[4] = {0, 3, 5, 6};
	FVECT  cumin, cumax;
	FVECT  vert[8];
	FVECT  v1, v2;
	int  vloc, vout;
	register int  i, j;
					/* check if cube vertex in octree */
	for (j = 0; j < 3; j++)
		cumax[j] = (cumin[j] = cu1->cuorg[j]) + cu1->cusize;
	vloc = ABOVE | BELOW;
	vout = 0;
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 3; j++) {
			v1[j] = cu->cuorg[j];
			if (i & 1<<j)
				v1[j] += cu->cusize;
		}
		multp3(v2, v1, fxf->b.xfm);
		if ( (j = plocate(v2, cumin, cumax)) )
			vout++;
		vloc &= j;
	}
	if (vout == 0)			/* all inside */
		return(O_IN);
	if (vout < 8)			/* some inside */
		return(O_HIT);
	if (vloc)			/* all to one side */
		return(O_MISS);
					/* octree vertices in cube? */
	for (j = 0; j < 3; j++)
		cumax[j] = (cumin[j] = cu->cuorg[j]) + cu->cusize;
	vloc = ABOVE | BELOW;
	for (i = 0; i < 8; i++) {
		for (j = 0; j < 3; j++) {
			v1[j] = cu1->cuorg[j];
			if (i & 1<<j)
				v1[j] += cu1->cusize;
		}
		multp3(vert[i], v1, fxf->f.xfm);
		if ( (j = plocate(vert[i], cumin, cumax)) )
			vloc &= j;
		else
			return(O_HIT);	/* vertex inside */
	}
	if (vloc)			/* all to one side */
		return(O_MISS);
					/* check edges */
	for (i = 0; i < 4; i++)
		for (j = 0; j < 3; j++) {
						/* clip modifies vertices! */
			VCOPY(v1, vert[vstart[i]]);
			VCOPY(v2, vert[vstart[i] ^ 1<<j]);
			if (clip(v1, v2, cumin, cumax))
				return(O_HIT);		/* edge inside */
		}

	return(O_MISS);			/* no intersection */
}
Ejemplo n.º 29
0
/* Sample BSDF direction based on the given random variable */
SDError
SDsampBSDF(SDValue *sv, FVECT ioVec, double randX, int sflags, const SDData *sd)
{
	SDError		ec;
	FVECT		inVec;
	int		inFront;
	SDSpectralDF	*rdf, *tdf;
	double		rdiff;
	float		coef[SDmaxCh];
	int		i, j, n, nr;
	SDComponent	*sdc;
	const SDCDst	**cdarr = NULL;
					/* check arguments */
	if ((sv == NULL) | (ioVec == NULL) | (sd == NULL) |
			(randX < 0) | (randX >= 1.))
		return SDEargument;
					/* whose side are we on? */
	VCOPY(inVec, ioVec);
	inFront = (inVec[2] > 0);
					/* remember diffuse portions */
	if (inFront) {
		*sv = sd->rLambFront;
		rdf = sd->rf;
		tdf = (sd->tf != NULL) ? sd->tf : sd->tb;
	} else /* !inFront */ {
		*sv = sd->rLambBack;
		rdf = sd->rb;
		tdf = (sd->tb != NULL) ? sd->tb : sd->tf;
	}
	if ((sflags & SDsampDf+SDsampR) != SDsampDf+SDsampR)
		sv->cieY = .0;
	rdiff = sv->cieY;
	if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT)
		sv->cieY += sd->tLamb.cieY;
					/* gather non-diffuse components */
	i = nr = (((sflags & SDsampSp+SDsampR) == SDsampSp+SDsampR) &
			(rdf != NULL)) ? rdf->ncomp : 0;
	j = (((sflags & SDsampSp+SDsampT) == SDsampSp+SDsampT) &
			(tdf != NULL)) ? tdf->ncomp : 0;
	n = i + j;
	if (n > 0 && (cdarr = (const SDCDst **)malloc(n*sizeof(SDCDst *))) == NULL)
		return SDEmemory;
	while (j-- > 0) {		/* non-diffuse transmission */
		cdarr[i+j] = (*tdf->comp[j].func->getCDist)(inVec, &tdf->comp[j]);
		if (cdarr[i+j] == NULL) {
			free(cdarr);
			return SDEmemory;
		}
		sv->cieY += cdarr[i+j]->cTotal;
	}
	while (i-- > 0) {		/* non-diffuse reflection */
		cdarr[i] = (*rdf->comp[i].func->getCDist)(inVec, &rdf->comp[i]);
		if (cdarr[i] == NULL) {
			free(cdarr);
			return SDEmemory;
		}
		sv->cieY += cdarr[i]->cTotal;
	}
	if (sv->cieY <= 1e-6) {		/* anything to sample? */
		sv->cieY = .0;
		memset(ioVec, 0, 3*sizeof(double));
		return SDEnone;
	}
					/* scale random variable */
	randX *= sv->cieY;
					/* diffuse reflection? */
	if (randX < rdiff) {
		SDdiffuseSamp(ioVec, inFront, randX/rdiff);
		goto done;
	}
	randX -= rdiff;
					/* diffuse transmission? */
	if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) {
		if (randX < sd->tLamb.cieY) {
			sv->spec = sd->tLamb.spec;
			SDdiffuseSamp(ioVec, !inFront, randX/sd->tLamb.cieY);
			goto done;
		}
		randX -= sd->tLamb.cieY;
	}
					/* else one of cumulative dist. */
	for (i = 0; i < n && randX < cdarr[i]->cTotal; i++)
		randX -= cdarr[i]->cTotal;
	if (i >= n)
		return SDEinternal;
					/* compute sample direction */
	sdc = (i < nr) ? &rdf->comp[i] : &tdf->comp[i-nr];
	ec = (*sdc->func->sampCDist)(ioVec, randX/cdarr[i]->cTotal, cdarr[i]);
	if (ec)
		return ec;
					/* compute color */
	j = (*sdc->func->getBSDFs)(coef, ioVec, inVec, sdc);
	if (j <= 0) {
		sprintf(SDerrorDetail, "BSDF \"%s\" sampling value error",
				sd->name);
		return SDEinternal;
	}
	sv->spec = sdc->cspec[0];
	rdiff = coef[0];
	while (--j) {
		c_cmix(&sv->spec, rdiff, &sv->spec, coef[j], &sdc->cspec[j]);
		rdiff += coef[j];
	}
done:
	if (cdarr != NULL)
		free(cdarr);
					/* make sure everything is set */
	c_ccvt(&sv->spec, C_CSXY+C_CSSPEC);
	return SDEnone;
}
Ejemplo n.º 30
0
static void
ambHessian(				/* anisotropic radii & pos. gradient */
	AMBHEMI	*hp,
	FVECT	uv[2],			/* returned */
	float	ra[2],			/* returned (optional) */
	float	pg[2]			/* returned (optional) */
)
{
	static char	memerrmsg[] = "out of memory in ambHessian()";
	FVECT		(*hessrow)[3] = NULL;
	FVECT		*gradrow = NULL;
	FVECT		hessian[3];
	FVECT		gradient;
	FFTRI		fftr;
	int		i, j;
					/* be sure to assign unit vectors */
	VCOPY(uv[0], hp->ux);
	VCOPY(uv[1], hp->uy);
			/* clock-wise vertex traversal from sample POV */
	if (ra != NULL) {		/* initialize Hessian row buffer */
		hessrow = (FVECT (*)[3])malloc(sizeof(FVECT)*3*(hp->ns-1));
		if (hessrow == NULL)
			error(SYSTEM, memerrmsg);
		memset(hessian, 0, sizeof(hessian));
	} else if (pg == NULL)		/* bogus call? */
		return;
	if (pg != NULL) {		/* initialize form factor row buffer */
		gradrow = (FVECT *)malloc(sizeof(FVECT)*(hp->ns-1));
		if (gradrow == NULL)
			error(SYSTEM, memerrmsg);
		memset(gradient, 0, sizeof(gradient));
	}
					/* compute first row of edges */
	for (j = 0; j < hp->ns-1; j++) {
		comp_fftri(&fftr, hp, AI(hp,0,j), AI(hp,0,j+1));
		if (hessrow != NULL)
			comp_hessian(hessrow[j], &fftr, hp->rp->ron);
		if (gradrow != NULL)
			comp_gradient(gradrow[j], &fftr, hp->rp->ron);
	}
					/* sum each row of triangles */
	for (i = 0; i < hp->ns-1; i++) {
	    FVECT	hesscol[3];	/* compute first vertical edge */
	    FVECT	gradcol;
	    comp_fftri(&fftr, hp, AI(hp,i,0), AI(hp,i+1,0));
	    if (hessrow != NULL)
		comp_hessian(hesscol, &fftr, hp->rp->ron);
	    if (gradrow != NULL)
		comp_gradient(gradcol, &fftr, hp->rp->ron);
	    for (j = 0; j < hp->ns-1; j++) {
		FVECT	hessdia[3];	/* compute triangle contributions */
		FVECT	graddia;
		double	backg;
		backg = back_ambval(hp, AI(hp,i,j),
					AI(hp,i,j+1), AI(hp,i+1,j));
					/* diagonal (inner) edge */
		comp_fftri(&fftr, hp, AI(hp,i,j+1), AI(hp,i+1,j));
		if (hessrow != NULL) {
		    comp_hessian(hessdia, &fftr, hp->rp->ron);
		    rev_hessian(hesscol);
		    add2hessian(hessian, hessrow[j], hessdia, hesscol, backg);
		}
		if (gradrow != NULL) {
		    comp_gradient(graddia, &fftr, hp->rp->ron);
		    rev_gradient(gradcol);
		    add2gradient(gradient, gradrow[j], graddia, gradcol, backg);
		}
					/* initialize edge in next row */
		comp_fftri(&fftr, hp, AI(hp,i+1,j+1), AI(hp,i+1,j));
		if (hessrow != NULL)
		    comp_hessian(hessrow[j], &fftr, hp->rp->ron);
		if (gradrow != NULL)
		    comp_gradient(gradrow[j], &fftr, hp->rp->ron);
					/* new column edge & paired triangle */
		backg = back_ambval(hp, AI(hp,i+1,j+1),
					AI(hp,i+1,j), AI(hp,i,j+1));
		comp_fftri(&fftr, hp, AI(hp,i,j+1), AI(hp,i+1,j+1));
		if (hessrow != NULL) {
		    comp_hessian(hesscol, &fftr, hp->rp->ron);
		    rev_hessian(hessdia);
		    add2hessian(hessian, hessrow[j], hessdia, hesscol, backg);
		    if (i < hp->ns-2)
			rev_hessian(hessrow[j]);
		}
		if (gradrow != NULL) {
		    comp_gradient(gradcol, &fftr, hp->rp->ron);
		    rev_gradient(graddia);
		    add2gradient(gradient, gradrow[j], graddia, gradcol, backg);
		    if (i < hp->ns-2)
			rev_gradient(gradrow[j]);
		}
	    }
	}
					/* release row buffers */
	if (hessrow != NULL) free(hessrow);
	if (gradrow != NULL) free(gradrow);
	
	if (ra != NULL)			/* extract eigenvectors & radii */
		eigenvectors(uv, ra, hessian);
	if (pg != NULL) {		/* tangential position gradient */
		pg[0] = DOT(gradient, uv[0]);
		pg[1] = DOT(gradient, uv[1]);
	}
}