ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.3
Committed: Wed Aug 12 14:44:15 1992 UTC (31 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +13 -1 lines
Log Message:
made off-axis polygons sample better

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