ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/source.c
Revision: 1.2
Committed: Fri Mar 3 20:58:33 1989 UTC (35 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
changed test in srcray to eliminate coplanar tests

File Contents

# Content
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)) <= FTINY)
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 */