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

# Content
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 }