ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.18
Committed: Thu Sep 13 06:31:21 2007 UTC (16 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.17: +86 -138 lines
Log Message:
Changed mkillum from calling rtrace to calling Radiance library (raypcalls.o)

File Contents

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