ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 1.11
Committed: Thu Aug 22 12:12:23 1991 UTC (32 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +39 -19 lines
Log Message:
interpret d=0 to mean diffuse source
changed peano() calls to multisamp()

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 greg 1.4 * Routines to do the actual calculation for mkillum
9 greg 1.1 */
10    
11     #include "mkillum.h"
12    
13     #include "face.h"
14    
15     #include "cone.h"
16    
17 greg 1.2 #include "random.h"
18 greg 1.1
19 greg 1.2
20     o_default(ob, il, rt, nm) /* default illum action */
21 greg 1.1 OBJREC *ob;
22     struct illum_args *il;
23     struct rtproc *rt;
24 greg 1.2 char *nm;
25 greg 1.1 {
26 greg 1.2 sprintf(errmsg, "(%s): cannot make illum for %s \"%s\"",
27     nm, ofun[ob->otype].funame, ob->oname);
28     error(WARNING, errmsg);
29     if (!(il->flags & IL_LIGHT))
30 greg 1.4 printobj(il->altmat, ob);
31 greg 1.2 }
32    
33    
34     o_face(ob, il, rt, nm) /* make an illum face */
35     OBJREC *ob;
36     struct illum_args *il;
37     struct rtproc *rt;
38     char *nm;
39     {
40 greg 1.3 #define MAXMISS (5*n*il->nsamps)
41 greg 1.10 int dim[3];
42     int n, nalt, nazi, h;
43 greg 1.3 float *distarr;
44 greg 1.10 double sp[2], r1, r2;
45 greg 1.4 FVECT dn, org, dir;
46 greg 1.3 FVECT u, v;
47     double ur[2], vr[2];
48     int nmisses;
49     register FACE *fa;
50     register int i, j;
51     /* get/check arguments */
52     fa = getface(ob);
53     if (fa->area == 0.0) {
54     freeface(ob);
55     o_default(ob, il, rt, nm);
56     return;
57     }
58     /* set up sampling */
59 greg 1.11 if (il->sampdens <= 0)
60     nalt = nazi = 1;
61     else {
62     n = PI * il->sampdens;
63     nalt = sqrt(n/PI) + .5;
64     nazi = PI*nalt + .5;
65     }
66 greg 1.3 n = nalt*nazi;
67     distarr = (float *)calloc(n, 3*sizeof(float));
68     if (distarr == NULL)
69     error(SYSTEM, "out of memory in o_face");
70     mkaxes(u, v, fa->norm);
71     ur[0] = vr[0] = FHUGE;
72     ur[1] = vr[1] = -FHUGE;
73     for (i = 0; i < fa->nv; i++) {
74     r1 = DOT(VERTEX(fa,i),u);
75     if (r1 < ur[0]) ur[0] = r1;
76     if (r1 > ur[1]) ur[1] = r1;
77     r2 = DOT(VERTEX(fa,i),v);
78     if (r2 < vr[0]) vr[0] = r2;
79     if (r2 > vr[1]) vr[1] = r2;
80     }
81     dim[0] = random();
82     /* sample polygon */
83     nmisses = 0;
84     for (dim[1] = 0; dim[1] < nalt; dim[1]++)
85     for (dim[2] = 0; dim[2] < nazi; dim[2]++)
86     for (i = 0; i < il->nsamps; i++) {
87     /* random direction */
88 greg 1.10 h = ilhash(dim, 3) + i;
89 greg 1.11 multisamp(sp, 2, urand(h));
90 greg 1.10 r1 = (dim[1] + sp[0])/nalt;
91     r2 = (dim[2] + sp[1])/nazi;
92 greg 1.3 flatdir(dn, r1, r2);
93     for (j = 0; j < 3; j++)
94 greg 1.5 dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*fa->norm[j];
95 greg 1.3 /* random location */
96     do {
97 greg 1.11 multisamp(sp, 2, urand(h+4862+nmisses));
98 greg 1.10 r1 = ur[0] + (ur[1]-ur[0]) * sp[0];
99     r2 = vr[0] + (vr[1]-vr[0]) * sp[1];
100 greg 1.3 for (j = 0; j < 3; j++)
101     org[j] = r1*u[j] + r2*v[j]
102     + fa->offset*fa->norm[j];
103     } while (!inface(org, fa) && nmisses++ < MAXMISS);
104     if (nmisses > MAXMISS) {
105     objerror(ob, WARNING, "bad aspect");
106     rt->nrays = 0;
107     freeface(ob);
108     free((char *)distarr);
109     o_default(ob, il, rt, nm);
110     return;
111     }
112     for (j = 0; j < 3; j++)
113     org[j] += .001*fa->norm[j];
114     /* send sample */
115 greg 1.7 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
116 greg 1.3 }
117     rayflush(rt);
118 greg 1.11 /* write out the face and its distribution */
119     average(il, distarr, nalt*nazi);
120     if (il->sampdens > 0)
121     flatout(il, distarr, nalt, nazi, u, v, fa->norm);
122 greg 1.4 illumout(il, ob);
123 greg 1.3 /* clean up */
124     freeface(ob);
125     free((char *)distarr);
126     #undef MAXMISS
127 greg 1.2 }
128    
129    
130     o_sphere(ob, il, rt, nm) /* make an illum sphere */
131 greg 1.3 register OBJREC *ob;
132 greg 1.2 struct illum_args *il;
133     struct rtproc *rt;
134     char *nm;
135     {
136 greg 1.10 int dim[3];
137 greg 1.2 int n, nalt, nazi;
138     float *distarr;
139 greg 1.10 double sp[4], r1, r2, r3;
140 greg 1.4 FVECT org, dir;
141 greg 1.2 FVECT u, v;
142     register int i, j;
143     /* check arguments */
144     if (ob->oargs.nfargs != 4)
145     objerror(ob, USER, "bad # of arguments");
146     /* set up sampling */
147 greg 1.11 if (il->sampdens <= 0)
148     nalt = nazi = 1;
149     else {
150     n = 4.*PI * il->sampdens;
151     nalt = sqrt(n/PI) + .5;
152     nazi = PI*nalt + .5;
153     }
154 greg 1.2 n = nalt*nazi;
155     distarr = (float *)calloc(n, 3*sizeof(float));
156     if (distarr == NULL)
157     error(SYSTEM, "out of memory in o_sphere");
158     dim[0] = random();
159     /* sample sphere */
160     for (dim[1] = 0; dim[1] < nalt; dim[1]++)
161 greg 1.8 for (dim[2] = 0; dim[2] < nazi; dim[2]++)
162 greg 1.2 for (i = 0; i < il->nsamps; i++) {
163 greg 1.10 /* next sample point */
164 greg 1.11 multisamp(sp, 4, urand(ilhash(dim,3)+i));
165 greg 1.2 /* random direction */
166 greg 1.10 r1 = (dim[1] + sp[0])/nalt;
167     r2 = (dim[2] + sp[1])/nazi;
168 greg 1.2 rounddir(dir, r1, r2);
169     /* random location */
170 greg 1.8 mkaxes(u, v, dir); /* yuck! */
171 greg 1.10 r3 = sqrt(sp[2]);
172     r2 = 2.*PI*sp[3];
173 greg 1.5 r1 = r3*ob->oargs.farg[3]*cos(r2);
174     r2 = r3*ob->oargs.farg[3]*sin(r2);
175     r3 = ob->oargs.farg[3]*sqrt(1.01-r3*r3);
176     for (j = 0; j < 3; j++) {
177     org[j] = ob->oargs.farg[j] + r1*u[j] + r2*v[j] +
178     r3*dir[j];
179     dir[j] = -dir[j];
180     }
181 greg 1.2 /* send sample */
182 greg 1.7 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
183 greg 1.2 }
184     rayflush(rt);
185 greg 1.11 /* write out the sphere and its distribution */
186     average(il, distarr, nalt*nazi);
187     if (il->sampdens > 0)
188     roundout(il, distarr, nalt, nazi);
189     else
190     objerror(ob, WARNING, "diffuse distribution");
191 greg 1.4 illumout(il, ob);
192 greg 1.2 /* clean up */
193     free((char *)distarr);
194     }
195    
196    
197     o_ring(ob, il, rt, nm) /* make an illum ring */
198     OBJREC *ob;
199     struct illum_args *il;
200     struct rtproc *rt;
201     char *nm;
202     {
203 greg 1.10 int dim[3];
204 greg 1.3 int n, nalt, nazi;
205     float *distarr;
206 greg 1.10 double sp[4], r1, r2, r3;
207 greg 1.4 FVECT dn, org, dir;
208 greg 1.3 FVECT u, v;
209     register CONE *co;
210     register int i, j;
211     /* get/check arguments */
212     co = getcone(ob, 0);
213     /* set up sampling */
214 greg 1.11 if (il->sampdens <= 0)
215     nalt = nazi = 1;
216     else {
217     n = PI * il->sampdens;
218     nalt = sqrt(n/PI) + .5;
219     nazi = PI*nalt + .5;
220     }
221 greg 1.3 n = nalt*nazi;
222     distarr = (float *)calloc(n, 3*sizeof(float));
223     if (distarr == NULL)
224     error(SYSTEM, "out of memory in o_ring");
225     mkaxes(u, v, co->ad);
226     dim[0] = random();
227     /* sample disk */
228     for (dim[1] = 0; dim[1] < nalt; dim[1]++)
229     for (dim[2] = 0; dim[2] < nazi; dim[2]++)
230     for (i = 0; i < il->nsamps; i++) {
231 greg 1.10 /* next sample point */
232 greg 1.11 multisamp(sp, 4, urand(ilhash(dim,3)+i));
233 greg 1.3 /* random direction */
234 greg 1.10 r1 = (dim[1] + sp[0])/nalt;
235     r2 = (dim[2] + sp[1])/nalt;
236 greg 1.3 flatdir(dn, r1, r2);
237     for (j = 0; j < 3; j++)
238 greg 1.5 dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*co->ad[j];
239 greg 1.3 /* random location */
240 greg 1.5 r3 = sqrt(CO_R0(co)*CO_R0(co) +
241 greg 1.10 sp[2]*(CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co)));
242     r2 = 2.*PI*sp[3];
243 greg 1.5 r1 = r3*cos(r2);
244     r2 = r3*sin(r2);
245 greg 1.3 for (j = 0; j < 3; j++)
246 greg 1.5 org[j] = CO_P0(co)[j] + r1*u[j] + r1*v[j] +
247     .001*co->ad[j];
248 greg 1.3
249     /* send sample */
250 greg 1.7 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
251 greg 1.3 }
252     rayflush(rt);
253 greg 1.11 /* write out the ring and its distribution */
254     average(il, distarr, nalt*nazi);
255     if (il->sampdens > 0)
256     flatout(il, distarr, nalt, nazi, u, v, co->ad);
257 greg 1.4 illumout(il, ob);
258 greg 1.3 /* clean up */
259     freecone(ob);
260     free((char *)distarr);
261 greg 1.2 }
262    
263    
264     raysamp(res, org, dir, rt) /* compute a ray sample */
265     float res[3];
266     FVECT org, dir;
267     register struct rtproc *rt;
268     {
269     register float *fp;
270    
271     if (rt->nrays == rt->bsiz)
272     rayflush(rt);
273     rt->dest[rt->nrays] = res;
274     fp = rt->buf + 6*rt->nrays++;
275     *fp++ = org[0]; *fp++ = org[1]; *fp++ = org[2];
276     *fp++ = dir[0]; *fp++ = dir[1]; *fp = dir[2];
277     }
278    
279    
280     rayflush(rt) /* flush buffered rays */
281     register struct rtproc *rt;
282     {
283     register int i;
284    
285     if (rt->nrays <= 0)
286     return;
287 greg 1.9 bzero(rt->buf+6*rt->nrays, 6*sizeof(float));
288 greg 1.2 if ( process(rt->pd, (char *)rt->buf, (char *)rt->buf,
289     3*sizeof(float)*rt->nrays,
290     6*sizeof(float)*(rt->nrays+1)) <
291     3*sizeof(float)*rt->nrays )
292     error(SYSTEM, "error reading from rtrace process");
293     i = rt->nrays;
294     while (i--) {
295     rt->dest[i][0] += rt->buf[3*i];
296     rt->dest[i][1] += rt->buf[3*i+1];
297     rt->dest[i][2] += rt->buf[3*i+2];
298     }
299     rt->nrays = 0;
300 greg 1.4 }
301    
302    
303     mkaxes(u, v, n) /* compute u and v to go with n */
304     FVECT u, v, n;
305     {
306     register int i;
307    
308     v[0] = v[1] = v[2] = 0.0;
309     for (i = 0; i < 3; i++)
310     if (n[i] < 0.6 && n[i] > -0.6)
311     break;
312     v[i] = 1.0;
313     fcross(u, v, n);
314     normalize(u);
315     fcross(v, n, u);
316     }
317    
318    
319     rounddir(dv, alt, azi) /* compute uniform spherical direction */
320     register FVECT dv;
321     double alt, azi;
322     {
323     double d1, d2;
324    
325     dv[2] = 1. - 2.*alt;
326     d1 = sqrt(1. - dv[2]*dv[2]);
327     d2 = 2.*PI * azi;
328     dv[0] = d1*cos(d2);
329     dv[1] = d1*sin(d2);
330     }
331    
332    
333     flatdir(dv, alt, azi) /* compute uniform hemispherical direction */
334     register FVECT dv;
335     double alt, azi;
336     {
337     double d1, d2;
338    
339     d1 = sqrt(alt);
340     d2 = 2.*PI * azi;
341     dv[0] = d1*cos(d2);
342     dv[1] = d1*sin(d2);
343 greg 1.6 dv[2] = sqrt(1. - alt);
344 greg 1.1 }