ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.10
Committed: Thu Jun 26 00:58:09 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.9: +2 -5 lines
Log Message:
Abstracted process and path handling for Windows.
Renamed FLOAT to RREAL because of conflict on Windows.
Added conditional compiles for some signal handlers.

File Contents

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