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

Comparing ray/src/cv/bsdfrbf.c (file contents):
Revision 2.23 by greg, Fri Mar 21 00:42:46 2014 UTC vs.
Revision 2.31 by greg, Wed Aug 1 17:00:22 2018 UTC

# Line 29 | Line 29 | static const char RCSid[] = "$Id$";
29   #include "bsdfrep.h"
30  
31   #ifndef RSCA
32 < #define RSCA            2.2             /* radius scaling factor (empirical) */
32 > #define RSCA            2.0             /* radius scaling factor (empirical) */
33   #endif
34 + #ifndef MAXSLOPE
35 + #define MAXSLOPE        200.0           /* maximum slope for smooth region */
36 + #endif
37   #ifndef SMOOTH_MSE
38   #define SMOOTH_MSE      5e-5            /* acceptable mean squared error */
39   #endif
40   #ifndef SMOOTH_MSER
41 < #define SMOOTH_MSER     0.03            /* acceptable relative MSE */
41 > #define SMOOTH_MSER     0.01            /* acceptable relative MSE */
42   #endif
43   #define MAX_RAD         (GRIDRES/8)     /* maximum lobe radius */
44  
45   #define RBFALLOCB       10              /* RBF allocation block size */
46  
47 <                                /* our loaded grid or comparison DSFs */
47 >                                        /* loaded grid or comparison DSFs */
48   GRIDVAL                 dsf_grid[GRIDRES][GRIDRES];
49 +                                        /* allocated chrominance sums if any */
50 + float                   (*spec_grid)[GRIDRES][GRIDRES];
51 + int                     nspec_grid = 0;
52  
53 + /* Set up visible spectrum sampling */
54 + void
55 + set_spectral_samples(int nspec)
56 + {
57 +        if (rbf_colorimetry == RBCunknown) {
58 +                if (nspec_grid > 0) {
59 +                        free(spec_grid);
60 +                        spec_grid = NULL;
61 +                        nspec_grid = 0;
62 +                }
63 +                if (nspec == 1) {
64 +                        rbf_colorimetry = RBCphotopic;
65 +                        return;
66 +                }
67 +                if (nspec == 3) {
68 +                        rbf_colorimetry = RBCtristimulus;
69 +                        spec_grid = (float (*)[GRIDRES][GRIDRES])calloc(
70 +                                        2*GRIDRES*GRIDRES, sizeof(float) );
71 +                        if (spec_grid == NULL)
72 +                                goto mem_error;
73 +                        nspec_grid = 2;
74 +                        return;
75 +                }
76 +                fprintf(stderr,
77 +                        "%s: only 1 or 3 spectral samples currently supported\n",
78 +                                progname);
79 +                exit(1);
80 +        }
81 +        if (nspec != nspec_grid+1) {
82 +                fprintf(stderr,
83 +                        "%s: number of spectral samples cannot be changed\n",
84 +                                progname);
85 +                exit(1);
86 +        }
87 +        return;
88 + mem_error:
89 +        fprintf(stderr, "%s: out of memory in set_spectral_samples()\n",
90 +                        progname);
91 +        exit(1);
92 + }
93 +
94   /* Start new DSF input grid */
95   void
96   new_bsdf_data(double new_theta, double new_phi)
# Line 51 | Line 98 | new_bsdf_data(double new_theta, double new_phi)
98          if (!new_input_direction(new_theta, new_phi))
99                  exit(1);
100          memset(dsf_grid, 0, sizeof(dsf_grid));
101 +        if (nspec_grid > 0)
102 +                memset(spec_grid, 0, sizeof(float)*GRIDRES*GRIDRES*nspec_grid);
103   }
104  
105   /* Add BSDF data point */
106   void
107 < add_bsdf_data(double theta_out, double phi_out, double val, int isDSF)
107 > add_bsdf_data(double theta_out, double phi_out, const double val[], int isDSF)
108   {
109          FVECT   ovec;
110 +        double  cfact, Yval;
111          int     pos[2];
112  
113 +        if (nspec_grid > 2) {
114 +                fprintf(stderr, "%s: unsupported color space\n", progname);
115 +                exit(1);
116 +        }
117          if (!output_orient)             /* check output orientation */
118                  output_orient = 1 - 2*(theta_out > 90.);
119          else if (output_orient > 0 ^ theta_out < 90.) {
120 <                fputs("Cannot handle output angles on both sides of surface\n",
121 <                                stderr);
120 >                fprintf(stderr,
121 >                "%s: cannot handle output angles on both sides of surface\n",
122 >                                progname);
123                  exit(1);
124          }
125          ovec[2] = sin((M_PI/180.)*theta_out);
126          ovec[0] = cos((M_PI/180.)*phi_out) * ovec[2];
127          ovec[1] = sin((M_PI/180.)*phi_out) * ovec[2];
128          ovec[2] = sqrt(1. - ovec[2]*ovec[2]);
129 +                                        /* BSDF to DSF correction */
130 +        cfact = isDSF ? 1. : ovec[2];
131  
132 <        if (!isDSF)
76 <                val *= ovec[2];         /* convert from BSDF to DSF */
77 <
132 >        Yval = cfact * val[rbf_colorimetry==RBCtristimulus];
133                                          /* update BSDF histogram */
134 <        if (val < BSDF2BIG*ovec[2] && val > BSDF2SML*ovec[2])
135 <                ++bsdf_hist[histndx(val/ovec[2])];
134 >        if (BSDF2SML*ovec[2] < Yval && Yval < BSDF2BIG*ovec[2])
135 >                ++bsdf_hist[histndx(Yval/ovec[2])];
136  
137          pos_from_vec(pos, ovec);
138  
139 <        dsf_grid[pos[0]][pos[1]].sum.v += val;
139 >        dsf_grid[pos[0]][pos[1]].sum.v += Yval;
140          dsf_grid[pos[0]][pos[1]].sum.n++;
141 +                                        /* add in X and Z values */
142 +        if (rbf_colorimetry == RBCtristimulus) {
143 +                spec_grid[0][pos[0]][pos[1]] += cfact * val[0];
144 +                spec_grid[1][pos[0]][pos[1]] += cfact * val[2];
145 +        }
146   }
147  
148   /* Compute minimum BSDF from histogram (does not clear) */
# Line 152 | Line 212 | smooth_region(int x0, int x1, int y0, int y1)
212                  return(1);              /* colinear values */
213          A = DOT(rMtx[0], xvec);
214          B = DOT(rMtx[1], xvec);
215 +        if (A*A + B*B > MAXSLOPE*MAXSLOPE)      /* too steep? */
216 +                return(0);
217          C = DOT(rMtx[2], xvec);
218          sqerr = 0.0;                    /* compute mean squared error */
219          for (x = x0; x < x1; x++)
# Line 171 | Line 233 | static int
233   create_lobe(RBFVAL *rvp, int x0, int x1, int y0, int y1)
234   {
235          double  vtot = 0.0;
236 +        double  CIEXtot = 0.0, CIEZtot = 0.0;
237          int     nv = 0;
238 +        double  wxsum = 0.0, wysum = 0.0, wtsum = 0.0;
239          double  rad;
240          int     x, y;
241                                          /* compute average for region */
242          for (x = x0; x < x1; x++)
243 <            for (y = y0; y < y1; y++) {
244 <                vtot += dsf_grid[x][y].sum.v;
245 <                nv += dsf_grid[x][y].sum.n;
246 <            }
243 >            for (y = y0; y < y1; y++)
244 >                if (dsf_grid[x][y].sum.n) {
245 >                    const double        v = dsf_grid[x][y].sum.v;
246 >                    const int           n = dsf_grid[x][y].sum.n;
247 >
248 >                    if (v > 0) {
249 >                        const double    wt = v / (double)n;
250 >                        wxsum += wt * x;
251 >                        wysum += wt * y;
252 >                        wtsum += wt;
253 >                    }
254 >                    vtot += v;
255 >                    nv += n;
256 >                    if (rbf_colorimetry == RBCtristimulus) {
257 >                        CIEXtot += spec_grid[0][x][y];
258 >                        CIEZtot += spec_grid[1][x][y];
259 >                    }
260 >                }
261          if (!nv) {
262                  fprintf(stderr, "%s: internal - missing samples in create_lobe\n",
263                                  progname);
# Line 187 | Line 265 | create_lobe(RBFVAL *rvp, int x0, int x1, int y0, int y
265          }
266          if (vtot <= 0)                  /* only create positive lobes */
267                  return(0);
268 +                                        /* assign color */
269 +        if (rbf_colorimetry == RBCtristimulus) {
270 +                const double    df = 1.0 / (CIEXtot + vtot + CIEZtot);
271 +                C_COLOR         cclr;
272 +                c_cset(&cclr, CIEXtot*df, vtot*df);
273 +                rvp->chroma = c_encodeChroma(&cclr);
274 +        } else
275 +                rvp->chroma = c_dfchroma;
276                                          /* peak value based on integral */
277          vtot *= (x1-x0)*(y1-y0)*(2.*M_PI/GRIDRES/GRIDRES)/(double)nv;
278          rad = (RSCA/(double)GRIDRES)*(x1-x0);
279          rvp->peak =  vtot / ((2.*M_PI) * rad*rad);
280 <        rvp->crad = ANG2R(rad);
281 <        rvp->gx = (x0+x1)>>1;
282 <        rvp->gy = (y0+y1)>>1;
280 >        rvp->crad = ANG2R(rad);         /* put peak at centroid */
281 >        rvp->gx = (int)(wxsum/wtsum + .5);
282 >        rvp->gy = (int)(wysum/wtsum + .5);
283          return(1);
284   }
285  
# Line 265 | Line 351 | make_rbfrep()
351          if (build_rbfrep(&rbfarr, &nn, 0, GRIDRES, 0, GRIDRES) <= 0) {
352                  if (nn)
353                          goto memerr;
354 <                fprintf(stderr, "%s: no usable data in make_rbfrep()\n",
355 <                                progname);
356 <                exit(1);
354 >                fprintf(stderr,
355 >                        "%s: warning - skipping bad incidence (%.1f,%.1f)\n",
356 >                                progname, theta_in_deg, phi_in_deg);
357 >                return(NULL);
358          }
359                                  /* (re)allocate RBF array */
360          newnode = (RBFNODE *)realloc(rbfarr,
# Line 295 | Line 382 | make_rbfrep()
382                          newnode->vtotal);
383   #endif
384          insert_dsf(newnode);
298
385          return(newnode);
386   memerr:
387          fprintf(stderr, "%s: Out of memory in make_rbfrep()\n", progname);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines