static AMBHEMI * samp_hemi( /* sample indirect hemisphere */ COLOR rcol, RAY *r, double wt ) { AMBHEMI *hp; double d; int n, i, j; /* insignificance check */ if (bright(rcol) <= FTINY) return(NULL); /* set number of divisions */ if (ambacc <= FTINY && wt > (d = 0.8*intens(rcol)*r->rweight/(ambdiv*minweight))) wt = d; /* avoid ray termination */ n = sqrt(ambdiv * wt) + 0.5; i = 1 + 5*(ambacc > FTINY); /* minimum number of samples */ if (n < i) n = i; /* allocate sampling array */ hp = (AMBHEMI *)malloc(sizeof(AMBHEMI) + sizeof(AMBSAMP)*(n*n - 1)); if (hp == NULL) error(SYSTEM, "out of memory in samp_hemi"); hp->rp = r; hp->ns = n; hp->acol[RED] = hp->acol[GRN] = hp->acol[BLU] = 0.0; memset(hp->sa, 0, sizeof(AMBSAMP)*n*n); hp->sampOK = 0; /* assign coefficient */ copycolor(hp->acoef, rcol); d = 1.0/(n*n); scalecolor(hp->acoef, d); /* make tangent plane axes */ if (!getperpendicular(hp->ux, r->ron, 1)) error(CONSISTENCY, "bad ray direction in samp_hemi"); VCROSS(hp->uy, r->ron, hp->ux); /* sample divisions */ for (i = hp->ns; i--; ) for (j = hp->ns; j--; ) hp->sampOK += ambsample(hp, i, j, 0); copycolor(rcol, hp->acol); if (!hp->sampOK) { /* utter failure? */ free(hp); return(NULL); } if (hp->sampOK < hp->ns*hp->ns) { hp->sampOK *= -1; /* soft failure */ return(hp); } if (hp->sampOK < 64) return(hp); /* insufficient for super-sampling */ n = ambssamp*wt + 0.5; if (n > 8) { /* perform super-sampling? */ ambsupersamp(hp, n); copycolor(rcol, hp->acol); } return(hp); /* all is well */ }
static void getacoords( /* set up coordinate system */ ANISODAT *np ) { MFUNC *mf; int i; mf = getfunc(np->mp, 3, 0x7, 1); setfunc(np->mp, np->rp); errno = 0; for (i = 0; i < 3; i++) np->u[i] = evalue(mf->ep[i]); if ((errno == EDOM) | (errno == ERANGE)) np->u[0] = np->u[1] = np->u[2] = 0.0; if (mf->fxp != &unitxf) multv3(np->u, np->u, mf->fxp->xfm); fcross(np->v, np->pnorm, np->u); if (normalize(np->v) == 0.0) { if (fabs(np->u_alpha - np->v_alpha) > 0.001) objerror(np->mp, WARNING, "illegal orientation vector"); getperpendicular(np->u, np->pnorm); /* punting */ fcross(np->v, np->pnorm, np->u); np->u_alpha = np->v_alpha = sqrt( 0.5 * (np->u_alpha*np->u_alpha + np->v_alpha*np->v_alpha) ); } else fcross(np->u, np->v, np->pnorm); }