ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.44
Committed: Sun Jun 5 19:52:01 2005 UTC (18 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.43: +2 -2 lines
Log Message:
Changed rtrace to default to Russian roulette ray termination

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rtrace.c,v 2.43 2005/06/02 04:47:27 greg Exp $";
3 #endif
4 /*
5 * rtrace.c - program and variables for individual ray tracing.
6 */
7
8 #include "copyright.h"
9
10 /*
11 * Input is in the form:
12 *
13 * xorg yorg zorg xdir ydir zdir
14 *
15 * The direction need not be normalized. Output is flexible.
16 * If the direction vector is (0,0,0), then the output is flushed.
17 * All values default to ascii representation of real
18 * numbers. Binary representations can be selected
19 * with '-ff' for float or '-fd' for double. By default,
20 * radiance is computed. The '-i' or '-I' options indicate that
21 * irradiance values are desired.
22 */
23
24 #include <time.h>
25
26 #include "platform.h"
27 #include "ray.h"
28 #include "ambient.h"
29 #include "source.h"
30 #include "otypes.h"
31 #include "resolu.h"
32
33 CUBE thescene; /* our scene */
34 OBJECT nsceneobjs; /* number of objects in our scene */
35
36 int dimlist[MAXDIM]; /* sampling dimensions */
37 int ndims = 0; /* number of sampling dimensions */
38 int samplendx = 0; /* index for this sample */
39
40 int imm_irrad = 0; /* compute immediate irradiance? */
41 int lim_dist = 0; /* limit distance? */
42
43 int inform = 'a'; /* input format */
44 int outform = 'a'; /* output format */
45 char *outvals = "v"; /* output specification */
46
47 int do_irrad = 0; /* compute irradiance? */
48
49 void (*trace)() = NULL; /* trace call */
50
51 char *tralist[128]; /* list of modifers to trace (or no) */
52 int traincl = -1; /* include == 1, exclude == 0 */
53 #define MAXTSET 511 /* maximum number in trace set */
54 OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */
55
56 int hresolu = 0; /* horizontal (scan) size */
57 int vresolu = 0; /* vertical resolution */
58
59 double dstrsrc = 0.0; /* square source distribution */
60 double shadthresh = .03; /* shadow threshold */
61 double shadcert = .75; /* shadow certainty */
62 int directrelay = 2; /* number of source relays */
63 int vspretest = 512; /* virtual source pretest density */
64 int directvis = 1; /* sources visible? */
65 double srcsizerat = .2; /* maximum ratio source size/dist. */
66
67 COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
68 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
69 double seccg = 0.; /* global scattering eccentricity */
70 double ssampdist = 0.; /* scatter sampling distance */
71
72 double specthresh = .15; /* specular sampling threshold */
73 double specjitter = 1.; /* specular sampling jitter */
74
75 int backvis = 1; /* back face visibility */
76
77 int maxdepth = -10; /* maximum recursion depth */
78 double minweight = 2e-3; /* minimum ray weight */
79
80 char *ambfile = NULL; /* ambient file name */
81 COLOR ambval = BLKCOLOR; /* ambient value */
82 int ambvwt = 0; /* initial weight for ambient value */
83 double ambacc = 0.15; /* ambient accuracy */
84 int ambres = 256; /* ambient resolution */
85 int ambdiv = 1024; /* ambient divisions */
86 int ambssamp = 512; /* ambient super-samples */
87 int ambounce = 0; /* ambient bounces */
88 char *amblist[AMBLLEN]; /* ambient include/exclude list */
89 int ambincl = -1; /* include == 1, exclude == 0 */
90
91 static int castonly = 0;
92
93 static RAY thisray; /* for our convenience */
94
95 typedef void putf_t(double v);
96 static putf_t puta, putd, putf;
97
98 typedef void oputf_t(RAY *r);
99 static oputf_t oputo, oputd, oputv, oputl, oputL, oputc, oputp,
100 oputn, oputN, oputs, oputw, oputW, oputm, oputM, oputtilde;
101
102 static void setoutput(char *vs);
103 static void tranotify(OBJECT obj);
104 static void bogusray(void);
105 static void rad(FVECT org, FVECT dir, double dmax);
106 static void irrad(FVECT org, FVECT dir);
107 static void printvals(RAY *r);
108 static int getvec(FVECT vec, int fmt, FILE *fp);
109 static void tabin(RAY *r);
110 static void ourtrace(RAY *r);
111
112 static oputf_t *ray_out[16], *every_out[16];
113 static putf_t *putreal;
114
115 void (*addobjnotify[])() = {ambnotify, tranotify, NULL};
116
117
118 void
119 quit( /* quit program */
120 int code
121 )
122 {
123 #ifndef NON_POSIX /* XXX we don't clean up elsewhere? */
124 headclean(); /* delete header file */
125 pfclean(); /* clean up persist files */
126 #endif
127 exit(code);
128 }
129
130
131 extern char *
132 formstr( /* return format identifier */
133 int f
134 )
135 {
136 switch (f) {
137 case 'a': return("ascii");
138 case 'f': return("float");
139 case 'd': return("double");
140 case 'c': return(COLRFMT);
141 }
142 return("unknown");
143 }
144
145
146 extern void
147 rtrace( /* trace rays from file */
148 char *fname
149 )
150 {
151 long vcount = hresolu>1 ? hresolu*vresolu : vresolu;
152 long nextflush = hresolu;
153 FILE *fp;
154 double d;
155 FVECT orig, direc;
156 /* set up input */
157 if (fname == NULL)
158 fp = stdin;
159 else if ((fp = fopen(fname, "r")) == NULL) {
160 sprintf(errmsg, "cannot open input file \"%s\"", fname);
161 error(SYSTEM, errmsg);
162 }
163 if (inform != 'a')
164 SET_FILE_BINARY(fp);
165 /* set up output */
166 setoutput(outvals);
167 switch (outform) {
168 case 'a': putreal = puta; break;
169 case 'f': putreal = putf; break;
170 case 'd': putreal = putd; break;
171 case 'c':
172 if (strcmp(outvals, "v"))
173 error(USER, "color format with value output only");
174 break;
175 default:
176 error(CONSISTENCY, "botched output format");
177 }
178 if (hresolu > 0) {
179 if (vresolu > 0)
180 fprtresolu(hresolu, vresolu, stdout);
181 fflush(stdout);
182 }
183 /* process file */
184 while (getvec(orig, inform, fp) == 0 &&
185 getvec(direc, inform, fp) == 0) {
186
187 d = normalize(direc);
188 if (d == 0.0) { /* zero ==> flush */
189 bogusray();
190 if (--nextflush <= 0 || vcount <= 0) {
191 fflush(stdout);
192 nextflush = hresolu;
193 }
194 } else {
195 samplendx++;
196 /* compute and print */
197 if (imm_irrad)
198 irrad(orig, direc);
199 else
200 rad(orig, direc, lim_dist ? d : 0.0);
201 /* flush if time */
202 if (--nextflush == 0) {
203 fflush(stdout);
204 nextflush = hresolu;
205 }
206 }
207 if (ferror(stdout))
208 error(SYSTEM, "write error");
209 if (--vcount == 0) /* check for end */
210 break;
211 }
212 fflush(stdout);
213 if (vcount > 0)
214 error(USER, "unexpected EOF on input");
215 if (fname != NULL)
216 fclose(fp);
217 }
218
219
220 static void
221 trace_sources(void) /* trace rays to light sources, also */
222 {
223 int sn;
224
225 for (sn = 0; sn < nsources; sn++)
226 source[sn].sflags |= SFOLLOW;
227 }
228
229
230 static void
231 setoutput( /* set up output tables */
232 register char *vs
233 )
234 {
235 register oputf_t **table = ray_out;
236
237 castonly = 1;
238 while (*vs)
239 switch (*vs++) {
240 case 'T': /* trace sources */
241 if (!*vs) break;
242 trace_sources();
243 /* fall through */
244 case 't': /* trace */
245 if (!*vs) break;
246 *table = NULL;
247 table = every_out;
248 trace = ourtrace;
249 castonly = 0;
250 break;
251 case 'o': /* origin */
252 *table++ = oputo;
253 break;
254 case 'd': /* direction */
255 *table++ = oputd;
256 break;
257 case 'v': /* value */
258 *table++ = oputv;
259 castonly = 0;
260 break;
261 case 'l': /* effective distance */
262 *table++ = oputl;
263 castonly = 0;
264 break;
265 case 'c': /* local coordinates */
266 *table++ = oputc;
267 break;
268 case 'L': /* single ray length */
269 *table++ = oputL;
270 break;
271 case 'p': /* point */
272 *table++ = oputp;
273 break;
274 case 'n': /* perturbed normal */
275 *table++ = oputn;
276 castonly = 0;
277 break;
278 case 'N': /* unperturbed normal */
279 *table++ = oputN;
280 break;
281 case 's': /* surface */
282 *table++ = oputs;
283 break;
284 case 'w': /* weight */
285 *table++ = oputw;
286 break;
287 case 'W': /* coefficient */
288 *table++ = oputW;
289 if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
290 error(WARNING,
291 "-otW accuracy depends on -aa 0 -as 0");
292 break;
293 case 'm': /* modifier */
294 *table++ = oputm;
295 break;
296 case 'M': /* material */
297 *table++ = oputM;
298 break;
299 case '~': /* tilde */
300 *table++ = oputtilde;
301 break;
302 }
303 *table = NULL;
304 }
305
306
307 static void
308 bogusray(void) /* print out empty record */
309 {
310 thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
311 thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
312 thisray.rmax = 0.0;
313 rayorigin(&thisray, PRIMARY, NULL, NULL);
314 printvals(&thisray);
315 }
316
317
318 static void
319 rad( /* compute and print ray value(s) */
320 FVECT org,
321 FVECT dir,
322 double dmax
323 )
324 {
325 VCOPY(thisray.rorg, org);
326 VCOPY(thisray.rdir, dir);
327 thisray.rmax = dmax;
328 rayorigin(&thisray, PRIMARY, NULL, NULL);
329 if (castonly) {
330 if (!localhit(&thisray, &thescene)) {
331 if (thisray.ro == &Aftplane) { /* clipped */
332 thisray.ro = NULL;
333 thisray.rot = FHUGE;
334 } else
335 sourcehit(&thisray);
336 }
337 } else
338 rayvalue(&thisray);
339 printvals(&thisray);
340 }
341
342
343 static void
344 irrad( /* compute immediate irradiance value */
345 FVECT org,
346 FVECT dir
347 )
348 {
349 register int i;
350
351 for (i = 0; i < 3; i++) {
352 thisray.rorg[i] = org[i] + dir[i];
353 thisray.rdir[i] = -dir[i];
354 }
355 thisray.rmax = 0.0;
356 rayorigin(&thisray, PRIMARY, NULL, NULL);
357 /* pretend we hit surface */
358 thisray.rot = 1.0-1e-4;
359 thisray.rod = 1.0;
360 VCOPY(thisray.ron, dir);
361 for (i = 0; i < 3; i++) /* fudge factor */
362 thisray.rop[i] = org[i] + 1e-4*dir[i];
363 /* compute and print */
364 (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
365 printvals(&thisray);
366 }
367
368
369 static void
370 printvals( /* print requested ray values */
371 RAY *r
372 )
373 {
374 register oputf_t **tp;
375
376 if (ray_out[0] == NULL)
377 return;
378 for (tp = ray_out; *tp != NULL; tp++)
379 (**tp)(r);
380 if (outform == 'a')
381 putchar('\n');
382 }
383
384
385 static int
386 getvec( /* get a vector from fp */
387 register FVECT vec,
388 int fmt,
389 FILE *fp
390 )
391 {
392 static float vf[3];
393 static double vd[3];
394 char buf[32];
395 register int i;
396
397 switch (fmt) {
398 case 'a': /* ascii */
399 for (i = 0; i < 3; i++) {
400 if (fgetword(buf, sizeof(buf), fp) == NULL ||
401 !isflt(buf))
402 return(-1);
403 vec[i] = atof(buf);
404 }
405 break;
406 case 'f': /* binary float */
407 if (fread((char *)vf, sizeof(float), 3, fp) != 3)
408 return(-1);
409 vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
410 break;
411 case 'd': /* binary double */
412 if (fread((char *)vd, sizeof(double), 3, fp) != 3)
413 return(-1);
414 vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
415 break;
416 default:
417 error(CONSISTENCY, "botched input format");
418 }
419 return(0);
420 }
421
422
423 static void
424 tranotify( /* record new modifier */
425 OBJECT obj
426 )
427 {
428 static int hitlimit = 0;
429 register OBJREC *o = objptr(obj);
430 register char **tralp;
431
432 if (obj == OVOID) { /* starting over */
433 traset[0] = 0;
434 hitlimit = 0;
435 return;
436 }
437 if (hitlimit || !ismodifier(o->otype))
438 return;
439 for (tralp = tralist; *tralp != NULL; tralp++)
440 if (!strcmp(o->oname, *tralp)) {
441 if (traset[0] >= MAXTSET) {
442 error(WARNING, "too many modifiers in trace list");
443 hitlimit++;
444 return; /* should this be fatal? */
445 }
446 insertelem(traset, obj);
447 return;
448 }
449 }
450
451
452 static void
453 ourtrace( /* print ray values */
454 RAY *r
455 )
456 {
457 register oputf_t **tp;
458
459 if (every_out[0] == NULL)
460 return;
461 if (r->ro == NULL) {
462 if (traincl == 1)
463 return;
464 } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
465 return;
466 tabin(r);
467 for (tp = every_out; *tp != NULL; tp++)
468 (**tp)(r);
469 if (outform == 'a')
470 putchar('\n');
471 }
472
473
474 static void
475 tabin( /* tab in appropriate amount */
476 RAY *r
477 )
478 {
479 const RAY *rp;
480
481 for (rp = r->parent; rp != NULL; rp = rp->parent)
482 putchar('\t');
483 }
484
485
486 static void
487 oputo( /* print origin */
488 RAY *r
489 )
490 {
491 (*putreal)(r->rorg[0]);
492 (*putreal)(r->rorg[1]);
493 (*putreal)(r->rorg[2]);
494 }
495
496
497 static void
498 oputd( /* print direction */
499 RAY *r
500 )
501 {
502 (*putreal)(r->rdir[0]);
503 (*putreal)(r->rdir[1]);
504 (*putreal)(r->rdir[2]);
505 }
506
507
508 static void
509 oputv( /* print value */
510 RAY *r
511 )
512 {
513 if (outform == 'c') {
514 COLR cout;
515 setcolr(cout, colval(r->rcol,RED),
516 colval(r->rcol,GRN),
517 colval(r->rcol,BLU));
518 fwrite((char *)cout, sizeof(cout), 1, stdout);
519 return;
520 }
521 (*putreal)(colval(r->rcol,RED));
522 (*putreal)(colval(r->rcol,GRN));
523 (*putreal)(colval(r->rcol,BLU));
524 }
525
526
527 static void
528 oputl( /* print effective distance */
529 RAY *r
530 )
531 {
532 (*putreal)(r->rt);
533 }
534
535
536 static void
537 oputL( /* print single ray length */
538 RAY *r
539 )
540 {
541 (*putreal)(r->rot);
542 }
543
544
545 static void
546 oputc( /* print local coordinates */
547 RAY *r
548 )
549 {
550 (*putreal)(r->uv[0]);
551 (*putreal)(r->uv[1]);
552 }
553
554
555 static void
556 oputp( /* print point */
557 RAY *r
558 )
559 {
560 if (r->rot < FHUGE) {
561 (*putreal)(r->rop[0]);
562 (*putreal)(r->rop[1]);
563 (*putreal)(r->rop[2]);
564 } else {
565 (*putreal)(0.0);
566 (*putreal)(0.0);
567 (*putreal)(0.0);
568 }
569 }
570
571
572 static void
573 oputN( /* print unperturbed normal */
574 RAY *r
575 )
576 {
577 if (r->rot < FHUGE) {
578 (*putreal)(r->ron[0]);
579 (*putreal)(r->ron[1]);
580 (*putreal)(r->ron[2]);
581 } else {
582 (*putreal)(0.0);
583 (*putreal)(0.0);
584 (*putreal)(0.0);
585 }
586 }
587
588
589 static void
590 oputn( /* print perturbed normal */
591 RAY *r
592 )
593 {
594 FVECT pnorm;
595
596 if (r->rot >= FHUGE) {
597 (*putreal)(0.0);
598 (*putreal)(0.0);
599 (*putreal)(0.0);
600 return;
601 }
602 raynormal(pnorm, r);
603 (*putreal)(pnorm[0]);
604 (*putreal)(pnorm[1]);
605 (*putreal)(pnorm[2]);
606 }
607
608
609 static void
610 oputs( /* print name */
611 RAY *r
612 )
613 {
614 if (r->ro != NULL)
615 fputs(r->ro->oname, stdout);
616 else
617 putchar('*');
618 putchar('\t');
619 }
620
621
622 static void
623 oputw( /* print weight */
624 RAY *r
625 )
626 {
627 (*putreal)(r->rweight);
628 }
629
630
631 static void
632 oputW( /* print contribution */
633 RAY *r
634 )
635 {
636 COLOR contr;
637
638 raycontrib(contr, r, PRIMARY);
639 (*putreal)(colval(contr,RED));
640 (*putreal)(colval(contr,GRN));
641 (*putreal)(colval(contr,BLU));
642 }
643
644
645 static void
646 oputm( /* print modifier */
647 RAY *r
648 )
649 {
650 if (r->ro != NULL)
651 if (r->ro->omod != OVOID)
652 fputs(objptr(r->ro->omod)->oname, stdout);
653 else
654 fputs(VOIDID, stdout);
655 else
656 putchar('*');
657 putchar('\t');
658 }
659
660
661 static void
662 oputM( /* print material */
663 RAY *r
664 )
665 {
666 OBJREC *mat;
667
668 if (r->ro != NULL) {
669 if ((mat = findmaterial(r->ro)) != NULL)
670 fputs(mat->oname, stdout);
671 else
672 fputs(VOIDID, stdout);
673 } else
674 putchar('*');
675 putchar('\t');
676 }
677
678
679 static void
680 oputtilde( /* output tilde (spacer) */
681 RAY *r
682 )
683 {
684 fputs("~\t", stdout);
685 }
686
687
688 static void
689 puta( /* print ascii value */
690 double v
691 )
692 {
693 printf("%e\t", v);
694 }
695
696
697 static void
698 putd(v) /* print binary double */
699 double v;
700 {
701 fwrite((char *)&v, sizeof(v), 1, stdout);
702 }
703
704
705 static void
706 putf(v) /* print binary float */
707 double v;
708 {
709 float f = v;
710
711 fwrite((char *)&f, sizeof(f), 1, stdout);
712 }