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.12 by greg, Mon Oct 21 18:33:15 2013 UTC vs.
Revision 2.23 by greg, Fri Mar 21 00:42:46 2014 UTC

# Line 7 | Line 7 | static const char RCSid[] = "$Id$";
7   *      G. Ward
8   */
9  
10 + /****************************************************************
11 + 1) Collect samples into a grid using the Shirley-Chiu
12 +        angular mapping from a hemisphere to a square.
13 +
14 + 2) Compute an adaptive quadtree by subdividing the grid so that
15 +        each leaf node has at least one sample up to as many
16 +        samples as fit nicely on a plane to within a certain
17 +        MSE tolerance.
18 +
19 + 3) Place one Gaussian lobe at each leaf node in the quadtree,
20 +        sizing it to have a radius equal to the leaf size and
21 +        a volume equal to the energy in that node.
22 + *****************************************************************/
23 +
24   #define _USE_MATH_DEFINES
25   #include <stdio.h>
26   #include <stdlib.h>
# Line 21 | Line 35 | static const char RCSid[] = "$Id$";
35   #define SMOOTH_MSE      5e-5            /* acceptable mean squared error */
36   #endif
37   #ifndef SMOOTH_MSER
38 < #define SMOOTH_MSER     0.07            /* acceptable relative MSE */
38 > #define SMOOTH_MSER     0.03            /* acceptable relative MSE */
39   #endif
40   #define MAX_RAD         (GRIDRES/8)     /* maximum lobe radius */
41  
42   #define RBFALLOCB       10              /* RBF allocation block size */
43  
44 <                                /* our loaded grid for this incident angle */
44 >                                /* our loaded grid or comparison DSFs */
45   GRIDVAL                 dsf_grid[GRIDRES][GRIDRES];
46  
47   /* Start new DSF input grid */
# Line 58 | Line 72 | add_bsdf_data(double theta_out, double phi_out, double
72          ovec[1] = sin((M_PI/180.)*phi_out) * ovec[2];
73          ovec[2] = sqrt(1. - ovec[2]*ovec[2]);
74  
75 <        if (val <= 0)                   /* truncate to zero */
62 <                val = 0;
63 <        else if (!isDSF)
75 >        if (!isDSF)
76                  val *= ovec[2];         /* convert from BSDF to DSF */
77  
78                                          /* update BSDF histogram */
# Line 69 | Line 81 | add_bsdf_data(double theta_out, double phi_out, double
81  
82          pos_from_vec(pos, ovec);
83  
84 <        dsf_grid[pos[0]][pos[1]].vsum += val;
85 <        dsf_grid[pos[0]][pos[1]].nval++;
84 >        dsf_grid[pos[0]][pos[1]].sum.v += val;
85 >        dsf_grid[pos[0]][pos[1]].sum.n++;
86   }
87  
88   /* Compute minimum BSDF from histogram (does not clear) */
89   static void
90   comp_bsdf_min()
91   {
92 <        int     cnt;
93 <        int     i, target;
92 >        unsigned long   cnt, target;
93 >        int             i;
94  
95          cnt = 0;
96          for (i = HISTLEN; i--; )
# Line 102 | Line 114 | empty_region(int x0, int x1, int y0, int y1)
114  
115          for (x = x0; x < x1; x++)
116              for (y = y0; y < y1; y++)
117 <                if (dsf_grid[x][y].nval)
117 >                if (dsf_grid[x][y].sum.n)
118                          return(0);
119          return(1);
120   }
# Line 120 | Line 132 | smooth_region(int x0, int x1, int y0, int y1)
132          memset(xvec, 0, sizeof(xvec));
133          for (x = x0; x < x1; x++)
134              for (y = y0; y < y1; y++)
135 <                if ((n = dsf_grid[x][y].nval) > 0) {
136 <                        double  z = dsf_grid[x][y].vsum;
137 <                        rMtx[0][0] += n*x*x;
138 <                        rMtx[0][1] += n*x*y;
139 <                        rMtx[0][2] += n*x;
140 <                        rMtx[1][1] += n*y*y;
141 <                        rMtx[1][2] += n*y;
142 <                        rMtx[2][2] += n;
135 >                if ((n = dsf_grid[x][y].sum.n) > 0) {
136 >                        double  z = dsf_grid[x][y].sum.v;
137 >                        rMtx[0][0] += x*x*(double)n;
138 >                        rMtx[0][1] += x*y*(double)n;
139 >                        rMtx[0][2] += x*(double)n;
140 >                        rMtx[1][1] += y*y*(double)n;
141 >                        rMtx[1][2] += y*(double)n;
142 >                        rMtx[2][2] += (double)n;
143                          xvec[0] += x*z;
144                          xvec[1] += y*z;
145                          xvec[2] += z;
146                  }
147          rMtx[1][0] = rMtx[0][1];
148 +        rMtx[2][0] = rMtx[0][2];
149          rMtx[2][1] = rMtx[1][2];
150          nvs = rMtx[2][2];
151          if (SDinvXform(rMtx, rMtx) != SDEnone)
152 <                return(0);
152 >                return(1);              /* colinear values */
153          A = DOT(rMtx[0], xvec);
154          B = DOT(rMtx[1], xvec);
155          C = DOT(rMtx[2], xvec);
156          sqerr = 0.0;                    /* compute mean squared error */
157          for (x = x0; x < x1; x++)
158              for (y = y0; y < y1; y++)
159 <                if ((n = dsf_grid[x][y].nval) > 0) {
160 <                        double  d = A*x + B*y + C - dsf_grid[x][y].vsum/n;
159 >                if ((n = dsf_grid[x][y].sum.n) > 0) {
160 >                        double  d = A*x + B*y + C - dsf_grid[x][y].sum.v/n;
161                          sqerr += n*d*d;
162                  }
163          if (sqerr <= nvs*SMOOTH_MSE)    /* below absolute MSE threshold? */
164                  return(1);
165 <                                        /* below relative MSE threshold? */
165 >                                        /* OR below relative MSE threshold? */
166          return(sqerr*nvs <= xvec[2]*xvec[2]*SMOOTH_MSER);
167   }
168  
169   /* Create new lobe based on integrated samples in region */
170 < static void
170 > static int
171   create_lobe(RBFVAL *rvp, int x0, int x1, int y0, int y1)
172   {
173          double  vtot = 0.0;
# Line 164 | Line 177 | create_lobe(RBFVAL *rvp, int x0, int x1, int y0, int y
177                                          /* compute average for region */
178          for (x = x0; x < x1; x++)
179              for (y = y0; y < y1; y++) {
180 <                vtot += dsf_grid[x][y].vsum;
181 <                nv += dsf_grid[x][y].nval;
180 >                vtot += dsf_grid[x][y].sum.v;
181 >                nv += dsf_grid[x][y].sum.n;
182              }
183          if (!nv) {
184                  fprintf(stderr, "%s: internal - missing samples in create_lobe\n",
185                                  progname);
186                  exit(1);
187          }
188 +        if (vtot <= 0)                  /* only create positive lobes */
189 +                return(0);
190                                          /* peak value based on integral */
191          vtot *= (x1-x0)*(y1-y0)*(2.*M_PI/GRIDRES/GRIDRES)/(double)nv;
192          rad = (RSCA/(double)GRIDRES)*(x1-x0);
# Line 179 | Line 194 | create_lobe(RBFVAL *rvp, int x0, int x1, int y0, int y
194          rvp->crad = ANG2R(rad);
195          rvp->gx = (x0+x1)>>1;
196          rvp->gy = (y0+y1)>>1;
197 +        return(1);
198   }
199  
200   /* Recursive function to build radial basis function representation */
# Line 209 | Line 225 | build_rbfrep(RBFVAL **arp, int *np, int x0, int x1, in
225          if (!nleaves)                   /* nothing but branches? */
226                  return(nadded);
227                                          /* combine 4 leaves into 1? */
228 <        if (nleaves == 4 && x1-x0 < MAX_RAD && smooth_region(x0, x1, y0, y1))
228 >        if ((nleaves == 4) & (x1-x0 <= MAX_RAD) &&
229 >                        smooth_region(x0, x1, y0, y1))
230                  return(0);
231                                          /* need more array space? */
232          if ((*np+nleaves-1)>>RBFALLOCB != (*np-1)>>RBFALLOCB) {
# Line 219 | Line 236 | build_rbfrep(RBFVAL **arp, int *np, int x0, int x1, in
236                          return(-1);
237          }
238                                          /* create lobes for leaves */
239 <        if (!branched[0])
240 <                create_lobe(*arp+(*np)++, x0, xmid, y0, ymid);
241 <        if (!branched[1])
242 <                create_lobe(*arp+(*np)++, xmid, x1, y0, ymid);
243 <        if (!branched[2])
244 <                create_lobe(*arp+(*np)++, x0, xmid, ymid, y1);
245 <        if (!branched[3])
246 <                create_lobe(*arp+(*np)++, xmid, x1, ymid, y1);
247 <        nadded += nleaves;
239 >        if (!branched[0] && create_lobe(*arp+*np, x0, xmid, y0, ymid)) {
240 >                ++(*np); ++nadded;
241 >        }
242 >        if (!branched[1] && create_lobe(*arp+*np, xmid, x1, y0, ymid)) {
243 >                ++(*np); ++nadded;
244 >        }
245 >        if (!branched[2] && create_lobe(*arp+*np, x0, xmid, ymid, y1)) {
246 >                ++(*np); ++nadded;
247 >        }
248 >        if (!branched[3] && create_lobe(*arp+*np, xmid, x1, ymid, y1)) {
249 >                ++(*np); ++nadded;
250 >        }
251          return(nadded);
252   }
253  
# Line 242 | Line 262 | make_rbfrep()
262          comp_bsdf_min();
263                                  /* create RBF node list */
264          rbfarr = NULL; nn = 0;
265 <        if (build_rbfrep(&rbfarr, &nn, 0, GRIDRES, 0, GRIDRES) <= 0)
266 <                goto memerr;
265 >        if (build_rbfrep(&rbfarr, &nn, 0, GRIDRES, 0, GRIDRES) <= 0) {
266 >                if (nn)
267 >                        goto memerr;
268 >                fprintf(stderr, "%s: no usable data in make_rbfrep()\n",
269 >                                progname);
270 >                exit(1);
271 >        }
272                                  /* (re)allocate RBF array */
273          newnode = (RBFNODE *)realloc(rbfarr,
274                          sizeof(RBFNODE) + sizeof(RBFVAL)*(nn-1));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines