| 15 |  |  | 
| 16 |  | COLORV *        distarr = NULL;         /* distribution array */ | 
| 17 |  | int             distsiz = 0; | 
| 18 | + | COLORV *        direct_discount = NULL; /* amount to take off direct */ | 
| 19 |  |  | 
| 19 | – |  | 
| 20 |  | void | 
| 21 |  | newdist(                        /* allocate & clear distribution array */ | 
| 22 |  | int siz | 
| 41 |  | } | 
| 42 |  |  | 
| 43 |  |  | 
| 44 | + | static void | 
| 45 | + | new_discount()                  /* allocate space for direct contrib. record */ | 
| 46 | + | { | 
| 47 | + | if (distsiz <= 0) | 
| 48 | + | return; | 
| 49 | + | direct_discount = (COLORV *)calloc(distsiz, sizeof(COLOR)); | 
| 50 | + | if (direct_discount == NULL) | 
| 51 | + | error(SYSTEM, "out of memory in new_discount"); | 
| 52 | + | } | 
| 53 | + |  | 
| 54 | + |  | 
| 55 | + | static void | 
| 56 | + | done_discount()                 /* clear off direct contrib. record */ | 
| 57 | + | { | 
| 58 | + | if (direct_discount == NULL) | 
| 59 | + | return; | 
| 60 | + | free((void *)direct_discount); | 
| 61 | + | direct_discount = NULL; | 
| 62 | + | } | 
| 63 | + |  | 
| 64 | + |  | 
| 65 |  | int | 
| 66 |  | process_ray(                    /* process a ray result or report error */ | 
| 67 |  | RAY *r, | 
| 79 |  | multcolor(r->rcol, r->rcoef);   /* in case it's a source ray */ | 
| 80 |  | colp = &distarr[r->rno * 3]; | 
| 81 |  | addcolor(colp, r->rcol); | 
| 82 | + | if (r->rsrc >= 0 &&             /* remember source contrib. */ | 
| 83 | + | direct_discount != NULL) { | 
| 84 | + | colp = &direct_discount[r->rno * 3]; | 
| 85 | + | addcolor(colp, r->rcol); | 
| 86 | + | } | 
| 87 |  | return(1); | 
| 88 |  | } | 
| 89 |  |  | 
| 153 |  | d = 5.*FTINY; | 
| 154 |  | for (i = 3; i--; ) | 
| 155 |  | sr.rorg[i] += d*nrm[i]; | 
| 156 | + | samplendx++;                    /* increment sample counter */ | 
| 157 |  | if (!srcray(&sr, NULL, &si)) | 
| 158 |  | break;                  /* end of sources */ | 
| 159 |  | /* index direction */ | 
| 170 |  | } else { | 
| 171 |  | if (v[2] >= -FTINY) | 
| 172 |  | continue;       /* only sample transmission */ | 
| 173 | < | d = 1.0 - v[2]*v[2]; | 
| 174 | < | i = d*nalt; | 
| 175 | < | d = atan2(-v[1], -v[0])/(2.*PI); | 
| 149 | < | if (d < 0.0) d += 1.0; | 
| 150 | < | j = d*nazi + 0.5; | 
| 151 | < | if (j >= nazi) j = 0; | 
| 152 | < | sr.rno = i*nazi + j; | 
| 153 | < | d = nalt*nazi/PI * -v[2]; | 
| 173 | > | v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2]; | 
| 174 | > | sr.rno = flatindex(v, nalt, nazi); | 
| 175 | > | d = nalt*nazi*(1./PI) * v[2]; | 
| 176 |  | } | 
| 177 |  | d *= si.dom;                    /* solid angle correction */ | 
| 178 |  | scalecolor(sr.rcoef, d); | 
| 244 |  | dv[2] = sqrt(1. - alt); | 
| 245 |  | } | 
| 246 |  |  | 
| 247 | + | int | 
| 248 | + | flatindex(              /* compute index for hemispherical direction */ | 
| 249 | + | FVECT   dv, | 
| 250 | + | int     nalt, | 
| 251 | + | int     nazi | 
| 252 | + | ) | 
| 253 | + | { | 
| 254 | + | double  d; | 
| 255 | + | int     i, j; | 
| 256 | + |  | 
| 257 | + | d = 1.0 - dv[2]*dv[2]; | 
| 258 | + | i = d*nalt; | 
| 259 | + | d = atan2(dv[1], dv[0]) * (0.5/PI); | 
| 260 | + | if (d < 0.0) d += 1.0; | 
| 261 | + | j = d*nazi + 0.5; | 
| 262 | + | if (j >= nazi) j = 0; | 
| 263 | + | return(i*nazi + j); | 
| 264 | + | } | 
| 265 |  |  | 
| 266 | + |  | 
| 267 |  | int | 
| 268 |  | my_default(     /* default illum action */ | 
| 269 |  | OBJREC  *ob, | 
| 391 |  | raysamp(dim[1], org, dir); | 
| 392 |  | } | 
| 393 |  | /* add in direct component? */ | 
| 394 | < | if (!directvis && il->flags & IL_LIGHT) { | 
| 394 | > | if (!directvis && (il->flags & IL_LIGHT || il->sd != NULL)) { | 
| 395 |  | MAT4    ixfm; | 
| 396 |  | if (il->sd == NULL) { | 
| 397 |  | for (i = 3; i--; ) { | 
| 402 |  | } | 
| 403 |  | ixfm[3][0] = ixfm[3][1] = ixfm[3][2] = 0.; | 
| 404 |  | ixfm[3][3] = 1.; | 
| 405 | < | } else if (!invmat4(ixfm, xfm)) | 
| 406 | < | objerror(ob, INTERNAL, "cannot invert BSDF transform"); | 
| 405 | > | } else { | 
| 406 | > | if (!invmat4(ixfm, xfm)) | 
| 407 | > | objerror(ob, INTERNAL, | 
| 408 | > | "cannot invert BSDF transform"); | 
| 409 | > | if (!(il->flags & IL_LIGHT)) | 
| 410 | > | new_discount(); | 
| 411 | > | } | 
| 412 |  | dim[0] = random(); | 
| 413 |  | nallow = 10*il->nsamps; | 
| 414 |  | for (i = 0; i < il->nsamps; i++) { | 
| 438 |  | nalt = sqrt(il->sd->nout/PI) + .5; | 
| 439 |  | nazi = PI*nalt + .5; | 
| 440 |  | redistribute(il->sd, nalt, nazi, u, v, fa->norm, xfm); | 
| 441 | + | done_discount(); | 
| 442 |  | if (!il->sampdens) | 
| 443 |  | il->sampdens = nalt*nazi/PI + .999; | 
| 444 |  | } | 
| 599 |  | raysamp(dim[1], org, dir); | 
| 600 |  | } | 
| 601 |  | /* add in direct component? */ | 
| 602 | < | if (!directvis && il->flags & IL_LIGHT) { | 
| 602 | > | if (!directvis && (il->flags & IL_LIGHT || il->sd != NULL)) { | 
| 603 |  | MAT4    ixfm; | 
| 604 |  | if (il->sd == NULL) { | 
| 605 |  | for (i = 3; i--; ) { | 
| 610 |  | } | 
| 611 |  | ixfm[3][0] = ixfm[3][1] = ixfm[3][2] = 0.; | 
| 612 |  | ixfm[3][3] = 1.; | 
| 613 | < | } else if (!invmat4(ixfm, xfm)) | 
| 614 | < | objerror(ob, INTERNAL, "cannot invert BSDF transform"); | 
| 613 | > | } else { | 
| 614 | > | if (!invmat4(ixfm, xfm)) | 
| 615 | > | objerror(ob, INTERNAL, | 
| 616 | > | "cannot invert BSDF transform"); | 
| 617 | > | if (!(il->flags & IL_LIGHT)) | 
| 618 | > | new_discount(); | 
| 619 | > | } | 
| 620 |  | dim[0] = random(); | 
| 621 |  | for (i = 0; i < il->nsamps; i++) { | 
| 622 |  | /* randomize location */ | 
| 639 |  | nalt = sqrt(il->sd->nout/PI) + .5; | 
| 640 |  | nazi = PI*nalt + .5; | 
| 641 |  | redistribute(il->sd, nalt, nazi, u, v, co->ad, xfm); | 
| 642 | + | done_discount(); | 
| 643 |  | if (!il->sampdens) | 
| 644 |  | il->sampdens = nalt*nazi/PI + .999; | 
| 645 |  | } |