ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/raytrace.c
Revision: 1.3
Committed: Wed Apr 19 22:24:28 1989 UTC (35 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +0 -2 lines
Log Message:
moved setting of ray transformation to intersection routines (bug)

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 * raytrace.c - routines for tracing and shading rays.
9 *
10 * 8/7/85
11 */
12
13 #include "ray.h"
14
15 #include "octree.h"
16
17 #include "otypes.h"
18
19 extern CUBE thescene; /* our scene */
20 extern int maxdepth; /* maximum recursion depth */
21 extern double minweight; /* minimum ray weight */
22
23 long nrays = 0L; /* number of rays traced */
24
25 #define MAXLOOP 32 /* modifier loop detection */
26
27 #define RAYHIT (-1) /* return value for intercepted ray */
28
29
30 rayorigin(r, ro, rt, rw) /* start new ray from old one */
31 register RAY *r, *ro;
32 int rt;
33 double rw;
34 {
35 if ((r->parent = ro) == NULL) { /* primary ray */
36 r->rlvl = 0;
37 r->rweight = rw;
38 r->crtype = r->rtype = rt;
39 r->rsrc = -1;
40 r->clipset = NULL;
41 } else { /* spawned ray */
42 r->rlvl = ro->rlvl;
43 if (rt & RAYREFL) {
44 r->rlvl++;
45 r->rsrc = -1;
46 r->clipset = ro->clipset;
47 } else {
48 r->rsrc = ro->rsrc;
49 r->clipset = ro->newcset;
50 }
51 r->rweight = ro->rweight * rw;
52 r->crtype = ro->crtype | (r->rtype = rt);
53 VCOPY(r->rorg, ro->rop);
54 }
55 r->rno = nrays;
56 r->newcset = r->clipset;
57 r->ro = NULL;
58 r->rot = FHUGE;
59 r->pert[0] = r->pert[1] = r->pert[2] = 0.0;
60 setcolor(r->pcol, 1.0, 1.0, 1.0);
61 setcolor(r->rcol, 0.0, 0.0, 0.0);
62 return(r->rlvl <= maxdepth && r->rweight >= minweight ? 0 : -1);
63 }
64
65
66 rayvalue(r) /* compute a ray's value */
67 register RAY *r;
68 {
69 extern int (*trace)();
70
71 if (localhit(r, &thescene))
72 if (r->clipset != NULL && inset(r->clipset, r->ro->omod))
73 raytrans(r); /* object is clipped */
74 else
75 rayshade(r, r->ro->omod);
76 else if (sourcehit(r))
77 rayshade(r, r->ro->omod);
78
79 if (trace != NULL)
80 (*trace)(r); /* trace execution */
81 }
82
83
84 raytrans(r) /* transmit ray as is */
85 RAY *r;
86 {
87 RAY tr;
88
89 if (rayorigin(&tr, r, TRANS, 1.0) == 0) {
90 VCOPY(tr.rdir, r->rdir);
91 rayvalue(&tr);
92 copycolor(r->rcol, tr.rcol);
93 }
94 }
95
96
97 rayshade(r, mod) /* shade ray r with material mod */
98 register RAY *r;
99 int mod;
100 {
101 static int depth = 0;
102 register OBJREC *m;
103 /* check for infinite loop */
104 if (depth++ >= MAXLOOP)
105 objerror(r->ro, USER, "material loop");
106 for ( ; mod != OVOID; mod = m->omod) {
107 m = objptr(mod);
108 if (!ismodifier(m->otype)) {
109 sprintf(errmsg, "illegal modifier \"%s\"", m->oname);
110 error(USER, errmsg);
111 }
112 (*ofun[m->otype].funp)(m, r); /* execute function */
113 m->lastrno = r->rno;
114 if (ismaterial(m->otype)) { /* materials call raytexture */
115 depth--;
116 return; /* we're done */
117 }
118 }
119 objerror(r->ro, USER, "material not found");
120 }
121
122
123 raytexture(r, mod) /* get material modifiers */
124 RAY *r;
125 int mod;
126 {
127 static int depth = 0;
128 register OBJREC *m;
129 /* check for infinite loop */
130 if (depth++ >= MAXLOOP)
131 objerror(r->ro, USER, "modifier loop");
132 /* execute textures and patterns */
133 for ( ; mod != OVOID; mod = m->omod) {
134 m = objptr(mod);
135 if (!istexture(m->otype)) {
136 sprintf(errmsg, "illegal modifier \"%s\"", m->oname);
137 error(USER, errmsg);
138 }
139 (*ofun[m->otype].funp)(m, r);
140 m->lastrno = r->rno;
141 }
142 depth--; /* end here */
143 }
144
145
146 raymixture(r, fore, back, coef) /* mix modifiers */
147 register RAY *r;
148 OBJECT fore, back;
149 double coef;
150 {
151 FVECT curpert, forepert, backpert;
152 COLOR curpcol, forepcol, backpcol;
153 register int i;
154 /* clip coefficient */
155 if (coef > 1.0)
156 coef = 1.0;
157 else if (coef < 0.0)
158 coef = 0.0;
159 /* save current mods */
160 VCOPY(curpert, r->pert);
161 copycolor(curpcol, r->pcol);
162 /* compute new mods */
163 /* foreground */
164 r->pert[0] = r->pert[1] = r->pert[2] = 0.0;
165 setcolor(r->pcol, 1.0, 1.0, 1.0);
166 if (fore != OVOID && coef > FTINY)
167 raytexture(r, fore);
168 VCOPY(forepert, r->pert);
169 copycolor(forepcol, r->pcol);
170 /* background */
171 r->pert[0] = r->pert[1] = r->pert[2] = 0.0;
172 setcolor(r->pcol, 1.0, 1.0, 1.0);
173 if (back != OVOID && coef < 1.0-FTINY)
174 raytexture(r, back);
175 VCOPY(backpert, r->pert);
176 copycolor(backpcol, r->pcol);
177 /* sum perturbations */
178 for (i = 0; i < 3; i++)
179 r->pert[i] = curpert[i] + coef*forepert[i] +
180 (1.0-coef)*backpert[i];
181 /* multiply colors */
182 setcolor(r->pcol, coef*colval(forepcol,RED) +
183 (1.0-coef)*colval(backpcol,RED),
184 coef*colval(forepcol,GRN) +
185 (1.0-coef)*colval(backpcol,GRN),
186 coef*colval(forepcol,BLU) +
187 (1.0-coef)*colval(backpcol,BLU));
188 multcolor(r->pcol, curpcol);
189 }
190
191
192 double
193 raynormal(norm, r) /* compute perturbed normal for ray */
194 FVECT norm;
195 register RAY *r;
196 {
197 double newdot;
198 register int i;
199
200 /* The perturbation is added to the surface normal to obtain
201 * the new normal. If the new normal would affect the surface
202 * orientation wrt. the ray, a correction is made. The method is
203 * still fraught with problems since reflected rays and similar
204 * directions calculated from the surface normal may spawn rays behind
205 * the surface. The only solution is to curb textures at high
206 * incidence (Rdot << 1).
207 */
208
209 for (i = 0; i < 3; i++)
210 norm[i] = r->ron[i] + r->pert[i];
211
212 if (normalize(norm) == 0.0) {
213 objerror(r->ro, WARNING, "illegal normal perturbation");
214 VCOPY(norm, r->ron);
215 return(r->rod);
216 }
217 newdot = -DOT(norm, r->rdir);
218 if ((newdot > 0.0) != (r->rod > 0.0)) { /* fix orientation */
219 for (i = 0; i < 3; i++)
220 norm[i] += 2.0*newdot*r->rdir[i];
221 newdot = -newdot;
222 }
223 return(newdot);
224 }
225
226
227 flipsurface(r) /* reverse surface orientation */
228 register RAY *r;
229 {
230 r->rod = -r->rod;
231 r->ron[0] = -r->ron[0];
232 r->ron[1] = -r->ron[1];
233 r->ron[2] = -r->ron[2];
234 r->pert[0] = -r->pert[0];
235 r->pert[1] = -r->pert[1];
236 r->pert[2] = -r->pert[2];
237 }
238
239
240 localhit(r, scene) /* check for hit in the octree */
241 register RAY *r;
242 register CUBE *scene;
243 {
244 FVECT curpos; /* current cube position */
245 int mpos, mneg; /* sign flags */
246 double t, dt;
247 register int i;
248
249 nrays++; /* increment trace counter */
250
251 mpos = mneg = 0;
252 for (i = 0; i < 3; i++) {
253 curpos[i] = r->rorg[i];
254 if (r->rdir[i] > FTINY)
255 mpos |= 1 << i;
256 else if (r->rdir[i] < -FTINY)
257 mneg |= 1 << i;
258 }
259 t = 0.0;
260 if (!incube(scene, curpos)) {
261 /* find distance to entry */
262 for (i = 0; i < 3; i++) {
263 /* plane in our direction */
264 if (mpos & 1<<i)
265 dt = scene->cuorg[i];
266 else if (mneg & 1<<i)
267 dt = scene->cuorg[i] + scene->cusize;
268 else
269 continue;
270 /* distance to the plane */
271 dt = (dt - r->rorg[i])/r->rdir[i];
272 if (dt > t)
273 t = dt; /* farthest face is the one */
274 }
275 t += FTINY; /* fudge to get inside cube */
276 /* advance position */
277 for (i = 0; i < 3; i++)
278 curpos[i] += r->rdir[i]*t;
279
280 if (!incube(scene, curpos)) /* non-intersecting ray */
281 return(0);
282 }
283 return(raymove(curpos, mpos, mneg, r, scene) == RAYHIT);
284 }
285
286
287 static int
288 raymove(pos, plus, minus, r, cu) /* check for hit as we move */
289 FVECT pos; /* modified */
290 int plus, minus; /* direction indicators to speed tests */
291 register RAY *r;
292 register CUBE *cu;
293 {
294 int ax;
295 double dt, t;
296 register int sgn;
297
298 if (istree(cu->cutree)) { /* recurse on subcubes */
299 CUBE cukid;
300 register int br;
301
302 cukid.cusize = cu->cusize * 0.5; /* find subcube */
303 VCOPY(cukid.cuorg, cu->cuorg);
304 br = 0;
305 if (pos[0] >= cukid.cuorg[0]+cukid.cusize) {
306 cukid.cuorg[0] += cukid.cusize;
307 br |= 1;
308 }
309 if (pos[1] >= cukid.cuorg[1]+cukid.cusize) {
310 cukid.cuorg[1] += cukid.cusize;
311 br |= 2;
312 }
313 if (pos[2] >= cukid.cuorg[2]+cukid.cusize) {
314 cukid.cuorg[2] += cukid.cusize;
315 br |= 4;
316 }
317 for ( ; ; ) {
318 cukid.cutree = octkid(cu->cutree, br);
319 if ((ax = raymove(pos,plus,minus,r,&cukid)) == RAYHIT)
320 return(RAYHIT);
321 sgn = 1 << ax;
322 if (sgn & minus) /* negative axis? */
323 if (sgn & br) {
324 cukid.cuorg[ax] -= cukid.cusize;
325 br &= ~sgn;
326 } else
327 return(ax); /* underflow */
328 else
329 if (sgn & br)
330 return(ax); /* overflow */
331 else {
332 cukid.cuorg[ax] += cukid.cusize;
333 br |= sgn;
334 }
335 }
336 /*NOTREACHED*/
337 }
338 if (isfull(cu->cutree) && checkhit(r, cu))
339 return(RAYHIT);
340 /* advance to next cube */
341 sgn = plus | minus;
342 if (sgn&1) {
343 dt = plus&1 ? cu->cuorg[0] + cu->cusize : cu->cuorg[0];
344 t = (dt - pos[0])/r->rdir[0];
345 ax = 0;
346 } else
347 t = FHUGE;
348 if (sgn&2) {
349 dt = plus&2 ? cu->cuorg[1] + cu->cusize : cu->cuorg[1];
350 dt = (dt - pos[1])/r->rdir[1];
351 if (dt < t) {
352 t = dt;
353 ax = 1;
354 }
355 }
356 if (sgn&4) {
357 dt = plus&4 ? cu->cuorg[2] + cu->cusize : cu->cuorg[2];
358 dt = (dt - pos[2])/r->rdir[2];
359 if (dt < t) {
360 t = dt;
361 ax = 2;
362 }
363 }
364 pos[0] += r->rdir[0]*t;
365 pos[1] += r->rdir[1]*t;
366 pos[2] += r->rdir[2]*t;
367 return(ax);
368 }
369
370
371 static
372 checkhit(r, cu) /* check for hit in full cube */
373 register RAY *r;
374 CUBE *cu;
375 {
376 OBJECT oset[MAXSET+1];
377 register OBJREC *o;
378 register int i;
379
380 objset(oset, cu->cutree);
381 for (i = oset[0]; i > 0; i--) {
382 o = objptr(oset[i]);
383 if (o->lastrno == r->rno) /* checked already? */
384 continue;
385 (*ofun[o->otype].funp)(o, r);
386 o->lastrno = r->rno;
387 }
388 if (r->ro == NULL)
389 return(0); /* no scores yet */
390
391 return(incube(cu, r->rop)); /* hit OK if in current cube */
392 }