ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.77
Committed: Sat May 4 13:48:06 2019 UTC (5 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.76: +3 -5 lines
Log Message:
Made rtrace a little more robust when reporting bogus ray values

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rtrace.c,v 2.76 2019/04/07 16:39:39 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 "otspecial.h"
32 #include "resolu.h"
33 #include "random.h"
34
35 extern int inform; /* input format */
36 extern int outform; /* output format */
37 extern char *outvals; /* output values */
38
39 extern int imm_irrad; /* compute immediate irradiance? */
40 extern int lim_dist; /* limit distance? */
41
42 extern char *tralist[]; /* list of modifers to trace (or no) */
43 extern int traincl; /* include == 1, exclude == 0 */
44
45 extern int hresolu; /* horizontal resolution */
46 extern int vresolu; /* vertical resolution */
47
48 static int castonly = 0;
49
50 #ifndef MAXTSET
51 #define MAXTSET 8191 /* maximum number in trace set */
52 #endif
53 OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */
54
55 static RAY thisray; /* for our convenience */
56
57 typedef void putf_t(RREAL *v, int n);
58 static putf_t puta, putd, putf;
59
60 typedef void oputf_t(RAY *r);
61 static oputf_t oputo, oputd, oputv, oputV, oputl, oputL, oputc, oputp,
62 oputr, oputR, oputx, oputX, oputn, oputN, oputs,
63 oputw, oputW, oputm, oputM, oputtilde;
64
65 static void setoutput(char *vs);
66 extern void tranotify(OBJECT obj);
67 static void bogusray(void);
68 static void raycast(RAY *r);
69 static void rayirrad(RAY *r);
70 static void rtcompute(FVECT org, FVECT dir, double dmax);
71 static int printvals(RAY *r);
72 static int getvec(FVECT vec, int fmt, FILE *fp);
73 static void tabin(RAY *r);
74 static void ourtrace(RAY *r);
75
76 static oputf_t *ray_out[32], *every_out[32];
77 static putf_t *putreal;
78
79
80 void
81 quit( /* quit program */
82 int code
83 )
84 {
85 if (ray_pnprocs > 0) /* close children if any */
86 ray_pclose(0);
87 #ifndef NON_POSIX
88 else if (!ray_pnprocs) {
89 headclean(); /* delete header file */
90 pfclean(); /* clean up persist files */
91 }
92 #endif
93 exit(code);
94 }
95
96
97 char *
98 formstr( /* return format identifier */
99 int f
100 )
101 {
102 switch (f) {
103 case 'a': return("ascii");
104 case 'f': return("float");
105 case 'd': return("double");
106 case 'c': return(COLRFMT);
107 }
108 return("unknown");
109 }
110
111
112 extern void
113 rtrace( /* trace rays from file */
114 char *fname,
115 int nproc
116 )
117 {
118 unsigned long vcount = (hresolu > 1) ? (unsigned long)hresolu*vresolu
119 : (unsigned long)vresolu;
120 long nextflush = (vresolu > 0) & (hresolu > 1) ? 0 : hresolu;
121 FILE *fp;
122 double d;
123 FVECT orig, direc;
124 /* set up input */
125 if (fname == NULL)
126 fp = stdin;
127 else if ((fp = fopen(fname, "r")) == NULL) {
128 sprintf(errmsg, "cannot open input file \"%s\"", fname);
129 error(SYSTEM, errmsg);
130 }
131 if (inform != 'a')
132 SET_FILE_BINARY(fp);
133 /* set up output */
134 setoutput(outvals);
135 if (imm_irrad)
136 castonly = 0;
137 else if (castonly)
138 nproc = 1; /* don't bother multiprocessing */
139 switch (outform) {
140 case 'a': putreal = puta; break;
141 case 'f': putreal = putf; break;
142 case 'd': putreal = putd; break;
143 case 'c':
144 if (strcmp(outvals, "v"))
145 error(USER, "color format with value output only");
146 break;
147 default:
148 error(CONSISTENCY, "botched output format");
149 }
150 if (nproc > 1) { /* start multiprocessing */
151 ray_popen(nproc);
152 ray_fifo_out = printvals;
153 }
154 if (hresolu > 0) {
155 if (vresolu > 0)
156 fprtresolu(hresolu, vresolu, stdout);
157 fflush(stdout);
158 }
159 /* process file */
160 while (getvec(orig, inform, fp) == 0 &&
161 getvec(direc, inform, fp) == 0) {
162
163 d = normalize(direc);
164 if (d == 0.0) { /* zero ==> flush */
165 if ((--nextflush <= 0) | !vcount) {
166 if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
167 error(USER, "child(ren) died");
168 bogusray();
169 fflush(stdout);
170 nextflush = (vresolu > 0) & (hresolu > 1) ? 0 :
171 hresolu;
172 } else
173 bogusray();
174 } else { /* compute and print */
175 rtcompute(orig, direc, lim_dist ? d : 0.0);
176 /* flush if time */
177 if (!--nextflush) {
178 if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
179 error(USER, "child(ren) died");
180 fflush(stdout);
181 nextflush = hresolu;
182 }
183 }
184 if (ferror(stdout))
185 error(SYSTEM, "write error");
186 if (vcount && !--vcount) /* check for end */
187 break;
188 }
189 if (ray_pnprocs > 1) { /* clean up children */
190 if (ray_fifo_flush() < 0)
191 error(USER, "unable to complete processing");
192 ray_pclose(0);
193 }
194 if (fflush(stdout) < 0)
195 error(SYSTEM, "write error");
196 if (vcount)
197 error(USER, "unexpected EOF on input");
198 if (fname != NULL)
199 fclose(fp);
200 }
201
202
203 static void
204 trace_sources(void) /* trace rays to light sources, also */
205 {
206 int sn;
207
208 for (sn = 0; sn < nsources; sn++)
209 source[sn].sflags |= SFOLLOW;
210 }
211
212
213 static void
214 setoutput( /* set up output tables */
215 char *vs
216 )
217 {
218 oputf_t **table = ray_out;
219
220 castonly = 1;
221 while (*vs)
222 switch (*vs++) {
223 case 'T': /* trace sources */
224 if (!*vs) break;
225 trace_sources();
226 /* fall through */
227 case 't': /* trace */
228 if (!*vs) break;
229 *table = NULL;
230 table = every_out;
231 trace = ourtrace;
232 castonly = 0;
233 break;
234 case 'o': /* origin */
235 *table++ = oputo;
236 break;
237 case 'd': /* direction */
238 *table++ = oputd;
239 break;
240 case 'r': /* reflected contrib. */
241 *table++ = oputr;
242 castonly = 0;
243 break;
244 case 'R': /* reflected distance */
245 *table++ = oputR;
246 castonly = 0;
247 break;
248 case 'x': /* xmit contrib. */
249 *table++ = oputx;
250 castonly = 0;
251 break;
252 case 'X': /* xmit distance */
253 *table++ = oputX;
254 castonly = 0;
255 break;
256 case 'v': /* value */
257 *table++ = oputv;
258 castonly = 0;
259 break;
260 case 'V': /* contribution */
261 *table++ = oputV;
262 castonly = 0;
263 if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
264 error(WARNING,
265 "-otV accuracy depends on -aa 0 -as 0");
266 break;
267 case 'l': /* effective distance */
268 *table++ = oputl;
269 castonly = 0;
270 break;
271 case 'c': /* local coordinates */
272 *table++ = oputc;
273 break;
274 case 'L': /* single ray length */
275 *table++ = oputL;
276 break;
277 case 'p': /* point */
278 *table++ = oputp;
279 break;
280 case 'n': /* perturbed normal */
281 *table++ = oputn;
282 castonly = 0;
283 break;
284 case 'N': /* unperturbed normal */
285 *table++ = oputN;
286 break;
287 case 's': /* surface */
288 *table++ = oputs;
289 break;
290 case 'w': /* weight */
291 *table++ = oputw;
292 break;
293 case 'W': /* coefficient */
294 *table++ = oputW;
295 castonly = 0;
296 if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
297 error(WARNING,
298 "-otW accuracy depends on -aa 0 -as 0");
299 break;
300 case 'm': /* modifier */
301 *table++ = oputm;
302 break;
303 case 'M': /* material */
304 *table++ = oputM;
305 break;
306 case '~': /* tilde */
307 *table++ = oputtilde;
308 break;
309 }
310 *table = NULL;
311 }
312
313
314 static void
315 bogusray(void) /* print out empty record */
316 {
317 memset(&thisray, 0, sizeof(thisray));
318 rayorigin(&thisray, PRIMARY, NULL, NULL);
319 printvals(&thisray);
320 }
321
322
323 static void
324 raycast( /* compute first ray intersection only */
325 RAY *r
326 )
327 {
328 if (!localhit(r, &thescene)) {
329 if (r->ro == &Aftplane) { /* clipped */
330 r->ro = NULL;
331 r->rot = FHUGE;
332 } else
333 sourcehit(r);
334 }
335 }
336
337
338 static void
339 rayirrad( /* compute irradiance rather than radiance */
340 RAY *r
341 )
342 {
343 void (*old_revf)(RAY *) = r->revf;
344 /* pretend we hit surface */
345 r->rxt = r->rot = 1e-5;
346 VSUM(r->rop, r->rorg, r->rdir, r->rot);
347 r->ron[0] = -r->rdir[0];
348 r->ron[1] = -r->rdir[1];
349 r->ron[2] = -r->rdir[2];
350 r->rod = 1.0;
351 /* compute result */
352 r->revf = raytrace;
353 (*ofun[Lamb.otype].funp)(&Lamb, r);
354 r->revf = old_revf;
355 }
356
357
358 static void
359 rtcompute( /* compute and print ray value(s) */
360 FVECT org,
361 FVECT dir,
362 double dmax
363 )
364 {
365 /* set up ray */
366 rayorigin(&thisray, PRIMARY, NULL, NULL);
367 if (imm_irrad) {
368 VSUM(thisray.rorg, org, dir, 1.1e-4);
369 thisray.rdir[0] = -dir[0];
370 thisray.rdir[1] = -dir[1];
371 thisray.rdir[2] = -dir[2];
372 thisray.rmax = 0.0;
373 thisray.revf = rayirrad;
374 } else {
375 VCOPY(thisray.rorg, org);
376 VCOPY(thisray.rdir, dir);
377 thisray.rmax = dmax;
378 if (castonly)
379 thisray.revf = raycast;
380 }
381 if (ray_pnprocs > 1) { /* multiprocessing FIFO? */
382 if (ray_fifo_in(&thisray) < 0)
383 error(USER, "lost children");
384 return;
385 }
386 samplendx++; /* else do it ourselves */
387 rayvalue(&thisray);
388 printvals(&thisray);
389 }
390
391
392 static int
393 printvals( /* print requested ray values */
394 RAY *r
395 )
396 {
397 oputf_t **tp;
398
399 if (ray_out[0] == NULL)
400 return(0);
401 for (tp = ray_out; *tp != NULL; tp++)
402 (**tp)(r);
403 if (outform == 'a')
404 putchar('\n');
405 return(1);
406 }
407
408
409 static int
410 getvec( /* get a vector from fp */
411 FVECT vec,
412 int fmt,
413 FILE *fp
414 )
415 {
416 static float vf[3];
417 static double vd[3];
418 char buf[32];
419 int i;
420
421 switch (fmt) {
422 case 'a': /* ascii */
423 for (i = 0; i < 3; i++) {
424 if (fgetword(buf, sizeof(buf), fp) == NULL ||
425 !isflt(buf))
426 return(-1);
427 vec[i] = atof(buf);
428 }
429 break;
430 case 'f': /* binary float */
431 if (getbinary(vf, sizeof(float), 3, fp) != 3)
432 return(-1);
433 VCOPY(vec, vf);
434 break;
435 case 'd': /* binary double */
436 if (getbinary(vd, sizeof(double), 3, fp) != 3)
437 return(-1);
438 VCOPY(vec, vd);
439 break;
440 default:
441 error(CONSISTENCY, "botched input format");
442 }
443 return(0);
444 }
445
446
447 void
448 tranotify( /* record new modifier */
449 OBJECT obj
450 )
451 {
452 static int hitlimit = 0;
453 OBJREC *o = objptr(obj);
454 char **tralp;
455
456 if (obj == OVOID) { /* starting over */
457 traset[0] = 0;
458 hitlimit = 0;
459 return;
460 }
461 if (hitlimit || !ismodifier(o->otype))
462 return;
463 for (tralp = tralist; *tralp != NULL; tralp++)
464 if (!strcmp(o->oname, *tralp)) {
465 if (traset[0] >= MAXTSET) {
466 error(WARNING, "too many modifiers in trace list");
467 hitlimit++;
468 return; /* should this be fatal? */
469 }
470 insertelem(traset, obj);
471 return;
472 }
473 }
474
475
476 static void
477 ourtrace( /* print ray values */
478 RAY *r
479 )
480 {
481 oputf_t **tp;
482
483 if (every_out[0] == NULL)
484 return;
485 if (r->ro == NULL) {
486 if (traincl == 1)
487 return;
488 } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
489 return;
490 tabin(r);
491 for (tp = every_out; *tp != NULL; tp++)
492 (**tp)(r);
493 if (outform == 'a')
494 putchar('\n');
495 }
496
497
498 static void
499 tabin( /* tab in appropriate amount */
500 RAY *r
501 )
502 {
503 const RAY *rp;
504
505 for (rp = r->parent; rp != NULL; rp = rp->parent)
506 putchar('\t');
507 }
508
509
510 static void
511 oputo( /* print origin */
512 RAY *r
513 )
514 {
515 (*putreal)(r->rorg, 3);
516 }
517
518
519 static void
520 oputd( /* print direction */
521 RAY *r
522 )
523 {
524 (*putreal)(r->rdir, 3);
525 }
526
527
528 static void
529 oputr( /* print mirrored contribution */
530 RAY *r
531 )
532 {
533 RREAL cval[3];
534
535 cval[0] = colval(r->mcol,RED);
536 cval[1] = colval(r->mcol,GRN);
537 cval[2] = colval(r->mcol,BLU);
538 (*putreal)(cval, 3);
539 }
540
541
542
543 static void
544 oputR( /* print mirrored distance */
545 RAY *r
546 )
547 {
548 (*putreal)(&r->rmt, 1);
549 }
550
551
552 static void
553 oputx( /* print unmirrored contribution */
554 RAY *r
555 )
556 {
557 RREAL cval[3];
558
559 cval[0] = colval(r->rcol,RED) - colval(r->mcol,RED);
560 cval[1] = colval(r->rcol,GRN) - colval(r->mcol,GRN);
561 cval[2] = colval(r->rcol,BLU) - colval(r->mcol,BLU);
562 (*putreal)(cval, 3);
563 }
564
565
566 static void
567 oputX( /* print unmirrored distance */
568 RAY *r
569 )
570 {
571 (*putreal)(&r->rxt, 1);
572 }
573
574
575 static void
576 oputv( /* print value */
577 RAY *r
578 )
579 {
580 RREAL cval[3];
581
582 if (outform == 'c') {
583 COLR cout;
584 setcolr(cout, colval(r->rcol,RED),
585 colval(r->rcol,GRN),
586 colval(r->rcol,BLU));
587 putbinary(cout, sizeof(cout), 1, stdout);
588 return;
589 }
590 cval[0] = colval(r->rcol,RED);
591 cval[1] = colval(r->rcol,GRN);
592 cval[2] = colval(r->rcol,BLU);
593 (*putreal)(cval, 3);
594 }
595
596
597 static void
598 oputV( /* print value contribution */
599 RAY *r
600 )
601 {
602 RREAL contr[3];
603
604 raycontrib(contr, r, PRIMARY);
605 multcolor(contr, r->rcol);
606 (*putreal)(contr, 3);
607 }
608
609
610 static void
611 oputl( /* print effective distance */
612 RAY *r
613 )
614 {
615 RREAL d = raydistance(r);
616
617 (*putreal)(&d, 1);
618 }
619
620
621 static void
622 oputL( /* print single ray length */
623 RAY *r
624 )
625 {
626 (*putreal)(&r->rot, 1);
627 }
628
629
630 static void
631 oputc( /* print local coordinates */
632 RAY *r
633 )
634 {
635 (*putreal)(r->uv, 2);
636 }
637
638
639 static RREAL vdummy[3] = {0.0, 0.0, 0.0};
640
641
642 static void
643 oputp( /* print point */
644 RAY *r
645 )
646 {
647 if (r->rot < FHUGE)
648 (*putreal)(r->rop, 3);
649 else
650 (*putreal)(vdummy, 3);
651 }
652
653
654 static void
655 oputN( /* print unperturbed normal */
656 RAY *r
657 )
658 {
659 if (r->rot < FHUGE)
660 (*putreal)(r->ron, 3);
661 else
662 (*putreal)(vdummy, 3);
663 }
664
665
666 static void
667 oputn( /* print perturbed normal */
668 RAY *r
669 )
670 {
671 FVECT pnorm;
672
673 if (r->rot >= FHUGE) {
674 (*putreal)(vdummy, 3);
675 return;
676 }
677 raynormal(pnorm, r);
678 (*putreal)(pnorm, 3);
679 }
680
681
682 static void
683 oputs( /* print name */
684 RAY *r
685 )
686 {
687 if (r->ro != NULL)
688 fputs(r->ro->oname, stdout);
689 else
690 putchar('*');
691 putchar('\t');
692 }
693
694
695 static void
696 oputw( /* print weight */
697 RAY *r
698 )
699 {
700 RREAL rwt = r->rweight;
701
702 (*putreal)(&rwt, 1);
703 }
704
705
706 static void
707 oputW( /* print coefficient */
708 RAY *r
709 )
710 {
711 RREAL contr[3];
712 /* shadow ray not on source? */
713 if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
714 setcolor(contr, 0.0, 0.0, 0.0);
715 else
716 raycontrib(contr, r, PRIMARY);
717
718 (*putreal)(contr, 3);
719 }
720
721
722 static void
723 oputm( /* print modifier */
724 RAY *r
725 )
726 {
727 if (r->ro != NULL)
728 if (r->ro->omod != OVOID)
729 fputs(objptr(r->ro->omod)->oname, stdout);
730 else
731 fputs(VOIDID, stdout);
732 else
733 putchar('*');
734 putchar('\t');
735 }
736
737
738 static void
739 oputM( /* print material */
740 RAY *r
741 )
742 {
743 OBJREC *mat;
744
745 if (r->ro != NULL) {
746 if ((mat = findmaterial(r->ro)) != NULL)
747 fputs(mat->oname, stdout);
748 else
749 fputs(VOIDID, stdout);
750 } else
751 putchar('*');
752 putchar('\t');
753 }
754
755
756 static void
757 oputtilde( /* output tilde (spacer) */
758 RAY *r
759 )
760 {
761 fputs("~\t", stdout);
762 }
763
764
765 static void
766 puta( /* print ascii value(s) */
767 RREAL *v, int n
768 )
769 {
770 if (n == 3) {
771 printf("%e\t%e\t%e\t", v[0], v[1], v[2]);
772 return;
773 }
774 while (n--)
775 printf("%e\t", *v++);
776 }
777
778
779 static void
780 putd(RREAL *v, int n) /* print binary double(s) */
781 {
782 #ifdef SMLFLT
783 double da[3];
784 int i;
785
786 if (n > 3)
787 error(INTERNAL, "code error in putd()");
788 for (i = n; i--; )
789 da[i] = v[i];
790 putbinary(da, sizeof(double), n, stdout);
791 #else
792 putbinary(v, sizeof(RREAL), n, stdout);
793 #endif
794 }
795
796
797 static void
798 putf(RREAL *v, int n) /* print binary float(s) */
799 {
800 #ifndef SMLFLT
801 float fa[3];
802 int i;
803
804 if (n > 3)
805 error(INTERNAL, "code error in putf()");
806 for (i = n; i--; )
807 fa[i] = v[i];
808 putbinary(fa, sizeof(float), n, stdout);
809 #else
810 putbinary(v, sizeof(RREAL), n, stdout);
811 #endif
812 }