ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 1.14
Committed: Fri Nov 8 13:17:47 1991 UTC (32 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.13: +1 -0 lines
Log Message:
reset errno at appropriate points

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