ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.9
Committed: Sat Feb 22 02:07:24 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.8: +5 -8 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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