ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 1.7
Committed: Thu Jul 25 14:12:22 1991 UTC (32 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +3 -3 lines
Log Message:
*** empty log message ***

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