ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/mkillum2.c
Revision: 1.7
Committed: Thu Jul 25 14:12:22 1991 UTC (32 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +3 -3 lines
Log Message:
*** empty log message ***

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