ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.78
Committed: Sat May 4 23:10:32 2019 UTC (5 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.77: +8 -5 lines
Log Message:
Removed unnecessary clear + made multiple zero directions -> single flush

File Contents

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