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;
}
示例#2
0
int32
addmeshvert(			/* find/add a mesh vertex */
	MESH	*mp,
	MESHVERT	*vp
)
{
	LUENT		*lvp;
	MCVERT		cv;
	int	i;

	if (!(vp->fl & MT_V))
		return(-1);
					/* encode vertex */
	for (i = 0; i < 3; i++) {
		if (vp->v[i] < mp->mcube.cuorg[i])
			return(-1);
		if (vp->v[i] >= mp->mcube.cuorg[i] + mp->mcube.cusize)
			return(-1);
		cv.xyz[i] = (uint32)(4294967296. *
				(vp->v[i] - mp->mcube.cuorg[i]) /
				mp->mcube.cusize);
	}
	if (vp->fl & MT_N)		/* assumes normalized! */
		cv.norm = encodedir(vp->n);
	if (vp->fl & MT_UV)
		for (i = 0; i < 2; i++) {
			if (vp->uv[i] <= mp->uvlim[0][i])
				return(-1);
			if (vp->uv[i] >= mp->uvlim[1][i])
				return(-1);
			cv.uv[i] = (uint32)(4294967296. *
					(vp->uv[i] - mp->uvlim[0][i]) /
					(mp->uvlim[1][i] - mp->uvlim[0][i]));
		}
	cv.fl = vp->fl;
	if (mp->lut.tsiz == 0) {
		mp->lut.hashf = cvhash;
		mp->lut.keycmp = cvcmp;
		mp->lut.freek = free;
		if (!lu_init(&mp->lut, 50000))
			goto nomem;
	}
					/* find entry */
	lvp = lu_find(&mp->lut, (char *)&cv);
	if (lvp == NULL)
		goto nomem;
	if (lvp->key == NULL) {
		lvp->key = (char *)malloc(sizeof(MCVERT)+sizeof(int32));
		memcpy((void *)lvp->key, (void *)&cv, sizeof(MCVERT));
	}
	if (lvp->data == NULL) {	/* new vertex */
		MESHPATCH	*pp;
		if (mp->npatches <= 0) {
			mp->patch = (MESHPATCH *)calloc(MPATCHBLKSIZ,
					sizeof(MESHPATCH));
			if (mp->patch == NULL)
				goto nomem;
			mp->npatches = 1;
		} else if (mp->patch[mp->npatches-1].nverts >= 256) {
			if (mp->npatches % MPATCHBLKSIZ == 0) {
				mp->patch = (MESHPATCH *)realloc(
						(void *)mp->patch,
					(mp->npatches + MPATCHBLKSIZ)*
						sizeof(MESHPATCH));
				memset((void *)(mp->patch + mp->npatches), '\0',
					MPATCHBLKSIZ*sizeof(MESHPATCH));
			}
			if (mp->npatches++ >= 1L<<22)
				error(INTERNAL, "too many mesh patches");
		}
		pp = &mp->patch[mp->npatches-1];
		if (pp->xyz == NULL) {
			pp->xyz = (uint32 (*)[3])calloc(256, 3*sizeof(int32));
			if (pp->xyz == NULL)
				goto nomem;
		}
		for (i = 0; i < 3; i++)
			pp->xyz[pp->nverts][i] = cv.xyz[i];
		if (cv.fl & MT_N) {
			if (pp->norm == NULL) {
				pp->norm = (int32 *)calloc(256, sizeof(int32));
				if (pp->norm == NULL)
					goto nomem;
			}
			pp->norm[pp->nverts] = cv.norm;
		}
		if (cv.fl & MT_UV) {
			if (pp->uv == NULL) {
				pp->uv = (uint32 (*)[2])calloc(256,
						2*sizeof(uint32));
				if (pp->uv == NULL)
					goto nomem;
			}
			for (i = 0; i < 2; i++)
				pp->uv[pp->nverts][i] = cv.uv[i];
		}
		pp->nverts++;
		lvp->data = lvp->key + sizeof(MCVERT);
		*(int32 *)lvp->data = (mp->npatches-1) << 8 | (pp->nverts-1);
	}
	return(*(int32 *)lvp->data);
nomem:
	error(SYSTEM, "out of memory in addmeshvert");
	return(-1);
}