ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 2.3
Committed: Wed Aug 12 14:44:15 1992 UTC (31 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +13 -1 lines
Log Message:
made off-axis polygons sample better

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