ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.11
Committed: Mon Jun 30 14:59:11 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.10: +4 -2 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

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