ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/source.c
Revision: 1.1
Committed: Thu Feb 2 10:41:41 1989 UTC (35 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1986 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 "source.h"
16    
17     #include "otypes.h"
18    
19     #include "cone.h"
20    
21     #include "face.h"
22    
23     #include "random.h"
24    
25    
26     extern double dstrsrc; /* source distribution amount */
27    
28     SOURCE srcval[MAXSOURCE]; /* our array of sources */
29     int nsources = 0; /* the number of sources */
30    
31    
32     marksources() /* find and mark source objects */
33     {
34     register OBJREC *o, *m;
35     register int i;
36    
37     for (i = 0; i < nobjects; i++) {
38    
39     o = objptr(i);
40    
41     if (o->omod == OVOID)
42     continue;
43    
44     m = objptr(o->omod);
45    
46     if (m->otype != MAT_LIGHT &&
47     m->otype != MAT_ILLUM &&
48     m->otype != MAT_GLOW &&
49     m->otype != MAT_SPOT)
50     continue;
51    
52     if (m->oargs.nfargs != (m->otype == MAT_GLOW ? 4 :
53     m->otype == MAT_SPOT ? 7 : 3))
54     objerror(m, USER, "bad # arguments");
55    
56     if (m->otype == MAT_GLOW &&
57     o->otype != OBJ_SOURCE &&
58     m->oargs.farg[3] <= FTINY)
59     continue; /* don't bother */
60    
61     if (nsources >= MAXSOURCE)
62     error(INTERNAL, "too many sources in marksources");
63    
64     newsource(&srcval[nsources], o);
65    
66     if (m->otype == MAT_GLOW) {
67     srcval[nsources].sflags |= SPROX;
68     srcval[nsources].sl.prox = m->oargs.farg[3];
69     if (o->otype == OBJ_SOURCE)
70     srcval[nsources].sflags |= SSKIP;
71     } else if (m->otype == MAT_SPOT) {
72     srcval[nsources].sflags |= SSPOT;
73     srcval[nsources].sl.s = makespot(m);
74     }
75     nsources++;
76     }
77     }
78    
79    
80     newsource(src, so) /* add a source to the array */
81     register SOURCE *src;
82     register OBJREC *so;
83     {
84     double cos(), tan(), sqrt();
85     double theta;
86     FACE *f;
87     CONE *co;
88     int j;
89     register int i;
90    
91     src->sflags = 0;
92     src->so = so;
93    
94     switch (so->otype) {
95     case OBJ_SOURCE:
96     if (so->oargs.nfargs != 4)
97     objerror(so, USER, "bad arguments");
98     src->sflags |= SDISTANT;
99     VCOPY(src->sloc, so->oargs.farg);
100     if (normalize(src->sloc) == 0.0)
101     objerror(so, USER, "zero direction");
102     theta = PI/180.0/2.0 * so->oargs.farg[3];
103     if (theta <= FTINY)
104     objerror(so, USER, "zero size");
105     src->ss = theta >= PI/4 ? 1.0 : tan(theta);
106     src->ss2 = 2.0*PI * (1.0 - cos(theta));
107     break;
108     case OBJ_SPHERE:
109     VCOPY(src->sloc, so->oargs.farg);
110     src->ss = so->oargs.farg[3];
111     src->ss2 = PI * src->ss * src->ss;
112     break;
113     case OBJ_FACE:
114     /* get the face */
115     f = getface(so);
116     /* find the center */
117     for (j = 0; j < 3; j++) {
118     src->sloc[j] = 0.0;
119     for (i = 0; i < f->nv; i++)
120     src->sloc[j] += VERTEX(f,i)[j];
121     src->sloc[j] /= f->nv;
122     }
123     if (!inface(src->sloc, f))
124     objerror(so, USER, "cannot hit center");
125     src->ss = sqrt(f->area / PI);
126     src->ss2 = f->area;
127     break;
128     case OBJ_RING:
129     /* get the ring */
130     co = getcone(so, 0);
131     VCOPY(src->sloc, CO_P0(co));
132     if (CO_R0(co) > 0.0)
133     objerror(so, USER, "cannot hit center");
134     src->ss = CO_R1(co);
135     src->ss2 = PI * src->ss * src->ss;
136     break;
137     default:
138     objerror(so, USER, "illegal material");
139     }
140     }
141    
142    
143     SPOT *
144     makespot(m) /* make a spotlight */
145     register OBJREC *m;
146     {
147     extern double cos();
148     register SPOT *ns;
149    
150     if ((ns = (SPOT *)malloc(sizeof(SPOT))) == NULL)
151     error(SYSTEM, "out of memory in makespot");
152     ns->siz = 2.0*PI * (1.0 - cos(PI/180.0/2.0 * m->oargs.farg[3]));
153     VCOPY(ns->aim, m->oargs.farg+4);
154     if ((ns->flen = normalize(ns->aim)) == 0.0)
155     objerror(m, USER, "zero focus vector");
156     return(ns);
157     }
158    
159    
160     double
161     srcray(sr, r, sn) /* send a ray to a source, return domega */
162     register RAY *sr; /* returned source ray */
163     RAY *r; /* ray which hit object */
164     register int sn; /* source number */
165     {
166     register double *norm = NULL; /* plane normal */
167     double ddot; /* (distance times) cosine */
168     FVECT vd;
169     double d;
170     register int i;
171    
172     if (srcval[sn].sflags & SSKIP)
173     return(0.0); /* skip this source */
174    
175     rayorigin(sr, r, SHADOW, 1.0); /* ignore limits */
176    
177     sr->rsrc = sn; /* remember source */
178     /* get source direction */
179     if (srcval[sn].sflags & SDISTANT)
180     /* constant direction */
181     VCOPY(sr->rdir, srcval[sn].sloc);
182     else { /* compute direction */
183     for (i = 0; i < 3; i++)
184     sr->rdir[i] = srcval[sn].sloc[i] - sr->rorg[i];
185    
186     if (srcval[sn].so->otype == OBJ_FACE)
187     norm = getface(srcval[sn].so)->norm;
188     else if (srcval[sn].so->otype == OBJ_RING)
189     norm = getcone(srcval[sn].so,0)->ad;
190    
191     if (norm != NULL && (ddot = -DOT(sr->rdir, norm)) <= 0.0)
192     return(0.0); /* behind surface! */
193     }
194     if (dstrsrc > FTINY) {
195     /* distribute source direction */
196     for (i = 0; i < 3; i++)
197     vd[i] = dstrsrc * srcval[sn].ss * (1.0 - 2.0*frandom());
198    
199     if (norm != NULL) { /* project offset */
200     d = DOT(vd, norm);
201     for (i = 0; i < 3; i++)
202     vd[i] -= d * norm[i];
203     }
204     for (i = 0; i < 3; i++) /* offset source direction */
205     sr->rdir[i] += vd[i];
206    
207     } else if (srcval[sn].sflags & SDISTANT)
208     /* already normalized */
209     return(srcval[sn].ss2);
210    
211     if ((d = normalize(sr->rdir)) == 0.0)
212     /* at source! */
213     return(0.0);
214    
215     if (srcval[sn].sflags & SDISTANT)
216     /* domega constant */
217     return(srcval[sn].ss2);
218    
219     else {
220     /* check proximity */
221     if (srcval[sn].sflags & SPROX &&
222     d > srcval[sn].sl.prox)
223     return(0.0);
224    
225     if (norm != NULL)
226     ddot /= d;
227     else
228     ddot = 1.0;
229     /* check angle */
230     if (srcval[sn].sflags & SSPOT) {
231     if (srcval[sn].sl.s->siz < 2.0*PI *
232     (1.0 + DOT(srcval[sn].sl.s->aim,sr->rdir)))
233     return(0.0);
234     d += srcval[sn].sl.s->flen;
235     }
236     /* return domega */
237     return(ddot*srcval[sn].ss2/(d*d));
238     }
239     }
240    
241    
242     sourcehit(r) /* check to see if ray hit distant source */
243     register RAY *r;
244     {
245     int first, last;
246     register int i;
247    
248     if (r->rsrc >= 0) { /* check only one if aimed */
249     first = last = r->rsrc;
250     } else { /* otherwise check all */
251     first = 0; last = nsources-1;
252     }
253     for (i = first; i <= last; i++)
254     if (srcval[i].sflags & SDISTANT)
255     /*
256     * Check to see if ray is within
257     * solid angle of source.
258     */
259     if (2.0*PI * (1.0 - DOT(srcval[i].sloc,r->rdir))
260     <= srcval[i].ss2) {
261     r->ro = srcval[i].so;
262     if (!(srcval[i].sflags & SSKIP))
263     break;
264     }
265    
266     if (r->ro != NULL) {
267     for (i = 0; i < 3; i++)
268     r->ron[i] = -r->rdir[i];
269     r->rod = 1.0;
270     return(1);
271     }
272     return(0);
273     }
274    
275    
276     #define wrongsource(m, r) (m->otype!=MAT_ILLUM && \
277     r->rsrc>=0 && \
278     srcval[r->rsrc].so!=r->ro)
279    
280     #define badambient(m, r) ((r->crtype&(AMBIENT|SHADOW))==AMBIENT && \
281     !(r->rtype&REFLECTED) && /* hack! */\
282     !(m->otype==MAT_GLOW&&r->rot>m->oargs.farg[3]))
283    
284     #define passillum(m, r) (m->otype==MAT_ILLUM && \
285     !(r->rsrc>=0&&srcval[r->rsrc].so==r->ro))
286    
287    
288     m_light(m, r) /* ray hit a light source */
289     register OBJREC *m;
290     register RAY *r;
291     {
292     /* check for behind */
293     if (r->rod < 0.0)
294     return;
295     /* check for over-counting */
296     if (wrongsource(m, r) || badambient(m, r))
297     return;
298     /* check for passed illum */
299     if (passillum(m, r)) {
300    
301     if (m->oargs.nsargs < 1 || !strcmp(m->oargs.sarg[0], VOIDID))
302     raytrans(r);
303     else
304     rayshade(r, modifier(m->oargs.sarg[0]));
305    
306     /* otherwise treat as source */
307     } else {
308     /* get distribution pattern */
309     raytexture(r, m->omod);
310     /* get source color */
311     setcolor(r->rcol, m->oargs.farg[0],
312     m->oargs.farg[1],
313     m->oargs.farg[2]);
314     /* modify value */
315     multcolor(r->rcol, r->pcol);
316     }
317     }
318    
319    
320     o_source() {} /* intersection with a source is done elsewhere */