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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Routines to do the actual calculation for mkillum
6 */
7
8 #include "mkillum.h"
9
10 #include "face.h"
11
12 #include "cone.h"
13
14 #include "random.h"
15
16
17 o_default(ob, il, rt, nm) /* default illum action */
18 OBJREC *ob;
19 struct illum_args *il;
20 struct rtproc *rt;
21 char *nm;
22 {
23 sprintf(errmsg, "(%s): cannot make illum for %s \"%s\"",
24 nm, ofun[ob->otype].funame, ob->oname);
25 error(WARNING, errmsg);
26 printobj(il->altmat, ob);
27 }
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 #define MAXMISS (5*n*il->nsamps)
37 int dim[3];
38 int n, nalt, nazi, h;
39 float *distarr;
40 double sp[2], r1, r2;
41 FVECT dn, org, dir;
42 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 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 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 /* take first edge longer than sqrt(area) */
67 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 if ((r1 = DOT(u,u)) >= fa->area-FTINY)
72 break;
73 }
74 if (i < fa->nv) { /* got one! -- let's align our axes */
75 r2 = 1.0/sqrt(r1);
76 u[0] *= r2; u[1] *= r2; u[2] *= r2;
77 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 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 h = ilhash(dim, 3) + i;
99 multisamp(sp, 2, urand(h));
100 r1 = (dim[1] + sp[0])/nalt;
101 r2 = (dim[2] + sp[1] - .5)/nazi;
102 flatdir(dn, r1, r2);
103 for (j = 0; j < 3; j++)
104 dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*fa->norm[j];
105 /* random location */
106 do {
107 multisamp(sp, 2, urand(h+4862+nmisses));
108 r1 = ur[0] + (ur[1]-ur[0]) * sp[0];
109 r2 = vr[0] + (vr[1]-vr[0]) * sp[1];
110 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 free((void *)distarr);
119 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 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
126 }
127 rayflush(rt);
128 /* write out the face and its distribution */
129 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 } else
134 printobj(il->altmat, ob);
135 /* clean up */
136 freeface(ob);
137 free((void *)distarr);
138 #undef MAXMISS
139 }
140
141
142 o_sphere(ob, il, rt, nm) /* make an illum sphere */
143 register OBJREC *ob;
144 struct illum_args *il;
145 struct rtproc *rt;
146 char *nm;
147 {
148 int dim[3];
149 int n, nalt, nazi;
150 float *distarr;
151 double sp[4], r1, r2, r3;
152 FVECT org, dir;
153 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 if (il->sampdens <= 0)
160 nalt = nazi = 1;
161 else {
162 n = 4.*PI * il->sampdens;
163 nalt = sqrt(2./PI*n) + .5;
164 nazi = PI/2.*nalt + .5;
165 }
166 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 for (dim[2] = 0; dim[2] < nazi; dim[2]++)
174 for (i = 0; i < il->nsamps; i++) {
175 /* next sample point */
176 multisamp(sp, 4, urand(ilhash(dim,3)+i));
177 /* random direction */
178 r1 = (dim[1] + sp[0])/nalt;
179 r2 = (dim[2] + sp[1] - .5)/nazi;
180 rounddir(dir, r1, r2);
181 /* random location */
182 mkaxes(u, v, dir); /* yuck! */
183 r3 = sqrt(sp[2]);
184 r2 = 2.*PI*sp[3];
185 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 /* send sample */
194 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
195 }
196 rayflush(rt);
197 /* write out the sphere and its distribution */
198 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 } else
205 printobj(il->altmat, ob);
206 /* clean up */
207 free((void *)distarr);
208 }
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 int dim[3];
218 int n, nalt, nazi;
219 float *distarr;
220 double sp[4], r1, r2, r3;
221 FVECT dn, org, dir;
222 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 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 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 /* next sample point */
246 multisamp(sp, 4, urand(ilhash(dim,3)+i));
247 /* random direction */
248 r1 = (dim[1] + sp[0])/nalt;
249 r2 = (dim[2] + sp[1] - .5)/nazi;
250 flatdir(dn, r1, r2);
251 for (j = 0; j < 3; j++)
252 dir[j] = -dn[0]*u[j] - dn[1]*v[j] - dn[2]*co->ad[j];
253 /* random location */
254 r3 = sqrt(CO_R0(co)*CO_R0(co) +
255 sp[2]*(CO_R1(co)*CO_R1(co) - CO_R0(co)*CO_R0(co)));
256 r2 = 2.*PI*sp[3];
257 r1 = r3*cos(r2);
258 r2 = r3*sin(r2);
259 for (j = 0; j < 3; j++)
260 org[j] = CO_P0(co)[j] + r1*u[j] + r2*v[j] +
261 .001*co->ad[j];
262
263 /* send sample */
264 raysamp(distarr+3*(dim[1]*nazi+dim[2]), org, dir, rt);
265 }
266 rayflush(rt);
267 /* write out the ring and its distribution */
268 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 } else
273 printobj(il->altmat, ob);
274 /* clean up */
275 freecone(ob);
276 free((void *)distarr);
277 }
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 bzero(rt->buf+6*rt->nrays, 6*sizeof(float));
304 errno = 0;
305 if ( process(rt->pd, (char *)rt->buf, (char *)rt->buf,
306 3*sizeof(float)*(rt->nrays+1),
307 6*sizeof(float)*(rt->nrays+1)) <
308 3*sizeof(float)*(rt->nrays+1) )
309 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 }
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 dv[2] = sqrt(1. - alt);
361 }