ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ambcomp.c
Revision: 1.1
Committed: Fri Jun 7 10:03:52 1991 UTC (32 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1991 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Routines to compute "ambient" values using Monte Carlo
9     */
10    
11     #include "ray.h"
12    
13     #include "ambient.h"
14    
15     #include "random.h"
16    
17     typedef struct {
18     short t, p; /* theta, phi indices */
19     COLOR v; /* value sum */
20     float k; /* error contribution for this division */
21     int n; /* number of subsamples */
22     } AMBSAMP; /* ambient division sample */
23    
24     typedef struct {
25     FVECT ux, uy, uz; /* x, y and z axis directions */
26     short nt, np; /* number of theta and phi directions */
27     } AMBHEMI; /* ambient sample hemisphere */
28    
29     extern double sin(), cos(), sqrt();
30    
31    
32     static int
33     ambcmp(d1, d2) /* decreasing order */
34     AMBSAMP *d1, *d2;
35     {
36     if (d1->k < d2->k)
37     return(1);
38     if (d1->k > d2->k)
39     return(-1);
40     return(0);
41     }
42    
43    
44     static int
45     ambnorm(d1, d2) /* standard order */
46     AMBSAMP *d1, *d2;
47     {
48     register int c;
49    
50     if (c = d1->t - d2->t)
51     return(c);
52     return(d1->p - d2->p);
53     }
54    
55    
56     static double
57     divsample(dp, h, r) /* sample a division */
58     register AMBSAMP *dp;
59     AMBHEMI *h;
60     RAY *r;
61     {
62     RAY ar;
63     int hlist[4];
64     double xd, yd, zd;
65     double b2;
66     double phi;
67     register int k;
68    
69     if (rayorigin(&ar, r, AMBIENT, 0.5) < 0)
70     return(0.0);
71     hlist[0] = r->rno;
72     hlist[1] = dp->t;
73     hlist[2] = dp->p;
74     hlist[3] = 0;
75     zd = sqrt((dp->t+urand(ilhash(hlist,4)+dp->n))/h->nt);
76     hlist[3] = 1;
77     phi = 2.0*PI * (dp->p+urand(ilhash(hlist,4)+dp->n))/h->np;
78     xd = cos(phi) * zd;
79     yd = sin(phi) * zd;
80     zd = sqrt(1.0 - zd*zd);
81     for (k = 0; k < 3; k++)
82     ar.rdir[k] = xd*h->ux[k] +
83     yd*h->uy[k] +
84     zd*h->uz[k];
85     dimlist[ndims++] = dp->t*h->np + dp->p + 38813;
86     rayvalue(&ar);
87     ndims--;
88     addcolor(dp->v, ar.rcol);
89     /* (re)initialize error */
90     if (dp->n++) {
91     b2 = bright(dp->v)/dp->n - bright(ar.rcol);
92     b2 = b2*b2 + dp->k*((dp->n-1)*(dp->n-1));
93     dp->k = b2/(dp->n*dp->n);
94     } else
95     dp->k = 0.0;
96     return(ar.rot);
97     }
98    
99    
100     double
101     doambient(acol, r, pg, dg) /* compute ambient component */
102     COLOR acol;
103     RAY *r;
104     FVECT pg, dg;
105     {
106     double b, d;
107     AMBHEMI hemi;
108     AMBSAMP *div;
109     AMBSAMP dnew;
110     register AMBSAMP *dp;
111     double arad;
112     int ndivs, ns;
113     register int i, j;
114     /* initialize color */
115     setcolor(acol, 0.0, 0.0, 0.0);
116     /* initialize hemisphere */
117     inithemi(&hemi, r);
118     ndivs = hemi.nt * hemi.np;
119     if (ndivs == 0)
120     return(0.0);
121     /* set number of super-samples */
122     ns = ambssamp * r->rweight + 0.5;
123     if (ns > 0 || pg != NULL || dg != NULL) {
124     div = (AMBSAMP *)malloc(ndivs*sizeof(AMBSAMP));
125     if (div == NULL)
126     error(SYSTEM, "out of memory in doambient");
127     } else
128     div = NULL;
129     /* sample the divisions */
130     arad = 0.0;
131     if ((dp = div) == NULL)
132     dp = &dnew;
133     for (i = 0; i < hemi.nt; i++)
134     for (j = 0; j < hemi.np; j++) {
135     dp->t = i; dp->p = j;
136     setcolor(dp->v, 0.0, 0.0, 0.0);
137     dp->n = 0;
138     if ((d = divsample(dp, &hemi, r)) == 0.0)
139     goto oopsy;
140     if (d < FHUGE)
141     arad += 1.0 / d;
142     if (div != NULL)
143     dp++;
144     else
145     addcolor(acol, dp->v);
146     }
147     if (ns > 0) { /* perform super-sampling */
148     comperrs(div, hemi); /* compute errors */
149     qsort(div, ndivs, sizeof(AMBSAMP), ambcmp); /* sort divs */
150     dp = div + ndivs; /* skim excess */
151     for (i = ndivs; i > ns; i--) {
152     dp--;
153     addcolor(acol, dp->v);
154     }
155     /* super-sample */
156     for (i = ns; i > 0; i--) {
157     copystruct(&dnew, div);
158     if ((d = divsample(&dnew, &hemi)) == 0.0)
159     goto oopsy;
160     if (d < FHUGE)
161     arad += 1.0 / d;
162     /* reinsert */
163     dp = div;
164     j = ndivs < i ? ndivs : i;
165     while (--j > 0 && dnew.k < dp[1].k) {
166     copystruct(dp, dp+1);
167     dp++;
168     }
169     copystruct(dp, &dnew);
170     /* extract darkest */
171     if (i <= ndivs) {
172     dp = div + i-1;
173     if (dp->n > 1) {
174     b = 1.0/dp->n;
175     scalecolor(dp->v, b);
176     dp->n = 1;
177     }
178     addcolor(acol, dp->v);
179     }
180     }
181     if (pg != NULL || dg != NULL) /* reorder */
182     qsort(div, ndivs, sizeof(AMBSAMP), ambnorm);
183     }
184     /* compute returned values */
185     if (pg != NULL)
186     posgradient(pg, div, &hemi);
187     if (dg != NULL)
188     dirgradient(dg, div, &hemi);
189     if (div != NULL)
190     free((char *)div);
191     b = 1.0/ndivs;
192     scalecolor(acol, b);
193     if (arad <= FTINY)
194     arad = FHUGE;
195     else
196     arad = (ndivs+ns)/arad;
197     if (arad > maxarad)
198     arad = maxarad;
199     else if (arad < minarad)
200     arad = minarad;
201     arad /= sqrt(r->rweight);
202     return(arad);
203     oopsy:
204     if (div != NULL)
205     free((char *)div);
206     return(0.0);
207     }
208    
209    
210     inithemi(hp, r) /* initialize sampling hemisphere */
211     register AMBHEMI *hp;
212     RAY *r;
213     {
214     register int k;
215     /* set number of divisions */
216     hp->nt = sqrt(ambdiv * r->rweight * 0.5) + 0.5;
217     hp->np = 2 * hp->nt;
218     /* make axes */
219     VCOPY(hp->uz, r->ron);
220     hp->uy[0] = hp->uy[1] = hp->uy[2] = 0.0;
221     for (k = 0; k < 3; k++)
222     if (hp->uz[k] < 0.6 && hp->uz[k] > -0.6)
223     break;
224     if (k >= 3)
225     error(CONSISTENCY, "bad ray direction in inithemi");
226     hp->uy[k] = 1.0;
227     fcross(hp->ux, hp->uz, hp->uy);
228     normalize(hp->ux);
229     fcross(hp->uy, hp->ux, hp->uz);
230     }
231    
232    
233     comperrs(da, hp) /* compute initial error estimates */
234     AMBSAMP *da;
235     register AMBHEMI *hp;
236     {
237     double b, b2;
238     int i, j;
239     register AMBSAMP *dp;
240     /* sum differences from neighbors */
241     dp = da;
242     for (i = 0; i < hp->nt; i++)
243     for (j = 0; j < hp->np; j++) {
244     b = bright(dp[0].v);
245     if (i > 0) { /* from above */
246     b2 = bright(dp[-hp->np].v) - b;
247     b2 *= b2 * 0.25;
248     dp[0].k += b2;
249     dp[-hp->np].k += b2;
250     }
251     if (j > 0) { /* from behind */
252     b2 = bright(dp[-1].v) - b;
253     b2 *= b2 * 0.25;
254     dp[0].k += b2;
255     dp[-1].k += b2;
256     }
257     if (j == hp->np-1) { /* around */
258     b2 = bright(dp[-(hp->np-1)].v) - b;
259     b2 *= b2 * 0.25;
260     dp[0].k += b2;
261     dp[-(hp->np-1)].k += b2;
262     }
263     dp++;
264     }
265     /* divide by number of neighbors */
266     dp = da;
267     for (j = 0; j < hp->np; j++) /* top row */
268     (dp++)->k *= 1.0/3.0;
269     if (hp->nt < 2)
270     return;
271     for (i = 1; i < hp->nt-1; i++) /* central region */
272     for (j = 0; j < hp->np; j++)
273     (dp++)->k *= 0.25;
274     for (j = 0; j < hp->np; j++) /* bottom row */
275     (dp++)->k *= 1.0/3.0;
276     }
277    
278    
279     posgradient(gv, da, hp) /* compute position gradient */
280     FVECT gv;
281     AMBSAMP *da;
282     AMBHEMI *hp;
283     {
284     gv[0] = 0.0; gv[1] = 0.0; gv[2] = 0.0;
285     }
286    
287    
288     dirgradient(gv, da, hp) /* compute direction gradient */
289     FVECT gv;
290     AMBSAMP *da;
291     AMBHEMI *hp;
292     {
293     gv[0] = 0.0; gv[1] = 0.0; gv[2] = 0.0;
294     }