ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/source.c
Revision: 1.46
Committed: Mon Oct 21 14:23:36 1991 UTC (32 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.45: +2 -2 lines
Log Message:
fixed a couple of minor bugs from last change

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 * source.c - routines dealing with illumination sources.
9 *
10 * 8/20/85
11 */
12
13 #include "ray.h"
14
15 #include "octree.h"
16
17 #include "otypes.h"
18
19 #include "source.h"
20
21 /*
22 * Structures used by direct()
23 */
24
25 typedef struct {
26 int sno; /* source number */
27 FVECT dir; /* source direction */
28 COLOR coef; /* material coefficient */
29 COLOR val; /* contribution */
30 } CONTRIB; /* direct contribution */
31
32 typedef struct {
33 int sndx; /* source index (to CONTRIB array) */
34 float brt; /* brightness (for comparison) */
35 } CNTPTR; /* contribution pointer */
36
37 static CONTRIB *srccnt; /* source contributions in direct() */
38 static CNTPTR *cntord; /* source ordering in direct() */
39 static int maxcntr = 0; /* size of contribution arrays */
40
41
42 marksources() /* find and mark source objects */
43 {
44 int i;
45 register OBJREC *o, *m;
46 register int ns;
47 /* initialize dispatch table */
48 initstypes();
49 /* find direct sources */
50 for (i = 0; i < nobjects; i++) {
51
52 o = objptr(i);
53
54 if (!issurface(o->otype) || o->omod == OVOID)
55 continue;
56
57 m = objptr(o->omod);
58
59 if (!islight(m->otype))
60 continue;
61
62 if (m->oargs.nfargs != (m->otype == MAT_GLOW ? 4 :
63 m->otype == MAT_SPOT ? 7 : 3))
64 objerror(m, USER, "bad # arguments");
65
66 if (m->otype == MAT_GLOW &&
67 o->otype != OBJ_SOURCE &&
68 m->oargs.farg[3] <= FTINY)
69 continue; /* don't bother */
70
71 if (sfun[o->otype].of == NULL ||
72 sfun[o->otype].of->setsrc == NULL)
73 objerror(o, USER, "illegal material");
74
75 if ((ns = newsource()) < 0)
76 goto memerr;
77
78 setsource(&source[ns], o);
79
80 if (m->otype == MAT_GLOW) {
81 source[ns].sflags |= SPROX;
82 source[ns].sl.prox = m->oargs.farg[3];
83 if (o->otype == OBJ_SOURCE)
84 source[ns].sflags |= SSKIP;
85 } else if (m->otype == MAT_SPOT) {
86 source[ns].sflags |= SSPOT;
87 if ((source[ns].sl.s = makespot(m)) == NULL)
88 goto memerr;
89 if (source[ns].sflags & SFLAT &&
90 !checkspot(source[ns].sl.s,source[ns].snorm)) {
91 objerror(o, WARNING,
92 "invalid spotlight direction");
93 source[ns].sflags |= SSKIP;
94 }
95 }
96 }
97 if (nsources <= 0) {
98 error(WARNING, "no light sources found");
99 return;
100 }
101 markvirtuals(); /* find and add virtual sources */
102 /* allocate our contribution arrays */
103 maxcntr = nsources + MAXSPART*2; /* start with this many */
104 srccnt = (CONTRIB *)malloc(maxcntr*sizeof(CONTRIB));
105 cntord = (CNTPTR *)malloc(maxcntr*sizeof(CNTPTR));
106 if (srccnt == NULL || cntord == NULL)
107 goto memerr;
108 return;
109 memerr:
110 error(SYSTEM, "out of memory in marksources");
111 }
112
113
114 srcray(sr, r, si) /* send a ray to a source, return domega */
115 register RAY *sr; /* returned source ray */
116 RAY *r; /* ray which hit object */
117 SRCINDEX *si; /* source sample index */
118 {
119 double d; /* distance to source */
120 FVECT vd;
121 register SRCREC *srcp;
122 register int i;
123
124 rayorigin(sr, r, SHADOW, 1.0); /* ignore limits */
125
126 while ((d = nextssamp(sr->rorg, sr->rdir, si)) != 0.0) {
127 sr->rsrc = si->sn; /* remember source */
128 srcp = source + si->sn;
129 if (srcp->sflags & SDISTANT) {
130 if (srcp->sflags & SSPOT) { /* check location */
131 for (i = 0; i < 3; i++)
132 vd[i] = srcp->sl.s->aim[i] - sr->rorg[i];
133 d = DOT(sr->rdir,vd);
134 if (d <= FTINY)
135 continue;
136 d = DOT(vd,vd) - d*d;
137 if (PI*d > srcp->sl.s->siz)
138 continue;
139 }
140 return(1); /* sample OK */
141 }
142 /* local source */
143 /* check proximity */
144 if (srcp->sflags & SPROX && d > srcp->sl.prox)
145 continue;
146 /* check angle */
147 if (srcp->sflags & SSPOT) {
148 if (srcp->sl.s->siz < 2.0*PI *
149 (1.0 + DOT(srcp->sl.s->aim,sr->rdir)))
150 continue;
151 /* adjust solid angle */
152 si->dom *= d*d;
153 d += srcp->sl.s->flen;
154 si->dom /= d*d;
155 }
156 return(1); /* sample OK */
157 }
158 return(0); /* no more samples */
159 }
160
161
162 srcvalue(r) /* punch ray to source and compute value */
163 RAY *r;
164 {
165 register SRCREC *sp;
166
167 sp = &source[r->rsrc];
168 if (sp->sflags & SVIRTUAL) { /* virtual source */
169 /* check intersection */
170 if (!(*ofun[sp->so->otype].funp)(sp->so, r))
171 return;
172 raycont(r); /* compute contribution */
173 return;
174 }
175 /* compute intersection */
176 if (sp->sflags & SDISTANT ? sourcehit(r) :
177 (*ofun[sp->so->otype].funp)(sp->so, r)) {
178 if (sp->sa.success >= 0)
179 sp->sa.success++;
180 raycont(r); /* compute contribution */
181 return;
182 }
183 if (sp->sa.success < 0)
184 return; /* bitched already */
185 sp->sa.success -= AIMREQT;
186 if (sp->sa.success >= 0)
187 return; /* leniency */
188 sprintf(errmsg, "aiming failure for light source \"%s\"",
189 sp->so->oname);
190 error(WARNING, errmsg); /* issue warning */
191 }
192
193
194 static int
195 cntcmp(sc1, sc2) /* contribution compare (descending) */
196 register CNTPTR *sc1, *sc2;
197 {
198 if (sc1->brt > sc2->brt)
199 return(-1);
200 if (sc1->brt < sc2->brt)
201 return(1);
202 return(0);
203 }
204
205
206 direct(r, f, p) /* add direct component */
207 RAY *r; /* ray that hit surface */
208 int (*f)(); /* direct component coefficient function */
209 char *p; /* data for f */
210 {
211 extern int (*trace)();
212 extern double pow();
213 register int sn;
214 SRCINDEX si;
215 int nshadcheck, ncnts;
216 int nhits;
217 double prob, ourthresh, hwt;
218 RAY sr;
219 /* NOTE: srccnt and cntord global so no recursion */
220 if (nsources <= 0)
221 return; /* no sources?! */
222 /* potential contributions */
223 initsrcindex(&si);
224 for (sn = 0; srcray(&sr, r, &si); sn++) {
225 if (sn >= maxcntr) {
226 maxcntr = sn + MAXSPART;
227 srccnt = (CONTRIB *)realloc((char *)srccnt,
228 maxcntr*sizeof(CONTRIB));
229 cntord = (CNTPTR *)realloc((char *)cntord,
230 maxcntr*sizeof(CNTPTR));
231 if (srccnt == NULL || cntord == NULL)
232 error(SYSTEM, "out of memory in direct");
233 }
234 cntord[sn].sndx = sn;
235 srccnt[sn].sno = sr.rsrc;
236 /* compute coefficient */
237 (*f)(srccnt[sn].coef, p, sr.rdir, si.dom);
238 cntord[sn].brt = bright(srccnt[sn].coef);
239 if (cntord[sn].brt <= 0.0)
240 continue;
241 VCOPY(srccnt[sn].dir, sr.rdir);
242 /* compute potential */
243 sr.revf = srcvalue;
244 rayvalue(&sr);
245 copycolor(srccnt[sn].val, sr.rcol);
246 multcolor(srccnt[sn].val, srccnt[sn].coef);
247 cntord[sn].brt = bright(srccnt[sn].val);
248 }
249 /* sort contributions */
250 qsort(cntord, sn, sizeof(CNTPTR), cntcmp);
251 { /* find last */
252 register int l, m;
253
254 ncnts = l = sn;
255 sn = 0;
256 while ((m = (sn + ncnts) >> 1) != l) {
257 if (cntord[m].brt > 0.0)
258 sn = m;
259 else
260 ncnts = m;
261 l = m;
262 }
263 }
264 /* accumulate tail */
265 for (sn = ncnts-1; sn > 0; sn--)
266 cntord[sn-1].brt += cntord[sn].brt;
267 /* compute number to check */
268 nshadcheck = pow((double)ncnts, shadcert) + .5;
269 /* modify threshold */
270 ourthresh = shadthresh / r->rweight;
271 /* test for shadows */
272 nhits = 0;
273 for (sn = 0; sn < ncnts; sn++) {
274 /* check threshold */
275 if ((sn+nshadcheck>=ncnts ? cntord[sn].brt :
276 cntord[sn].brt-cntord[sn+nshadcheck].brt)
277 < ourthresh*bright(r->rcol))
278 break;
279 /* test for hit */
280 rayorigin(&sr, r, SHADOW, 1.0);
281 VCOPY(sr.rdir, srccnt[cntord[sn].sndx].dir);
282 sr.rsrc = srccnt[cntord[sn].sndx].sno;
283 source[sr.rsrc].ntests++; /* keep statistics */
284 if (localhit(&sr, &thescene) &&
285 ( sr.ro != source[sr.rsrc].so ||
286 source[sr.rsrc].sflags & SFOLLOW )) {
287 /* follow entire path */
288 raycont(&sr);
289 if (trace != NULL)
290 (*trace)(&sr); /* trace execution */
291 if (bright(sr.rcol) <= FTINY)
292 continue; /* missed! */
293 copycolor(srccnt[cntord[sn].sndx].val, sr.rcol);
294 multcolor(srccnt[cntord[sn].sndx].val,
295 srccnt[cntord[sn].sndx].coef);
296 }
297 /* add contribution if hit */
298 addcolor(r->rcol, srccnt[cntord[sn].sndx].val);
299 nhits++;
300 source[sr.rsrc].nhits++;
301 }
302 /* surface hit rate */
303 if (sn > 0)
304 hwt = (double)nhits / (double)sn;
305 else
306 hwt = 0.5;
307 #ifdef DEBUG
308 sprintf(errmsg, "%d tested, %d untested, %f hit rate\n",
309 sn, ncnts-sn, hwt);
310 eputs(errmsg);
311 #endif
312 /* add in untested sources */
313 for ( ; sn < ncnts; sn++) {
314 sr.rsrc = srccnt[cntord[sn].sndx].sno;
315 prob = hwt * (double)source[sr.rsrc].nhits /
316 (double)source[sr.rsrc].ntests;
317 scalecolor(srccnt[cntord[sn].sndx].val, prob);
318 addcolor(r->rcol, srccnt[cntord[sn].sndx].val);
319 }
320 }