ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambcomp.c
Revision: 2.25
Committed: Fri Apr 11 20:31:37 2014 UTC (10 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.24: +7 -3 lines
Log Message:
Partial implementation of Hessian gradient calculation (-DNEWAMB)

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ambcomp.c,v 2.24 2013/08/07 05:10:09 greg Exp $";
3 #endif
4 /*
5 * Routines to compute "ambient" values using Monte Carlo
6 *
7 * Declarations of external symbols in ambient.h
8 */
9
10 #include "copyright.h"
11
12 #include "ray.h"
13 #include "ambient.h"
14 #include "random.h"
15
16 #ifdef NEWAMB
17
18 #else /* ! NEWAMB */
19
20
21 void
22 inithemi( /* initialize sampling hemisphere */
23 AMBHEMI *hp,
24 COLOR ac,
25 RAY *r,
26 double wt
27 )
28 {
29 double d;
30 int i;
31 /* set number of divisions */
32 if (ambacc <= FTINY &&
33 wt > (d = 0.8*intens(ac)*r->rweight/(ambdiv*minweight)))
34 wt = d; /* avoid ray termination */
35 hp->nt = sqrt(ambdiv * wt / PI) + 0.5;
36 i = ambacc > FTINY ? 3 : 1; /* minimum number of samples */
37 if (hp->nt < i)
38 hp->nt = i;
39 hp->np = PI * hp->nt + 0.5;
40 /* set number of super-samples */
41 hp->ns = ambssamp * wt + 0.5;
42 /* assign coefficient */
43 copycolor(hp->acoef, ac);
44 d = 1.0/(hp->nt*hp->np);
45 scalecolor(hp->acoef, d);
46 /* make axes */
47 VCOPY(hp->uz, r->ron);
48 hp->uy[0] = hp->uy[1] = hp->uy[2] = 0.0;
49 for (i = 0; i < 3; i++)
50 if (hp->uz[i] < 0.6 && hp->uz[i] > -0.6)
51 break;
52 if (i >= 3)
53 error(CONSISTENCY, "bad ray direction in inithemi");
54 hp->uy[i] = 1.0;
55 fcross(hp->ux, hp->uy, hp->uz);
56 normalize(hp->ux);
57 fcross(hp->uy, hp->uz, hp->ux);
58 }
59
60
61 int
62 divsample( /* sample a division */
63 AMBSAMP *dp,
64 AMBHEMI *h,
65 RAY *r
66 )
67 {
68 RAY ar;
69 int hlist[3];
70 double spt[2];
71 double xd, yd, zd;
72 double b2;
73 double phi;
74 int i;
75 /* ambient coefficient for weight */
76 if (ambacc > FTINY)
77 setcolor(ar.rcoef, AVGREFL, AVGREFL, AVGREFL);
78 else
79 copycolor(ar.rcoef, h->acoef);
80 if (rayorigin(&ar, AMBIENT, r, ar.rcoef) < 0)
81 return(-1);
82 if (ambacc > FTINY) {
83 multcolor(ar.rcoef, h->acoef);
84 scalecolor(ar.rcoef, 1./AVGREFL);
85 }
86 hlist[0] = r->rno;
87 hlist[1] = dp->t;
88 hlist[2] = dp->p;
89 multisamp(spt, 2, urand(ilhash(hlist,3)+dp->n));
90 zd = sqrt((dp->t + spt[0])/h->nt);
91 phi = 2.0*PI * (dp->p + spt[1])/h->np;
92 xd = tcos(phi) * zd;
93 yd = tsin(phi) * zd;
94 zd = sqrt(1.0 - zd*zd);
95 for (i = 0; i < 3; i++)
96 ar.rdir[i] = xd*h->ux[i] +
97 yd*h->uy[i] +
98 zd*h->uz[i];
99 checknorm(ar.rdir);
100 dimlist[ndims++] = dp->t*h->np + dp->p + 90171;
101 rayvalue(&ar);
102 ndims--;
103 multcolor(ar.rcol, ar.rcoef); /* apply coefficient */
104 addcolor(dp->v, ar.rcol);
105 /* use rt to improve gradient calc */
106 if (ar.rt > FTINY && ar.rt < FHUGE)
107 dp->r += 1.0/ar.rt;
108 /* (re)initialize error */
109 if (dp->n++) {
110 b2 = bright(dp->v)/dp->n - bright(ar.rcol);
111 b2 = b2*b2 + dp->k*((dp->n-1)*(dp->n-1));
112 dp->k = b2/(dp->n*dp->n);
113 } else
114 dp->k = 0.0;
115 return(0);
116 }
117
118
119 static int
120 ambcmp( /* decreasing order */
121 const void *p1,
122 const void *p2
123 )
124 {
125 const AMBSAMP *d1 = (const AMBSAMP *)p1;
126 const AMBSAMP *d2 = (const AMBSAMP *)p2;
127
128 if (d1->k < d2->k)
129 return(1);
130 if (d1->k > d2->k)
131 return(-1);
132 return(0);
133 }
134
135
136 static int
137 ambnorm( /* standard order */
138 const void *p1,
139 const void *p2
140 )
141 {
142 const AMBSAMP *d1 = (const AMBSAMP *)p1;
143 const AMBSAMP *d2 = (const AMBSAMP *)p2;
144 int c;
145
146 if ( (c = d1->t - d2->t) )
147 return(c);
148 return(d1->p - d2->p);
149 }
150
151
152 double
153 doambient( /* compute ambient component */
154 COLOR rcol,
155 RAY *r,
156 double wt,
157 FVECT pg,
158 FVECT dg
159 )
160 {
161 double b, d=0;
162 AMBHEMI hemi;
163 AMBSAMP *div;
164 AMBSAMP dnew;
165 double acol[3];
166 AMBSAMP *dp;
167 double arad;
168 int divcnt;
169 int i, j;
170 /* initialize hemisphere */
171 inithemi(&hemi, rcol, r, wt);
172 divcnt = hemi.nt * hemi.np;
173 /* initialize */
174 if (pg != NULL)
175 pg[0] = pg[1] = pg[2] = 0.0;
176 if (dg != NULL)
177 dg[0] = dg[1] = dg[2] = 0.0;
178 setcolor(rcol, 0.0, 0.0, 0.0);
179 if (divcnt == 0)
180 return(0.0);
181 /* allocate super-samples */
182 if (hemi.ns > 0 || pg != NULL || dg != NULL) {
183 div = (AMBSAMP *)malloc(divcnt*sizeof(AMBSAMP));
184 if (div == NULL)
185 error(SYSTEM, "out of memory in doambient");
186 } else
187 div = NULL;
188 /* sample the divisions */
189 arad = 0.0;
190 acol[0] = acol[1] = acol[2] = 0.0;
191 if ((dp = div) == NULL)
192 dp = &dnew;
193 divcnt = 0;
194 for (i = 0; i < hemi.nt; i++)
195 for (j = 0; j < hemi.np; j++) {
196 dp->t = i; dp->p = j;
197 setcolor(dp->v, 0.0, 0.0, 0.0);
198 dp->r = 0.0;
199 dp->n = 0;
200 if (divsample(dp, &hemi, r) < 0) {
201 if (div != NULL)
202 dp++;
203 continue;
204 }
205 arad += dp->r;
206 divcnt++;
207 if (div != NULL)
208 dp++;
209 else
210 addcolor(acol, dp->v);
211 }
212 if (!divcnt) {
213 if (div != NULL)
214 free((void *)div);
215 return(0.0); /* no samples taken */
216 }
217 if (divcnt < hemi.nt*hemi.np) {
218 pg = dg = NULL; /* incomplete sampling */
219 hemi.ns = 0;
220 } else if (arad > FTINY && divcnt/arad < minarad) {
221 hemi.ns = 0; /* close enough */
222 } else if (hemi.ns > 0) { /* else perform super-sampling? */
223 comperrs(div, &hemi); /* compute errors */
224 qsort(div, divcnt, sizeof(AMBSAMP), ambcmp); /* sort divs */
225 /* super-sample */
226 for (i = hemi.ns; i > 0; i--) {
227 dnew = *div;
228 if (divsample(&dnew, &hemi, r) < 0) {
229 dp++;
230 continue;
231 }
232 dp = div; /* reinsert */
233 j = divcnt < i ? divcnt : i;
234 while (--j > 0 && dnew.k < dp[1].k) {
235 *dp = *(dp+1);
236 dp++;
237 }
238 *dp = dnew;
239 }
240 if (pg != NULL || dg != NULL) /* restore order */
241 qsort(div, divcnt, sizeof(AMBSAMP), ambnorm);
242 }
243 /* compute returned values */
244 if (div != NULL) {
245 arad = 0.0; /* note: divcnt may be < nt*np */
246 for (i = hemi.nt*hemi.np, dp = div; i-- > 0; dp++) {
247 arad += dp->r;
248 if (dp->n > 1) {
249 b = 1.0/dp->n;
250 scalecolor(dp->v, b);
251 dp->r *= b;
252 dp->n = 1;
253 }
254 addcolor(acol, dp->v);
255 }
256 b = bright(acol);
257 if (b > FTINY) {
258 b = 1.0/b; /* compute & normalize gradient(s) */
259 if (pg != NULL) {
260 posgradient(pg, div, &hemi);
261 for (i = 0; i < 3; i++)
262 pg[i] *= b;
263 }
264 if (dg != NULL) {
265 dirgradient(dg, div, &hemi);
266 for (i = 0; i < 3; i++)
267 dg[i] *= b;
268 }
269 }
270 free((void *)div);
271 }
272 copycolor(rcol, acol);
273 if (arad <= FTINY)
274 arad = maxarad;
275 else
276 arad = (divcnt+hemi.ns)/arad;
277 if (pg != NULL) { /* reduce radius if gradient large */
278 d = DOT(pg,pg);
279 if (d*arad*arad > 1.0)
280 arad = 1.0/sqrt(d);
281 }
282 if (arad < minarad) {
283 arad = minarad;
284 if (pg != NULL && d*arad*arad > 1.0) { /* cap gradient */
285 d = 1.0/arad/sqrt(d);
286 for (i = 0; i < 3; i++)
287 pg[i] *= d;
288 }
289 }
290 if ((arad /= sqrt(wt)) > maxarad)
291 arad = maxarad;
292 return(arad);
293 }
294
295
296 void
297 comperrs( /* compute initial error estimates */
298 AMBSAMP *da, /* assumes standard ordering */
299 AMBHEMI *hp
300 )
301 {
302 double b, b2;
303 int i, j;
304 AMBSAMP *dp;
305 /* sum differences from neighbors */
306 dp = da;
307 for (i = 0; i < hp->nt; i++)
308 for (j = 0; j < hp->np; j++) {
309 #ifdef DEBUG
310 if (dp->t != i || dp->p != j)
311 error(CONSISTENCY,
312 "division order in comperrs");
313 #endif
314 b = bright(dp[0].v);
315 if (i > 0) { /* from above */
316 b2 = bright(dp[-hp->np].v) - b;
317 b2 *= b2 * 0.25;
318 dp[0].k += b2;
319 dp[-hp->np].k += b2;
320 }
321 if (j > 0) { /* from behind */
322 b2 = bright(dp[-1].v) - b;
323 b2 *= b2 * 0.25;
324 dp[0].k += b2;
325 dp[-1].k += b2;
326 } else { /* around */
327 b2 = bright(dp[hp->np-1].v) - b;
328 b2 *= b2 * 0.25;
329 dp[0].k += b2;
330 dp[hp->np-1].k += b2;
331 }
332 dp++;
333 }
334 /* divide by number of neighbors */
335 dp = da;
336 for (j = 0; j < hp->np; j++) /* top row */
337 (dp++)->k *= 1.0/3.0;
338 if (hp->nt < 2)
339 return;
340 for (i = 1; i < hp->nt-1; i++) /* central region */
341 for (j = 0; j < hp->np; j++)
342 (dp++)->k *= 0.25;
343 for (j = 0; j < hp->np; j++) /* bottom row */
344 (dp++)->k *= 1.0/3.0;
345 }
346
347
348 void
349 posgradient( /* compute position gradient */
350 FVECT gv,
351 AMBSAMP *da, /* assumes standard ordering */
352 AMBHEMI *hp
353 )
354 {
355 int i, j;
356 double nextsine, lastsine, b, d;
357 double mag0, mag1;
358 double phi, cosp, sinp, xd, yd;
359 AMBSAMP *dp;
360
361 xd = yd = 0.0;
362 for (j = 0; j < hp->np; j++) {
363 dp = da + j;
364 mag0 = mag1 = 0.0;
365 lastsine = 0.0;
366 for (i = 0; i < hp->nt; i++) {
367 #ifdef DEBUG
368 if (dp->t != i || dp->p != j)
369 error(CONSISTENCY,
370 "division order in posgradient");
371 #endif
372 b = bright(dp->v);
373 if (i > 0) {
374 d = dp[-hp->np].r;
375 if (dp[0].r > d) d = dp[0].r;
376 /* sin(t)*cos(t)^2 */
377 d *= lastsine * (1.0 - (double)i/hp->nt);
378 mag0 += d*(b - bright(dp[-hp->np].v));
379 }
380 nextsine = sqrt((double)(i+1)/hp->nt);
381 if (j > 0) {
382 d = dp[-1].r;
383 if (dp[0].r > d) d = dp[0].r;
384 mag1 += d * (nextsine - lastsine) *
385 (b - bright(dp[-1].v));
386 } else {
387 d = dp[hp->np-1].r;
388 if (dp[0].r > d) d = dp[0].r;
389 mag1 += d * (nextsine - lastsine) *
390 (b - bright(dp[hp->np-1].v));
391 }
392 dp += hp->np;
393 lastsine = nextsine;
394 }
395 mag0 *= 2.0*PI / hp->np;
396 phi = 2.0*PI * (double)j/hp->np;
397 cosp = tcos(phi); sinp = tsin(phi);
398 xd += mag0*cosp - mag1*sinp;
399 yd += mag0*sinp + mag1*cosp;
400 }
401 for (i = 0; i < 3; i++)
402 gv[i] = (xd*hp->ux[i] + yd*hp->uy[i])*(hp->nt*hp->np)/PI;
403 }
404
405
406 void
407 dirgradient( /* compute direction gradient */
408 FVECT gv,
409 AMBSAMP *da, /* assumes standard ordering */
410 AMBHEMI *hp
411 )
412 {
413 int i, j;
414 double mag;
415 double phi, xd, yd;
416 AMBSAMP *dp;
417
418 xd = yd = 0.0;
419 for (j = 0; j < hp->np; j++) {
420 dp = da + j;
421 mag = 0.0;
422 for (i = 0; i < hp->nt; i++) {
423 #ifdef DEBUG
424 if (dp->t != i || dp->p != j)
425 error(CONSISTENCY,
426 "division order in dirgradient");
427 #endif
428 /* tan(t) */
429 mag += bright(dp->v)/sqrt(hp->nt/(i+.5) - 1.0);
430 dp += hp->np;
431 }
432 phi = 2.0*PI * (j+.5)/hp->np + PI/2.0;
433 xd += mag * tcos(phi);
434 yd += mag * tsin(phi);
435 }
436 for (i = 0; i < 3; i++)
437 gv[i] = xd*hp->ux[i] + yd*hp->uy[i];
438 }
439
440 #endif /* ! NEWAMB */