ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.40
Committed: Tue Apr 19 01:15:06 2005 UTC (19 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.39: +50 -7 lines
Log Message:
Extensive changes to enable rtrace -oTW option for tracking ray contributions

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rtrace.c,v 2.39 2005/04/14 18:04:12 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 = 8; /* 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;
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 #ifdef _WIN32
164 if (inform != 'a')
165 SET_FILE_BINARY(fp);
166 #endif
167 /* set up output */
168 setoutput(outvals);
169 switch (outform) {
170 case 'a': putreal = puta; break;
171 case 'f': putreal = putf; break;
172 case 'd': putreal = putd; break;
173 case 'c':
174 if (strcmp(outvals, "v"))
175 error(USER, "color format with value output only");
176 break;
177 default:
178 error(CONSISTENCY, "botched output format");
179 }
180 if (hresolu > 0) {
181 if (vresolu > 0)
182 fprtresolu(hresolu, vresolu, stdout);
183 fflush(stdout);
184 }
185 /* process file */
186 while (getvec(orig, inform, fp) == 0 &&
187 getvec(direc, inform, fp) == 0) {
188
189 d = normalize(direc);
190 if (d == 0.0) { /* zero ==> flush */
191 bogusray();
192 if (--nextflush <= 0 || vcount <= 0) {
193 fflush(stdout);
194 nextflush = hresolu;
195 }
196 } else {
197 samplendx++;
198 /* compute and print */
199 if (imm_irrad)
200 irrad(orig, direc);
201 else
202 rad(orig, direc, lim_dist ? d : 0.0);
203 /* flush if time */
204 if (--nextflush == 0) {
205 fflush(stdout);
206 nextflush = hresolu;
207 }
208 }
209 if (ferror(stdout))
210 error(SYSTEM, "write error");
211 if (--vcount == 0) /* check for end */
212 break;
213 }
214 fflush(stdout);
215 if (vcount > 0)
216 error(USER, "read error");
217 if (fname != NULL)
218 fclose(fp);
219 }
220
221
222 static void
223 trace_sources(void) /* trace rays to light sources, also */
224 {
225 int sn;
226
227 for (sn = 0; sn < nsources; sn++)
228 source[sn].sflags |= SFOLLOW;
229 }
230
231
232 static void
233 setoutput( /* set up output tables */
234 register char *vs
235 )
236 {
237 register oputf_t **table = ray_out;
238
239 castonly = 1;
240 while (*vs)
241 switch (*vs++) {
242 case 'T': /* trace sources */
243 trace_sources();
244 /* fall through */
245 case 't': /* trace */
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 requires -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 }
300 *table = NULL;
301 }
302
303
304 static void
305 bogusray(void) /* print out empty record */
306 {
307 thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
308 thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
309 thisray.rmax = 0.0;
310 rayorigin(&thisray, PRIMARY, NULL, NULL);
311 printvals(&thisray);
312 }
313
314
315 static void
316 rad( /* compute and print ray value(s) */
317 FVECT org,
318 FVECT dir,
319 double dmax
320 )
321 {
322 VCOPY(thisray.rorg, org);
323 VCOPY(thisray.rdir, dir);
324 thisray.rmax = dmax;
325 rayorigin(&thisray, PRIMARY, NULL, NULL);
326 if (castonly) {
327 if (!localhit(&thisray, &thescene)) {
328 if (thisray.ro == &Aftplane) { /* clipped */
329 thisray.ro = NULL;
330 thisray.rot = FHUGE;
331 } else
332 sourcehit(&thisray);
333 }
334 } else
335 rayvalue(&thisray);
336 printvals(&thisray);
337 }
338
339
340 static void
341 irrad( /* compute immediate irradiance value */
342 FVECT org,
343 FVECT dir
344 )
345 {
346 register int i;
347
348 for (i = 0; i < 3; i++) {
349 thisray.rorg[i] = org[i] + dir[i];
350 thisray.rdir[i] = -dir[i];
351 }
352 thisray.rmax = 0.0;
353 rayorigin(&thisray, PRIMARY, NULL, NULL);
354 /* pretend we hit surface */
355 thisray.rot = 1.0-1e-4;
356 thisray.rod = 1.0;
357 VCOPY(thisray.ron, dir);
358 for (i = 0; i < 3; i++) /* fudge factor */
359 thisray.rop[i] = org[i] + 1e-4*dir[i];
360 /* compute and print */
361 (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
362 printvals(&thisray);
363 }
364
365
366 static void
367 printvals( /* print requested ray values */
368 RAY *r
369 )
370 {
371 register oputf_t **tp;
372
373 if (ray_out[0] == NULL)
374 return;
375 for (tp = ray_out; *tp != NULL; tp++)
376 (**tp)(r);
377 if (outform == 'a')
378 putchar('\n');
379 }
380
381
382 static int
383 getvec( /* get a vector from fp */
384 register FVECT vec,
385 int fmt,
386 FILE *fp
387 )
388 {
389 static float vf[3];
390 static double vd[3];
391 char buf[32];
392 register int i;
393
394 switch (fmt) {
395 case 'a': /* ascii */
396 for (i = 0; i < 3; i++) {
397 if (fgetword(buf, sizeof(buf), fp) == NULL ||
398 !isflt(buf))
399 return(-1);
400 vec[i] = atof(buf);
401 }
402 break;
403 case 'f': /* binary float */
404 if (fread((char *)vf, sizeof(float), 3, fp) != 3)
405 return(-1);
406 vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
407 break;
408 case 'd': /* binary double */
409 if (fread((char *)vd, sizeof(double), 3, fp) != 3)
410 return(-1);
411 vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
412 break;
413 default:
414 error(CONSISTENCY, "botched input format");
415 }
416 return(0);
417 }
418
419
420 static void
421 tranotify( /* record new modifier */
422 OBJECT obj
423 )
424 {
425 static int hitlimit = 0;
426 register OBJREC *o = objptr(obj);
427 register char **tralp;
428
429 if (obj == OVOID) { /* starting over */
430 traset[0] = 0;
431 hitlimit = 0;
432 return;
433 }
434 if (hitlimit || !ismodifier(o->otype))
435 return;
436 for (tralp = tralist; *tralp != NULL; tralp++)
437 if (!strcmp(o->oname, *tralp)) {
438 if (traset[0] >= MAXTSET) {
439 error(WARNING, "too many modifiers in trace list");
440 hitlimit++;
441 return; /* should this be fatal? */
442 }
443 insertelem(traset, obj);
444 return;
445 }
446 }
447
448
449 static void
450 ourtrace( /* print ray values */
451 RAY *r
452 )
453 {
454 register oputf_t **tp;
455
456 if (every_out[0] == NULL)
457 return;
458 if (r->ro == NULL) {
459 if (traincl == 1)
460 return;
461 } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
462 return;
463 tabin(r);
464 for (tp = every_out; *tp != NULL; tp++)
465 (**tp)(r);
466 putchar('\n');
467 }
468
469
470 static void
471 tabin( /* tab in appropriate amount */
472 RAY *r
473 )
474 {
475 const RAY *rp;
476
477 for (rp = r->parent; rp != NULL; rp = rp->parent)
478 putchar('\t');
479 }
480
481
482 static void
483 oputo( /* print origin */
484 RAY *r
485 )
486 {
487 (*putreal)(r->rorg[0]);
488 (*putreal)(r->rorg[1]);
489 (*putreal)(r->rorg[2]);
490 }
491
492
493 static void
494 oputd( /* print direction */
495 RAY *r
496 )
497 {
498 (*putreal)(r->rdir[0]);
499 (*putreal)(r->rdir[1]);
500 (*putreal)(r->rdir[2]);
501 }
502
503
504 static void
505 oputv( /* print value */
506 RAY *r
507 )
508 {
509 COLR cout;
510
511 if (outform == 'c') {
512 setcolr(cout, colval(r->rcol,RED),
513 colval(r->rcol,GRN),
514 colval(r->rcol,BLU));
515 fwrite((char *)cout, sizeof(cout), 1, stdout);
516 return;
517 }
518 (*putreal)(colval(r->rcol,RED));
519 (*putreal)(colval(r->rcol,GRN));
520 (*putreal)(colval(r->rcol,BLU));
521 }
522
523
524 static void
525 oputl( /* print effective distance */
526 RAY *r
527 )
528 {
529 (*putreal)(r->rt);
530 }
531
532
533 static void
534 oputL( /* print single ray length */
535 RAY *r
536 )
537 {
538 (*putreal)(r->rot);
539 }
540
541
542 static void
543 oputc( /* print local coordinates */
544 RAY *r
545 )
546 {
547 (*putreal)(r->uv[0]);
548 (*putreal)(r->uv[1]);
549 }
550
551
552 static void
553 oputp( /* print point */
554 RAY *r
555 )
556 {
557 if (r->rot < FHUGE) {
558 (*putreal)(r->rop[0]);
559 (*putreal)(r->rop[1]);
560 (*putreal)(r->rop[2]);
561 } else {
562 (*putreal)(0.0);
563 (*putreal)(0.0);
564 (*putreal)(0.0);
565 }
566 }
567
568
569 static void
570 oputN( /* print unperturbed normal */
571 RAY *r
572 )
573 {
574 if (r->rot < FHUGE) {
575 (*putreal)(r->ron[0]);
576 (*putreal)(r->ron[1]);
577 (*putreal)(r->ron[2]);
578 } else {
579 (*putreal)(0.0);
580 (*putreal)(0.0);
581 (*putreal)(0.0);
582 }
583 }
584
585
586 static void
587 oputn( /* print perturbed normal */
588 RAY *r
589 )
590 {
591 FVECT pnorm;
592
593 if (r->rot >= FHUGE) {
594 (*putreal)(0.0);
595 (*putreal)(0.0);
596 (*putreal)(0.0);
597 return;
598 }
599 raynormal(pnorm, r);
600 (*putreal)(pnorm[0]);
601 (*putreal)(pnorm[1]);
602 (*putreal)(pnorm[2]);
603 }
604
605
606 static void
607 oputs( /* print name */
608 RAY *r
609 )
610 {
611 if (r->ro != NULL)
612 fputs(r->ro->oname, stdout);
613 else
614 putchar('*');
615 putchar('\t');
616 }
617
618
619 static void
620 oputw( /* print weight */
621 RAY *r
622 )
623 {
624 (*putreal)(r->rweight);
625 }
626
627
628 static void
629 oputW( /* print contribution */
630 RAY *r
631 )
632 {
633 COLOR contr;
634 COLR cout;
635
636 raycontrib(contr, r, PRIMARY);
637 if (outform == 'c') {
638 setcolr(cout, colval(contr,RED),
639 colval(contr,GRN),
640 colval(contr,BLU));
641 fwrite((char *)cout, sizeof(cout), 1, stdout);
642 return;
643 }
644 (*putreal)(colval(contr,RED));
645 (*putreal)(colval(contr,GRN));
646 (*putreal)(colval(contr,BLU));
647 }
648
649
650 static void
651 oputm( /* print modifier */
652 RAY *r
653 )
654 {
655 if (r->ro != NULL)
656 if (r->ro->omod != OVOID)
657 fputs(objptr(r->ro->omod)->oname, stdout);
658 else
659 fputs(VOIDID, stdout);
660 else
661 putchar('*');
662 putchar('\t');
663 }
664
665
666 static void
667 oputM( /* print material */
668 RAY *r
669 )
670 {
671 OBJREC *mat;
672
673 if (r->ro != NULL) {
674 if ((mat = findmaterial(r->ro)) != NULL)
675 fputs(mat->oname, stdout);
676 else
677 fputs(VOIDID, stdout);
678 } else
679 putchar('*');
680 putchar('\t');
681 }
682
683
684 static void
685 puta( /* print ascii value */
686 double v
687 )
688 {
689 printf("%e\t", v);
690 }
691
692
693 static void
694 putd(v) /* print binary double */
695 double v;
696 {
697 fwrite((char *)&v, sizeof(v), 1, stdout);
698 }
699
700
701 static void
702 putf(v) /* print binary float */
703 double v;
704 {
705 float f = v;
706
707 fwrite((char *)&f, sizeof(f), 1, stdout);
708 }