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; }
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); }