Beispiel #1
0
extern int
rayshade(		/* shade ray r with material mod */
	RAY  *r,
	int  mod
)
{
	OBJREC  *m;

	r->rt = r->rot;			/* set effective ray length */
	for ( ; mod != OVOID; mod = m->omod) {
		m = objptr(mod);
		/****** unnecessary test since modifier() is always called
		if (!ismodifier(m->otype)) {
			sprintf(errmsg, "illegal modifier \"%s\"", m->oname);
			error(USER, errmsg);
		}
		******/
					/* hack for irradiance calculation */
		if (do_irrad && !(r->crtype & ~(PRIMARY|TRANS)) &&
				m->otype != MAT_CLIP &&
				(ofun[m->otype].flags & (T_M|T_X))) {
			if (irr_ignore(m->otype)) {
				raytrans(r);
				return(1);
			}
			if (!islight(m->otype))
				m = &Lamb;
		}
		if ((*ofun[m->otype].funp)(m, r))
			return(1);	/* materials call raytexture() */
	}
	return(0);			/* no material! */
}
void photonPreCompDensity (PhotonMap *pmap, RAY *r, COLOR irrad)
/* Returns precomputed photon density estimate at ray -> rop. */
{
   Photon p;
   
   setcolor(irrad, 0, 0, 0);

   /* Ignore sources */
   if (r -> ro && islight(objptr(r -> ro -> omod) -> otype)) 
      return;
      
   find1Photon(preCompPmap, r, &p);
   getPhotonFlux(&p, irrad);
}
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);
}
Beispiel #4
0
extern void
marksources(void)			/* find and mark source objects */
{
	int  foundsource = 0;
	int  i;
	register OBJREC  *o, *m;
	register int  ns;
					/* initialize dispatch table */
	initstypes();
					/* find direct sources */
	for (i = 0; i < nsceneobjs; i++) {
	
		o = objptr(i);

		if (!issurface(o->otype) || o->omod == OVOID)
			continue;
					/* find material */
		m = findmaterial(objptr(o->omod));
		if (m == NULL)
			continue;
		if (m->otype == MAT_CLIP) {
			markclip(m);	/* special case for antimatter */
			continue;
		}
		if (!islight(m->otype))
			continue;	/* not source modifier */
	
		if (m->oargs.nfargs != (m->otype == MAT_GLOW ? 4 :
				m->otype == MAT_SPOT ? 7 : 3))
			objerror(m, USER, "bad # arguments");

		if (m->oargs.farg[0] <= FTINY && m->oargs.farg[1] <= FTINY &&
				m->oargs.farg[2] <= FTINY)
			continue;			/* don't bother */
		if (m->otype == MAT_GLOW &&
				o->otype != OBJ_SOURCE &&
				m->oargs.farg[3] <= FTINY) {
			foundsource += (ambounce > 0);
			continue;			/* don't track these */
		}
		if (sfun[o->otype].of == NULL ||
				sfun[o->otype].of->setsrc == NULL)
			objerror(o, USER, "illegal material");

		if ((ns = newsource()) < 0)
			goto memerr;

		setsource(&source[ns], o);

		if (m->otype == MAT_GLOW) {
			source[ns].sflags |= SPROX;
			source[ns].sl.prox = m->oargs.farg[3];
			if (source[ns].sflags & SDISTANT) {
				source[ns].sflags |= SSKIP;
				foundsource += (ambounce > 0);
			}
		} else if (m->otype == MAT_SPOT) {
			source[ns].sflags |= SSPOT;
			if ((source[ns].sl.s = makespot(m)) == NULL)
				goto memerr;
			if (source[ns].sflags & SFLAT &&
				!checkspot(source[ns].sl.s,source[ns].snorm)) {
				objerror(o, WARNING,
					"invalid spotlight direction");
				source[ns].sflags |= SSKIP;
			}
		}
#if  SHADCACHE
		initobscache(ns);
#endif
		foundsource += !(source[ns].sflags & SSKIP);
	}
	if (!foundsource) {
		error(WARNING, "no light sources found");
		return;
	}
	markvirtuals();			/* find and add virtual sources */
				/* allocate our contribution arrays */
	maxcntr = nsources + MAXSPART;	/* start with this many */
	srccnt = (CONTRIB *)malloc(maxcntr*sizeof(CONTRIB));
	cntord = (CNTPTR *)malloc(maxcntr*sizeof(CNTPTR));
	if ((srccnt == NULL) | (cntord == NULL))
		goto memerr;
	return;
memerr:
	error(SYSTEM, "out of memory in marksources");
}
int newPhoton (PhotonMap* pmap, const RAY* ray)
{
   unsigned i;
   Photon photon;
   COLOR photonFlux;
   
   /* Account for distribution ratio */
   if (!pmap || pmapRandom(pmap -> randState) > pmap -> distribRatio) 
      return -1;
      
   /* Don't store on sources */
   if (ray -> robj > -1 && islight(objptr(ray -> ro -> omod) -> otype)) 
      return -1;

   /*  if modifier in include/exclude set */
   if (ambincl != -1 && ray -> ro && 
       ambincl != inset(ambset, ray -> ro -> omod))
      return -1;

   if (pmapNumROI && pmapROI) {      
      unsigned inROI = 0;
      
      /* Store photon if within a region of interest (for ze Ecksperts!) */
      for (i = 0; !inROI && i < pmapNumROI; i++)
         inROI = (ray -> rop [0] >= pmapROI [i].min [0] && 
                  ray -> rop [0] <= pmapROI [i].max [0] &&
                  ray -> rop [1] >= pmapROI [i].min [1] && 
                  ray -> rop [1] <= pmapROI [i].max [1] &&
                  ray -> rop [2] >= pmapROI [i].min [2] && 
                  ray -> rop [2] <= pmapROI [i].max [2]);
      if (!inROI)
         return -1;
   }
    
   /* Adjust flux according to distribution ratio and ray weight */
   copycolor(photonFlux, ray -> rcol);   
   scalecolor(photonFlux, 
              ray -> rweight / (pmap -> distribRatio ? pmap -> distribRatio
                                                     : 1));
   setPhotonFlux(&photon, photonFlux);
            
   /* Set photon position and flags */
   VCOPY(photon.pos, ray -> rop);
   photon.flags = 0;
   photon.caustic = PMAP_CAUSTICRAY(ray);

   /* Set contrib photon's primary ray and subprocess index (the latter
    * to linearise the primary ray indices after photon distribution is
    * complete). Also set primary ray's source index, thereby marking it
    * as used. */
   if (isContribPmap(pmap)) {
      photon.primary = pmap -> numPrimary;
      photon.proc = PMAP_GETRAYPROC(ray);
      pmap -> lastPrimary.srcIdx = ray -> rsrc;
   }
   else photon.primary = 0;
   
   /* Set normal */
   for (i = 0; i <= 2; i++)
      photon.norm [i] = 127.0 * (isVolumePmap(pmap) ? ray -> rdir [i] 
                                                    : ray -> ron [i]);

   if (!pmap -> heapBuf) {
      /* Lazily allocate heap buffa */
#if NIX
      /* Randomise buffa size to temporally decorellate flushes in
       * multiprocessing mode */
      srandom(randSeed + getpid());
      pmap -> heapBufSize = PMAP_HEAPBUFSIZE * (0.5 + frandom());
#else
      /* Randomisation disabled for single processes on WIN; also useful
       * for reproducability during debugging */         
      pmap -> heapBufSize = PMAP_HEAPBUFSIZE;
#endif         
      if (!(pmap -> heapBuf = calloc(pmap -> heapBufSize, sizeof(Photon))))
         error(SYSTEM, "failed heap buffer allocation in newPhoton");
      pmap -> heapBufLen = 0;      
   }

   /* Photon initialised; now append to heap buffa */
   memcpy(pmap -> heapBuf + pmap -> heapBufLen, &photon, sizeof(Photon));
               
   if (++pmap -> heapBufLen >= pmap -> heapBufSize)
      /* Heap buffa full, flush to heap file */
      flushPhotonHeap(pmap);

   pmap -> numPhotons++;
            
   return 0;
}