ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.2
Committed: Wed Mar 11 12:25:47 1992 UTC (32 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +4 -5 lines
Log Message:
changed so light below threshold is printed as ordinary object

File Contents

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