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

Comparing ray/src/rt/pmutil.c (file contents):
Revision 2.1 by greg, Mon Sep 26 20:19:30 2016 UTC vs.
Revision 2.7 by greg, Fri Jan 10 21:43:22 2025 UTC

# Line 28 | Line 28 | extern char *octname;
28   /* Photon map lookup functions per type */
29   void (*pmapLookup [NUM_PMAP_TYPES])(PhotonMap*, RAY*, COLOR) = {
30     photonDensity, photonPreCompDensity, photonDensity, volumePhotonDensity,
31 <   photonDensity, NULL
31 >   photonDensity, photonDensity
32   };
33  
34  
# Line 56 | Line 56 | void loadPmaps (PhotonMap **pmaps, const PhotonMapPara
56     struct stat octstat, pmstat;
57     PhotonMap *pm;
58     PhotonMapType type;
59 <  
59 >
60     for (t = 0; t < NUM_PMAP_TYPES; t++)
61 <      if (setPmapParam(&pm, parm + t)) {        
61 >      if (setPmapParam(&pm, parm + t)) {
62           /* Check if photon map newer than octree */
63           if (pm -> fileName && octname &&
64               !stat(pm -> fileName, &pmstat) && !stat(octname, &octstat) &&
# Line 67 | Line 67 | void loadPmaps (PhotonMap **pmaps, const PhotonMapPara
67                      pm -> fileName);
68              error(USER, errmsg);
69           }
70 <        
70 >
71           /* Load photon map from file and get its type */
72           if ((type = loadPhotonMap(pm, pm -> fileName)) == PMAP_TYPE_NONE)
73              error(USER, "failed loading photon map");
# Line 75 | Line 75 | void loadPmaps (PhotonMap **pmaps, const PhotonMapPara
75           /* Assign to appropriate photon map type (deleting previously
76            * loaded photon map of same type if necessary) */
77           if (pmaps [type]) {
78 +            sprintf(errmsg, "multiple %s photon maps, dropping previous",
79 +                    pmapName [type]);
80 +            error(WARNING, errmsg);
81              deletePhotons(pmaps [type]);
82              free(pmaps [type]);
83           }
84           pmaps [type] = pm;
85 <        
86 <         /* Check for invalid density estimate bandwidth */                            
85 >
86 >         /* Check for valid density estimate bandwidths */
87 >         if ((pm -> minGather > 1 || pm -> maxGather > 1) &&
88 >             (type == PMAP_TYPE_PRECOMP)) {
89 >            /* Force bwidth to 1 for precomputed pmap */
90 >            error(WARNING, "ignoring bandwidth for precomp photon map");
91 >            pm -> minGather = pm -> maxGather = 1;
92 >         }
93 >
94 >         if ((pm -> maxGather > pm -> minGather) &&
95 >             (type == PMAP_TYPE_VOLUME)) {            
96 >            /* Biascomp for volume pmaps (see volumePhotonDensity() below)
97 >               is considered redundant, and there's probably no point in
98 >               recovering by using the lower bandwidth, since it's probably
99 >               not what the user wants, so bail out. */
100 >            sprintf(errmsg,
101 >                    "bias compensation is not available with %s photon maps",
102 >                    pmapName [type]);
103 >            error(USER, errmsg);
104 >         }
105 >
106           if (pm -> maxGather > pm -> numPhotons) {
107 <            error(WARNING, "adjusting density estimate bandwidth");
108 <            pm -> minGather = pm -> maxGather = pm -> numPhotons;
107 >            /* Clamp lookup bandwidth to total number of photons (minus one,
108 >               since density estimate gets extra photon to obtain averaged
109 >               radius) */
110 >            sprintf(
111 >               errmsg, "clamping density estimate bandwidth to %ld",
112 >               pm -> numPhotons
113 >            );
114 >            error(WARNING, errmsg);
115 >            pm -> minGather = pm -> maxGather = pm -> numPhotons - 1;
116           }
117        }
118   }
# Line 98 | Line 127 | void cleanUpPmaps (PhotonMap **pmaps)
127        if (pmaps [t]) {
128           deletePhotons(pmaps [t]);
129           free(pmaps [t]);
130 +         pmaps [t] = NULL;
131        }
132     }
133   }
# Line 109 | Line 139 | void photonDensity (PhotonMap *pmap, RAY *ray, COLOR i
139   /* Photon density estimate. Returns irradiance at ray -> rop. */
140   {
141     unsigned                      i;
142 <   float                         r;
142 >   float                         r2;
143     COLOR                         flux;
144     Photon                        *photon;
145     const PhotonSearchQueueNode   *sqn;
# Line 141 | Line 171 | void photonDensity (PhotonMap *pmap, RAY *ray, COLOR i
171        /* No bias compensation. Just do a plain vanilla estimate */
172        sqn = pmap -> squeue.node + 1;
173        
174 <      /* Average radius between furthest two photons to improve accuracy */      
175 <      r = max(sqn -> dist2, (sqn + 1) -> dist2);
176 <      r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r));  
174 >      /* Average radius^2 between furthest two photons to improve accuracy */
175 >      r2 = max(sqn -> dist2, (sqn + 1) -> dist2);
176 >      r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2));
177        
178        /* Skip the extra photon */
179        for (i = 1 ; i < pmap -> squeue.tail; i++, sqn++) {
# Line 151 | Line 181 | void photonDensity (PhotonMap *pmap, RAY *ray, COLOR i
181           getPhotonFlux(photon, flux);        
182   #ifdef PMAP_EPANECHNIKOV
183           /* Apply Epanechnikov kernel to photon flux based on photon dist */
184 <         scalecolor(flux, 2 * (1 - sqn -> dist2 / r));
184 >         scalecolor(flux, 2 * (1 - sqn -> dist2 / r2));
185   #endif  
186           addcolor(irrad, flux);
187        }
188        
189        /* Divide by search area PI * r^2, 1 / PI required as ambient
190           normalisation factor */        
191 <      scalecolor(irrad, 1 / (PI * PI * r));
191 >      scalecolor(irrad, 1 / (PI * PI * r2));
192        
193        return;
194     }
# Line 181 | Line 211 | void photonPreCompDensity (PhotonMap *pmap, RAY *r, CO
211     if (r -> ro && islight(objptr(r -> ro -> omod) -> otype))
212        return;
213        
214 <   find1Photon(preCompPmap, r, &p);
215 <   getPhotonFlux(&p, irrad);
214 >   if (find1Photon(preCompPmap, r, &p))
215 >      /* p contains a found photon, so get its irradiance, otherwise it
216 >       * remains zero under the assumption all photons are too distant
217 >       * to contribute significantly */
218 >      getPhotonFlux(&p, irrad);
219   }
220  
221  
# Line 192 | Line 225 | void volumePhotonDensity (PhotonMap *pmap, RAY *ray, C
225   /* Photon volume density estimate. Returns irradiance at ray -> rop. */
226   {
227     unsigned                      i;
228 <   float                         r, gecc2, ph;
228 >   float                         r2, gecc2, ph;
229     COLOR                         flux;
230     Photon                        *photon;
231     const PhotonSearchQueueNode   *sqn;
# Line 217 | Line 250 | void volumePhotonDensity (PhotonMap *pmap, RAY *ray, C
250        gecc2 = ray -> gecc * ray -> gecc;
251        sqn = pmap -> squeue.node + 1;
252        
253 <      /* Average radius between furthest two photons to improve accuracy */      
254 <      r = max(sqn -> dist2, (sqn + 1) -> dist2);
255 <      r = 0.25 * (pmap -> maxDist2 + r + 2 * sqrt(pmap -> maxDist2 * r));  
253 >      /* Average radius^2 between furthest two photons to improve accuracy */      
254 >      r2 = max(sqn -> dist2, (sqn + 1) -> dist2);
255 >      r2 = 0.25 * (pmap -> maxDist2 + r2 + 2 * sqrt(pmap -> maxDist2 * r2));
256        
257        /* Skip the extra photon */
258        for (i = 1; i < pmap -> squeue.tail; i++, sqn++) {
# Line 241 | Line 274 | void volumePhotonDensity (PhotonMap *pmap, RAY *ray, C
274        
275        /* Divide by search volume 4 / 3 * PI * r^3 and phase function
276           normalization factor 1 / (4 * PI) */
277 <      scalecolor(irrad, 3 / (16 * PI * PI * r * sqrt(r)));
277 >      scalecolor(irrad, 3 / (16 * PI * PI * r2 * sqrt(r2)));
278        return;
279     }
280   #if 0

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines