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

Comparing ray/src/common/bsdf_t.c (file contents):
Revision 3.17 by greg, Thu Jun 9 17:09:39 2011 UTC vs.
Revision 3.29 by greg, Thu Jul 4 01:24:17 2013 UTC

# Line 26 | Line 26 | typedef int    SDtreCallback(float val, const double *cmi
26  
27                                          /* reference width maximum (1.0) */
28   static const unsigned   iwbits = sizeof(unsigned)*4;
29 < static const unsigned   iwmax = (1<<(sizeof(unsigned)*4))-1;
29 > static const unsigned   iwmax = 1<<(sizeof(unsigned)*4);
30                                          /* maximum cumulative value */
31   static const unsigned   cumlmax = ~0;
32                                          /* constant z-vector */
33   static const FVECT      zvec = {.0, .0, 1.};
34 +                                        /* quantization value */
35 + static double           quantum = 1./256.;
36  
37   /* Struct used for our distribution-building callback */
38   typedef struct {
39 <        int             nic;            /* number of input coordinates */
39 >        short           nic;            /* number of input coordinates */
40 >        short           rev;            /* reversing query */
41          unsigned        alen;           /* current array length */
42          unsigned        nall;           /* number of allocated entries */
43          unsigned        wmin;           /* minimum square size so far */
# Line 430 | Line 433 | SDlookupTre(const SDNode *st, const double *pos, doubl
433   static float
434   SDqueryTre(const SDTre *sdt, const FVECT outVec, const FVECT inVec, double *hc)
435   {
436 <        FVECT                   rOutVec;
437 <        double                  gridPos[4];
436 >        const RREAL     *vtmp;
437 >        FVECT           rOutVec;
438 >        double          gridPos[4];
439  
440          switch (sdt->sidef) {           /* whose side are you on? */
441 <        case SD_UFRONT:
441 >        case SD_FREFL:
442                  if ((outVec[2] < 0) | (inVec[2] < 0))
443                          return -1.;
444                  break;
445 <        case SD_UBACK:
445 >        case SD_BREFL:
446                  if ((outVec[2] > 0) | (inVec[2] > 0))
447                          return -1.;
448                  break;
449 <        case SD_XMIT:
450 <                if ((outVec[2] > 0) == (inVec[2] > 0))
449 >        case SD_FXMIT:
450 >                if (outVec[2] > 0) {
451 >                        if (inVec[2] > 0)
452 >                                return -1.;
453 >                        vtmp = outVec; outVec = inVec; inVec = vtmp;
454 >                } else if (inVec[2] < 0)
455                          return -1.;
456                  break;
457 +        case SD_BXMIT:
458 +                if (inVec[2] > 0) {
459 +                        if (outVec[2] > 0)
460 +                                return -1.;
461 +                        vtmp = outVec; outVec = inVec; inVec = vtmp;
462 +                } else if (outVec[2] < 0)
463 +                        return -1.;
464 +                break;
465          default:
466                  return -1.;
467          }
# Line 483 | Line 499 | build_scaffold(float val, const double *cmin, double c
499   {
500          SDdistScaffold  *sp = (SDdistScaffold *)cptr;
501          int             wid = csiz*(double)iwmax + .5;
502 +        double          revcmin[2];
503          bitmask_t       bmin[2], bmax[2];
504  
505 <        cmin += sp->nic;                /* skip to output coords */
505 >        if (sp->rev) {                  /* need to reverse sense? */
506 >                revcmin[0] = 1. - cmin[0] - csiz;
507 >                revcmin[1] = 1. - cmin[1] - csiz;
508 >                cmin = revcmin;
509 >        } else {
510 >                cmin += sp->nic;        /* else skip to output coords */
511 >        }
512          if (wid < sp->wmin)             /* new minimum width? */
513                  sp->wmin = wid;
514          if (wid > sp->wmax)             /* new maximum? */
# Line 531 | Line 554 | sscmp(const void *p1, const void *p2)
554  
555   /* Create a new cumulative distribution for the given input direction */
556   static SDTreCDst *
557 < make_cdist(const SDTre *sdt, const double *pos)
557 > make_cdist(const SDTre *sdt, const double *invec, int rev)
558   {
559          SDdistScaffold  myScaffold;
560 +        double          pos[4];
561 +        int             cmask;
562          SDTreCDst       *cd;
563          struct outdir_s *sp;
564          double          scale, cursum;
# Line 542 | Line 567 | make_cdist(const SDTre *sdt, const double *pos)
567          myScaffold.wmin = iwmax;
568          myScaffold.wmax = 0;
569          myScaffold.nic = sdt->st->ndim - 2;
570 +        myScaffold.rev = rev;
571          myScaffold.alen = 0;
572          myScaffold.nall = 512;
573          myScaffold.darr = (struct outdir_s *)malloc(sizeof(struct outdir_s) *
574                                                          myScaffold.nall);
575          if (myScaffold.darr == NULL)
576                  return NULL;
577 +                                        /* set up traversal */
578 +        cmask = (1<<myScaffold.nic) - 1;
579 +        for (i = myScaffold.nic; i--; )
580 +                        pos[i+2*rev] = invec[i];
581 +        cmask <<= 2*rev;
582                                          /* grow the distribution */
583 <        if (SDtraverseTre(sdt->st, pos, (1<<myScaffold.nic)-1,
583 >        if (SDtraverseTre(sdt->st, pos, cmask,
584                                  &build_scaffold, &myScaffold) < 0) {
585                  free(myScaffold.darr);
586                  return NULL;
# Line 572 | Line 603 | make_cdist(const SDTre *sdt, const double *pos)
603                                          /* record input range */
604          scale = myScaffold.wmin / (double)iwmax;
605          for (i = myScaffold.nic; i--; ) {
606 <                cd->clim[i][0] = floor(pos[i]/scale) * scale;
606 >                cd->clim[i][0] = floor(pos[i+2*rev]/scale) * scale;
607                  cd->clim[i][1] = cd->clim[i][0] + scale;
608          }
609          if (cd->isodist) {              /* avoid issue in SDqueryTreProjSA() */
# Line 581 | Line 612 | make_cdist(const SDTre *sdt, const double *pos)
612          }
613          cd->max_psa = myScaffold.wmax / (double)iwmax;
614          cd->max_psa *= cd->max_psa * M_PI;
615 <        cd->sidef = sdt->sidef;
615 >        if (rev)
616 >                cd->sidef = (sdt->sidef==SD_BXMIT) ? SD_FXMIT : SD_BXMIT;
617 >        else
618 >                cd->sidef = sdt->sidef;
619          cd->cTotal = 1e-20;             /* compute directional total */
620          sp = myScaffold.darr;
621          for (i = myScaffold.alen; i--; sp++)
# Line 608 | Line 642 | SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
642   {
643          const SDTre     *sdt;
644          double          inCoord[2];
611        int             vflags;
645          int             i;
646 +        int             mode;
647          SDTreCDst       *cd, *cdlast;
648                                          /* check arguments */
649          if ((inVec == NULL) | (sdc == NULL) ||
650                          (sdt = (SDTre *)sdc->dist) == NULL)
651                  return NULL;
652 <        if (sdt->st->ndim == 3)         /* isotropic BSDF? */
652 >        switch (mode = sdt->sidef) {    /* check direction */
653 >        case SD_FREFL:
654 >                if (inVec[2] < 0)
655 >                        return NULL;
656 >                break;
657 >        case SD_BREFL:
658 >                if (inVec[2] > 0)
659 >                        return NULL;
660 >                break;
661 >        case SD_FXMIT:
662 >                if (inVec[2] < 0)
663 >                        mode = SD_BXMIT;
664 >                break;
665 >        case SD_BXMIT:
666 >                if (inVec[2] > 0)
667 >                        mode = SD_FXMIT;
668 >                break;
669 >        default:
670 >                return NULL;
671 >        }
672 >        if (sdt->st->ndim == 3) {       /* isotropic BSDF? */
673 >                if (mode != sdt->sidef) /* XXX unhandled reciprocity */
674 >                        return &SDemptyCD;
675                  inCoord[0] = .5 - .5*sqrt(inVec[0]*inVec[0] + inVec[1]*inVec[1]);
676 <        else if (sdt->st->ndim == 4)
677 <                SDdisk2square(inCoord, -inVec[0], -inVec[1]);
678 <        else
676 >        } else if (sdt->st->ndim == 4) {
677 >                if (mode != sdt->sidef) /* use reciprocity? */
678 >                        SDdisk2square(inCoord, inVec[0], inVec[1]);
679 >                else
680 >                        SDdisk2square(inCoord, -inVec[0], -inVec[1]);
681 >        } else
682                  return NULL;            /* should be internal error */
683 +                                        /* quantize to avoid f.p. errors */
684 +        for (i = sdt->st->ndim - 2; i--; )
685 +                inCoord[i] = floor(inCoord[i]/quantum)*quantum + .5*quantum;
686          cdlast = NULL;                  /* check for direction in cache list */
687          for (cd = (SDTreCDst *)sdc->cdList; cd != NULL;
688 <                                cdlast = cd, cd = (SDTreCDst *)cd->next) {
688 >                                        cdlast = cd, cd = cd->next) {
689 >                if (cd->sidef != mode)
690 >                        continue;
691                  for (i = sdt->st->ndim - 2; i--; )
692                          if ((cd->clim[i][0] > inCoord[i]) |
693                                          (inCoord[i] >= cd->clim[i][1]))
# Line 632 | Line 696 | SDgetTreCDist(const FVECT inVec, SDComponent *sdc)
696                          break;          /* means we have a match */
697          }
698          if (cd == NULL)                 /* need to create new entry? */
699 <                cdlast = cd = make_cdist(sdt, inCoord);
699 >                cdlast = cd = make_cdist(sdt, inCoord, mode != sdt->sidef);
700          if (cdlast != NULL) {           /* move entry to head of cache list */
701                  cdlast->next = cd->next;
702 <                cd->next = sdc->cdList;
702 >                cd->next = (SDTreCDst *)sdc->cdList;
703                  sdc->cdList = (SDCDst *)cd;
704          }
705          return (SDCDst *)cd;            /* ready to go */
# Line 664 | Line 728 | SDqueryTreProjSA(double *psa, const FVECT v1, const RR
728          } else {
729                  const SDTreCDst *cd = (const SDTreCDst *)SDgetTreCDist(v1, sdc);
730                  if (cd == NULL)
731 <                        return SDEmemory;
732 <                myPSA[0] = M_PI * (cd->clim[0][1] - cd->clim[0][0]) *
733 <                                (cd->clim[1][1] - cd->clim[1][0]);
734 <                myPSA[1] = cd->max_psa;
731 >                        myPSA[0] = myPSA[1] = 0;
732 >                else {
733 >                        myPSA[0] = M_PI * (cd->clim[0][1] - cd->clim[0][0]) *
734 >                                        (cd->clim[1][1] - cd->clim[1][0]);
735 >                        myPSA[1] = cd->max_psa;
736 >                }
737          }
738          switch (qflags) {               /* record based on flag settings */
739          case SDqueryVal:
# Line 703 | Line 769 | SDsampTreCDist(FVECT ioVec, double randX, const SDCDst
769                                          /* check arguments */
770          if ((ioVec == NULL) | (cd == NULL))
771                  return SDEargument;
772 +        if (!cd->sidef)
773 +                return SDEnone;         /* XXX should never happen */
774          if (ioVec[2] > 0) {
775 <                if (!(cd->sidef & SD_UFRONT))
775 >                if ((cd->sidef != SD_FREFL) & (cd->sidef != SD_FXMIT))
776                          return SDEargument;
777 <        } else if (!(cd->sidef & SD_UBACK))
777 >        } else if ((cd->sidef != SD_BREFL) & (cd->sidef != SD_BXMIT))
778                  return SDEargument;
779                                          /* binary search to find position */
780          ilower = 0; iupper = cd->calen;
781          while ((i = (iupper + ilower) >> 1) != ilower)
782 <                if ((long)target >= (long)cd->carr[i].cuml)
782 >                if (target >= cd->carr[i].cuml)
783                          ilower = i;
784                  else
785                          iupper = i;
# Line 732 | Line 800 | SDsampTreCDist(FVECT ioVec, double randX, const SDCDst
800          if (gpos[2] > 0)                /* paranoia, I hope */
801                  gpos[2] = sqrt(gpos[2]);
802                                          /* emit from back? */
803 <        if (ioVec[2] > 0 ^ cd->sidef != SD_XMIT)
803 >        if ((cd->sidef == SD_BREFL) | (cd->sidef == SD_FXMIT))
804                  gpos[2] = -gpos[2];
805          if (cd->isodist) {              /* rotate isotropic result */
806                  rotangle = atan2(-ioVec[1],-ioVec[0]);
# Line 842 | Line 910 | get_extrema(SDSpectralDF *df)
910          double  stepWidth, dhemi, bmin[4], bmax[4];
911  
912          stepWidth = SDsmallestLeaf(st);
913 +        if (quantum > stepWidth)        /* adjust quantization factor */
914 +                quantum = stepWidth;
915          df->minProjSA = M_PI*stepWidth*stepWidth;
916          if (stepWidth < .03125)
917                  stepWidth = .03125;     /* 1/32 resolution good enough */
# Line 881 | Line 951 | load_bsdf_data(SDData *sd, ezxml_t wdb, int ndim)
951          SDSpectralDF    *df;
952          SDTre           *sdt;
953          char            *sdata;
884        int             i;
954                                          /* allocate BSDF component */
955          sdata = ezxml_txt(ezxml_child(wdb, "WavelengthDataDirection"));
956          if (!sdata)
# Line 889 | Line 958 | load_bsdf_data(SDData *sd, ezxml_t wdb, int ndim)
958          /*
959           * Remember that front and back are reversed from WINDOW 6 orientations
960           */
961 <        if (!strcasecmp(sdata, "Transmission")) {
961 >        if (!strcasecmp(sdata, "Transmission Front")) {
962 >                if (sd->tb != NULL)
963 >                        SDfreeSpectralDF(sd->tb);
964 >                if ((sd->tb = SDnewSpectralDF(1)) == NULL)
965 >                        return SDEmemory;
966 >                df = sd->tb;
967 >        } else if (!strcasecmp(sdata, "Transmission Back")) {
968                  if (sd->tf != NULL)
969                          SDfreeSpectralDF(sd->tf);
970                  if ((sd->tf = SDnewSpectralDF(1)) == NULL)
971                          return SDEmemory;
972                  df = sd->tf;
973          } else if (!strcasecmp(sdata, "Reflection Front")) {
974 <                if (sd->rb != NULL)     /* note back-front reversal */
974 >                if (sd->rb != NULL)
975                          SDfreeSpectralDF(sd->rb);
976                  if ((sd->rb = SDnewSpectralDF(1)) == NULL)
977                          return SDEmemory;
978                  df = sd->rb;
979          } else if (!strcasecmp(sdata, "Reflection Back")) {
980 <                if (sd->rf != NULL)     /* note front-back reversal */
980 >                if (sd->rf != NULL)
981                          SDfreeSpectralDF(sd->rf);
982                  if ((sd->rf = SDnewSpectralDF(1)) == NULL)
983                          return SDEmemory;
# Line 922 | Line 997 | load_bsdf_data(SDData *sd, ezxml_t wdb, int ndim)
997          if (sdt == NULL)
998                  return SDEmemory;
999          if (df == sd->rf)
1000 <                sdt->sidef = SD_UFRONT;
1000 >                sdt->sidef = SD_FREFL;
1001          else if (df == sd->rb)
1002 <                sdt->sidef = SD_UBACK;
1003 <        else
1004 <                sdt->sidef = SD_XMIT;
1002 >                sdt->sidef = SD_BREFL;
1003 >        else if (df == sd->tf)
1004 >                sdt->sidef = SD_FXMIT;
1005 >        else /* df == sd->tb */
1006 >                sdt->sidef = SD_BXMIT;
1007          sdt->st = NULL;
1008          df->comp[0].cspec[0] = c_dfcolor; /* XXX monochrome for now */
1009          df->comp[0].dist = sdt;
# Line 1088 | Line 1165 | SDloadTre(SDData *sd, ezxml_t wtl)
1165                                          /* separate diffuse components */
1166          extract_diffuse(&sd->rLambFront, sd->rf);
1167          extract_diffuse(&sd->rLambBack, sd->rb);
1168 <        extract_diffuse(&sd->tLamb, sd->tf);
1168 >        if (sd->tf != NULL)
1169 >                extract_diffuse(&sd->tLamb, sd->tf);
1170 >        if (sd->tb != NULL)
1171 >                extract_diffuse(&sd->tLamb, sd->tb);
1172                                          /* return success */
1173          return SDEnone;
1174   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines