ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambient.c
(Generate patch)

Comparing ray/src/rt/ambient.c (file contents):
Revision 2.85 by greg, Tue May 6 17:15:11 2014 UTC vs.
Revision 2.87 by greg, Fri May 9 16:40:01 2014 UTC

# Line 267 | Line 267 | ambnotify(                     /* record new modifier */
267  
268   #define tfunc(lwr, x, upr)      (((x)-(lwr))/((upr)-(lwr)))
269  
270 + static int      plugaleak(RAY *r, AMBVAL *ap, FVECT anorm, double ang);
271   static double   sumambient(COLOR acol, RAY *r, FVECT rn, int al,
272                                  AMBTREE *at, FVECT c0, double s);
273   static int      makeambient(COLOR acol, RAY *r, FVECT rn, int al);
# Line 298 | Line 299 | multambient(           /* compute ambient component & multiply
299          if (ambacc <= FTINY) {                  /* no ambient storage */
300                  copycolor(acol, aval);
301                  rdepth++;
302 <                ok = doambient(acol, r, r->rweight, NULL, NULL, NULL, NULL);
302 >                ok = doambient(acol, r, r->rweight,
303 >                                NULL, NULL, NULL, NULL, NULL);
304                  rdepth--;
305                  if (!ok)
306                          goto dumbamb;
# Line 344 | Line 346 | dumbamb:                                       /* return global value */
346   }
347  
348  
349 < double
349 > /* Plug a potential leak where ambient cache value is occluded */
350 > static int
351 > plugaleak(RAY *r, AMBVAL *ap, FVECT anorm, double ang)
352 > {
353 >        const double    cost70sq = 0.1169778;   /* cos(70deg)^2 */
354 >        RAY             rtst;
355 >        FVECT           vdif;
356 >        double          normdot, ndotd, nadotd;
357 >        double          a, b, c, t[2];
358 >
359 >        ang += 2.*PI*(ang < 0);                 /* check direction flags */
360 >        if ( !(ap->corral>>(int)(ang*(16./PI)) & 1) )
361 >                return(0);
362 >        /*
363 >         * Generate test ray, targeting 20 degrees above sample point plane
364 >         * along surface normal from cache position.  This should be high
365 >         * enough to miss local geometry we don't really care about.
366 >         */
367 >        VSUB(vdif, ap->pos, r->rop);
368 >        normdot = DOT(anorm, r->ron);
369 >        ndotd = DOT(vdif, r->ron);
370 >        nadotd = DOT(vdif, anorm);
371 >        a = normdot*normdot - cost70sq;
372 >        b = 2.0*(normdot*ndotd - nadotd*cost70sq);
373 >        c = ndotd*ndotd - DOT(vdif,vdif)*cost70sq;
374 >        if (quadratic(t, a, b, c) != 2)
375 >                return(1);                      /* should rarely happen */
376 >        if (t[1] <= FTINY)
377 >                return(0);                      /* should fail behind test */
378 >        rayorigin(&rtst, SHADOW, r, NULL);
379 >        VSUM(rtst.rdir, vdif, anorm, t[1]);     /* further dist. > plane */
380 >        rtst.rmax = normalize(rtst.rdir);       /* short ray test */
381 >        while (localhit(&rtst, &thescene)) {    /* check for occluder */
382 >                if (rtst.ro->omod != OVOID &&
383 >                                (rtst.clipset == NULL ||
384 >                                        !inset(rtst.clipset, rtst.ro->omod)))
385 >                        return(1);              /* plug light leak */
386 >                VCOPY(rtst.rorg, rtst.rop);     /* skip invisible surface */
387 >                rtst.rmax -= rtst.rot;
388 >                rayclear(&rtst);
389 >        }
390 >        return(0);                              /* seems we're OK */
391 > }
392 >
393 >
394 > static double
395   sumambient(             /* get interpolated ambient value */
396          COLOR  acol,
397          RAY  *r,
# Line 387 | Line 434 | sumambient(            /* get interpolated ambient value */
434                  maxangle = (maxangle - PI/2.)*pow(r->rweight,0.13) + PI/2.;
435                                          /* sum this node */
436          for (av = at->alist; av != NULL; av = av->next) {
437 <                double  d, delta_r2, delta_t2;
437 >                double  u, v, d, delta_r2, delta_t2;
438                  COLOR   ct;
439                  FVECT   uvw[3];
440                                          /* record access */
# Line 396 | Line 443 | sumambient(            /* get interpolated ambient value */
443                  /*
444                   *  Ambient level test
445                   */
446 <                if (av->lvl > al)       /* list sorted, so this works */
446 >                if (av->lvl > al ||     /* list sorted, so this works */
447 >                                (av->lvl == al) & (av->weight < 0.9*r->rweight))
448                          break;
401                if (av->weight < 0.9*r->rweight)
402                        continue;
449                  /*
450                   *  Direction test using unperturbed normal
451                   */
# Line 426 | Line 472 | sumambient(            /* get interpolated ambient value */
472                   */
473                  decodedir(uvw[0], av->udir);
474                  VCROSS(uvw[1], uvw[2], uvw[0]);
475 <                d = DOT(ck0, uvw[0]) / av->rad[0];
475 >                d = (u = DOT(ck0, uvw[0])) / av->rad[0];
476                  delta_t2 += d*d;
477 <                d = DOT(ck0, uvw[1]) / av->rad[1];
477 >                d = (v = DOT(ck0, uvw[1])) / av->rad[1];
478                  delta_t2 += d*d;
479                  if (delta_t2 >= ambacc*ambacc)
480                          continue;
481                  /*
482 +                 *  Test for potential light leak
483 +                 */
484 +                if (av->corral && plugaleak(r, av, uvw[2], atan2a(v,u)))
485 +                        continue;
486 +                /*
487                   *  Extrapolate value and compute final weight (hat function)
488                   */
489                  extambient(ct, av, r->rop, rn, uvw);
# Line 446 | Line 497 | sumambient(            /* get interpolated ambient value */
497   }
498  
499  
500 < int
500 > static int
501   makeambient(            /* make a new ambient value for storage */
502          COLOR  acol,
503          RAY  *r,
# Line 465 | Line 516 | makeambient(           /* make a new ambient value for storage
516                  amb.weight = 1.25*r->rweight;
517          setcolor(acol, AVGREFL, AVGREFL, AVGREFL);
518                                                  /* compute ambient */
519 <        i = doambient(acol, r, amb.weight, uvw, amb.rad, amb.gpos, amb.gdir);
519 >        i = doambient(acol, r, amb.weight,
520 >                        uvw, amb.rad, amb.gpos, amb.gdir, &amb.corral);
521          scalecolor(acol, 1./AVGREFL);           /* undo assumed reflectance */
522          if (i <= 0 || amb.rad[0] <= FTINY)      /* no Hessian or zero radius */
523                  return(i);
# Line 485 | Line 537 | makeambient(           /* make a new ambient value for storage
537   }
538  
539  
540 < void
540 > static void
541   extambient(             /* extrapolate value at pv, nv */
542          COLOR  cr,
543          AMBVAL   *ap,
# Line 555 | Line 607 | avinsert(                              /* insert ambient value in our tree */
607          }
608          avh.next = at->alist;           /* order by increasing level */
609          for (ap = &avh; ap->next != NULL; ap = ap->next)
610 <                if (ap->next->lvl >= av->lvl)
610 >                if ( ap->next->lvl > av->lvl ||
611 >                                (ap->next->lvl == av->lvl) &
612 >                                (ap->next->weight <= av->weight) )
613                          break;
614          av->next = ap->next;
615          ap->next = (AMBVAL*)av;
# Line 668 | Line 722 | sumambient(    /* get interpolated ambient value */
722                  /*
723                   *  Ambient level test.
724                   */
725 <                if (av->lvl > al)       /* list sorted, so this works */
725 >                if (av->lvl > al ||     /* list sorted, so this works */
726 >                                (av->lvl == al) & (av->weight < 0.9*r->rweight))
727                          break;
673                if (av->weight < 0.9*r->rweight)
674                        continue;
728                  /*
729                   *  Ambient radius test.
730                   */
# Line 853 | Line 906 | avinsert(                              /* insert ambient value in our tree */
906          }
907          avh.next = at->alist;           /* order by increasing level */
908          for (ap = &avh; ap->next != NULL; ap = ap->next)
909 <                if (ap->next->lvl >= av->lvl)
909 >                if ( ap->next->lvl > av->lvl ||
910 >                                (ap->next->lvl == av->lvl) &
911 >                                (ap->next->weight <= av->weight) )
912                          break;
913          av->next = ap->next;
914          ap->next = (AMBVAL*)av;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines