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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: mkillum2.c,v 2.9 2003/02/22 02:07:24 greg Exp $";
3 #endif
4 /*
5 * Routines to do the actual calculation for mkillum
6 */
7
8 #include "mkillum.h"
9 #include "face.h"
10 #include "cone.h"
11 #include "random.h"
12
13
14 o_default(ob, il, rt, nm) /* default illum action */
15 OBJREC *ob;
16 struct illum_args *il;
17 struct rtproc *rt;
18 char *nm;
19 {
20 sprintf(errmsg, "(%s): cannot make illum for %s \"%s\"",
21 nm, ofun[ob->otype].funame, ob->oname);
22 error(WARNING, errmsg);
23 printobj(il->altmat, ob);
24 }
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 #define MAXMISS (5*n*il->nsamps)
34 int dim[3];
35 int n, nalt, nazi, h;
36 float *distarr;
37 double sp[2], r1, r2;
38 FVECT dn, org, dir;
39 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 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 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 /* take first edge longer than sqrt(area) */
64 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 if ((r1 = DOT(u,u)) >= fa->area-FTINY)
69 break;
70 }
71 if (i < fa->nv) { /* got one! -- let's align our axes */
72 r2 = 1.0/sqrt(r1);
73 u[0] *= r2; u[1] *= r2; u[2] *= r2;
74 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 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 h = ilhash(dim, 3) + i;
96 multisamp(sp, 2, urand(h));
97 r1 = (dim[1] + sp[0])/nalt;
98 r2 = (dim[2] + sp[1] - .5)/nazi;
99 flatdir(dn, r1, r2);
100 for (j = 0; j < 3; j++)
101 dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*fa->norm[j];
102 /* random location */
103 do {
104 multisamp(sp, 2, urand(h+4862+nmisses));
105 r1 = ur[0] + (ur[1]-ur[0]) * sp[0];
106 r2 = vr[0] + (vr[1]-vr[0]) * sp[1];
107 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 free((void *)distarr);
116 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 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
123 }
124 rayflush(rt);
125 /* write out the face and its distribution */
126 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 } else
131 printobj(il->altmat, ob);
132 /* clean up */
133 freeface(ob);
134 free((void *)distarr);
135 #undef MAXMISS
136 }
137
138
139 o_sphere(ob, il, rt, nm) /* make an illum sphere */
140 register OBJREC *ob;
141 struct illum_args *il;
142 struct rtproc *rt;
143 char *nm;
144 {
145 int dim[3];
146 int n, nalt, nazi;
147 float *distarr;
148 double sp[4], r1, r2, r3;
149 FVECT org, dir;
150 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 if (il->sampdens <= 0)
157 nalt = nazi = 1;
158 else {
159 n = 4.*PI * il->sampdens;
160 nalt = sqrt(2./PI*n) + .5;
161 nazi = PI/2.*nalt + .5;
162 }
163 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 for (dim[2] = 0; dim[2] < nazi; dim[2]++)
171 for (i = 0; i < il->nsamps; i++) {
172 /* next sample point */
173 multisamp(sp, 4, urand(ilhash(dim,3)+i));
174 /* random direction */
175 r1 = (dim[1] + sp[0])/nalt;
176 r2 = (dim[2] + sp[1] - .5)/nazi;
177 rounddir(dir, r1, r2);
178 /* random location */
179 mkaxes(u, v, dir); /* yuck! */
180 r3 = sqrt(sp[2]);
181 r2 = 2.*PI*sp[3];
182 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 /* send sample */
191 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
192 }
193 rayflush(rt);
194 /* write out the sphere and its distribution */
195 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 } else
202 printobj(il->altmat, ob);
203 /* clean up */
204 free((void *)distarr);
205 }
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 int dim[3];
215 int n, nalt, nazi;
216 float *distarr;
217 double sp[4], r1, r2, r3;
218 FVECT dn, org, dir;
219 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 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 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 /* next sample point */
243 multisamp(sp, 4, urand(ilhash(dim,3)+i));
244 /* random direction */
245 r1 = (dim[1] + sp[0])/nalt;
246 r2 = (dim[2] + sp[1] - .5)/nazi;
247 flatdir(dn, r1, r2);
248 for (j = 0; j < 3; j++)
249 dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*co->ad[j];
250 /* random location */
251 r3 = sqrt(CO_R0(co)*CO_R0(co) +
252 sp[2]*(CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co)));
253 r2 = 2.*PI*sp[3];
254 r1 = r3*cos(r2);
255 r2 = r3*sin(r2);
256 for (j = 0; j < 3; j++)
257 org[j] = CO_P0(co)[j] + r1*u[j] + r2*v[j] +
258 .001*co->ad[j];
259
260 /* send sample */
261 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
262 }
263 rayflush(rt);
264 /* write out the ring and its distribution */
265 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 } else
270 printobj(il->altmat, ob);
271 /* clean up */
272 freecone(ob);
273 free((void *)distarr);
274 }
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 bzero(rt->buf+6*rt->nrays, 6*sizeof(float));
301 errno = 0;
302 if ( process(&(rt->pd), (char *)rt->buf, (char *)rt->buf,
303 3*sizeof(float)*(rt->nrays+1),
304 6*sizeof(float)*(rt->nrays+1)) <
305 3*sizeof(float)*(rt->nrays+1) )
306 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 }
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 dv[2] = sqrt(1. - alt);
358 }