ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.75
Committed: Thu Mar 28 16:33:36 2019 UTC (5 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.74: +3 -3 lines
Log Message:
Added missing initialization for rmt and rxt

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rtrace.c,v 2.74 2019/01/08 00:16:31 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 thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
318 thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
319 thisray.rmax = 0.0;
320 rayorigin(&thisray, PRIMARY, NULL, NULL);
321 printvals(&thisray);
322 }
323
324
325 static void
326 raycast( /* compute first ray intersection only */
327 RAY *r
328 )
329 {
330 if (!localhit(r, &thescene)) {
331 if (r->ro == &Aftplane) { /* clipped */
332 r->ro = NULL;
333 r->rot = FHUGE;
334 } else
335 sourcehit(r);
336 }
337 }
338
339
340 static void
341 rayirrad( /* compute irradiance rather than radiance */
342 RAY *r
343 )
344 {
345 void (*old_revf)(RAY *) = r->revf;
346 /* pretend we hit surface */
347 r->rxt = r->rmt = r->rot = 1e-5;
348 VSUM(r->rop, r->rorg, r->rdir, r->rot);
349 r->ron[0] = -r->rdir[0];
350 r->ron[1] = -r->rdir[1];
351 r->ron[2] = -r->rdir[2];
352 r->rod = 1.0;
353 /* compute result */
354 r->revf = raytrace;
355 (*ofun[Lamb.otype].funp)(&Lamb, r);
356 r->revf = old_revf;
357 }
358
359
360 static void
361 rtcompute( /* compute and print ray value(s) */
362 FVECT org,
363 FVECT dir,
364 double dmax
365 )
366 {
367 /* set up ray */
368 rayorigin(&thisray, PRIMARY, NULL, NULL);
369 if (imm_irrad) {
370 VSUM(thisray.rorg, org, dir, 1.1e-4);
371 thisray.rdir[0] = -dir[0];
372 thisray.rdir[1] = -dir[1];
373 thisray.rdir[2] = -dir[2];
374 thisray.rmax = 0.0;
375 thisray.revf = rayirrad;
376 } else {
377 VCOPY(thisray.rorg, org);
378 VCOPY(thisray.rdir, dir);
379 thisray.rmax = dmax;
380 if (castonly)
381 thisray.revf = raycast;
382 }
383 if (ray_pnprocs > 1) { /* multiprocessing FIFO? */
384 if (ray_fifo_in(&thisray) < 0)
385 error(USER, "lost children");
386 return;
387 }
388 samplendx++; /* else do it ourselves */
389 rayvalue(&thisray);
390 printvals(&thisray);
391 }
392
393
394 static int
395 printvals( /* print requested ray values */
396 RAY *r
397 )
398 {
399 oputf_t **tp;
400
401 if (ray_out[0] == NULL)
402 return(0);
403 for (tp = ray_out; *tp != NULL; tp++)
404 (**tp)(r);
405 if (outform == 'a')
406 putchar('\n');
407 return(1);
408 }
409
410
411 static int
412 getvec( /* get a vector from fp */
413 FVECT vec,
414 int fmt,
415 FILE *fp
416 )
417 {
418 static float vf[3];
419 static double vd[3];
420 char buf[32];
421 int i;
422
423 switch (fmt) {
424 case 'a': /* ascii */
425 for (i = 0; i < 3; i++) {
426 if (fgetword(buf, sizeof(buf), fp) == NULL ||
427 !isflt(buf))
428 return(-1);
429 vec[i] = atof(buf);
430 }
431 break;
432 case 'f': /* binary float */
433 if (getbinary(vf, sizeof(float), 3, fp) != 3)
434 return(-1);
435 VCOPY(vec, vf);
436 break;
437 case 'd': /* binary double */
438 if (getbinary(vd, sizeof(double), 3, fp) != 3)
439 return(-1);
440 VCOPY(vec, vd);
441 break;
442 default:
443 error(CONSISTENCY, "botched input format");
444 }
445 return(0);
446 }
447
448
449 void
450 tranotify( /* record new modifier */
451 OBJECT obj
452 )
453 {
454 static int hitlimit = 0;
455 OBJREC *o = objptr(obj);
456 char **tralp;
457
458 if (obj == OVOID) { /* starting over */
459 traset[0] = 0;
460 hitlimit = 0;
461 return;
462 }
463 if (hitlimit || !ismodifier(o->otype))
464 return;
465 for (tralp = tralist; *tralp != NULL; tralp++)
466 if (!strcmp(o->oname, *tralp)) {
467 if (traset[0] >= MAXTSET) {
468 error(WARNING, "too many modifiers in trace list");
469 hitlimit++;
470 return; /* should this be fatal? */
471 }
472 insertelem(traset, obj);
473 return;
474 }
475 }
476
477
478 static void
479 ourtrace( /* print ray values */
480 RAY *r
481 )
482 {
483 oputf_t **tp;
484
485 if (every_out[0] == NULL)
486 return;
487 if (r->ro == NULL) {
488 if (traincl == 1)
489 return;
490 } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
491 return;
492 tabin(r);
493 for (tp = every_out; *tp != NULL; tp++)
494 (**tp)(r);
495 if (outform == 'a')
496 putchar('\n');
497 }
498
499
500 static void
501 tabin( /* tab in appropriate amount */
502 RAY *r
503 )
504 {
505 const RAY *rp;
506
507 for (rp = r->parent; rp != NULL; rp = rp->parent)
508 putchar('\t');
509 }
510
511
512 static void
513 oputo( /* print origin */
514 RAY *r
515 )
516 {
517 (*putreal)(r->rorg, 3);
518 }
519
520
521 static void
522 oputd( /* print direction */
523 RAY *r
524 )
525 {
526 (*putreal)(r->rdir, 3);
527 }
528
529
530 static void
531 oputr( /* print mirrored contribution */
532 RAY *r
533 )
534 {
535 RREAL cval[3];
536
537 cval[0] = colval(r->mcol,RED);
538 cval[1] = colval(r->mcol,GRN);
539 cval[2] = colval(r->mcol,BLU);
540 (*putreal)(cval, 3);
541 }
542
543
544
545 static void
546 oputR( /* print mirrored distance */
547 RAY *r
548 )
549 {
550 (*putreal)(&r->rmt, 1);
551 }
552
553
554 static void
555 oputx( /* print unmirrored contribution */
556 RAY *r
557 )
558 {
559 RREAL cval[3];
560
561 cval[0] = colval(r->rcol,RED) - colval(r->mcol,RED);
562 cval[1] = colval(r->rcol,GRN) - colval(r->mcol,GRN);
563 cval[2] = colval(r->rcol,BLU) - colval(r->mcol,BLU);
564 (*putreal)(cval, 3);
565 }
566
567
568 static void
569 oputX( /* print unmirrored distance */
570 RAY *r
571 )
572 {
573 (*putreal)(&r->rxt, 1);
574 }
575
576
577 static void
578 oputv( /* print value */
579 RAY *r
580 )
581 {
582 RREAL cval[3];
583
584 if (outform == 'c') {
585 COLR cout;
586 setcolr(cout, colval(r->rcol,RED),
587 colval(r->rcol,GRN),
588 colval(r->rcol,BLU));
589 putbinary(cout, sizeof(cout), 1, stdout);
590 return;
591 }
592 cval[0] = colval(r->rcol,RED);
593 cval[1] = colval(r->rcol,GRN);
594 cval[2] = colval(r->rcol,BLU);
595 (*putreal)(cval, 3);
596 }
597
598
599 static void
600 oputV( /* print value contribution */
601 RAY *r
602 )
603 {
604 RREAL contr[3];
605
606 raycontrib(contr, r, PRIMARY);
607 multcolor(contr, r->rcol);
608 (*putreal)(contr, 3);
609 }
610
611
612 static void
613 oputl( /* print effective distance */
614 RAY *r
615 )
616 {
617 RREAL d = raydistance(r);
618
619 (*putreal)(&d, 1);
620 }
621
622
623 static void
624 oputL( /* print single ray length */
625 RAY *r
626 )
627 {
628 (*putreal)(&r->rot, 1);
629 }
630
631
632 static void
633 oputc( /* print local coordinates */
634 RAY *r
635 )
636 {
637 (*putreal)(r->uv, 2);
638 }
639
640
641 static RREAL vdummy[3] = {0.0, 0.0, 0.0};
642
643
644 static void
645 oputp( /* print point */
646 RAY *r
647 )
648 {
649 if (r->rot < FHUGE)
650 (*putreal)(r->rop, 3);
651 else
652 (*putreal)(vdummy, 3);
653 }
654
655
656 static void
657 oputN( /* print unperturbed normal */
658 RAY *r
659 )
660 {
661 if (r->rot < FHUGE)
662 (*putreal)(r->ron, 3);
663 else
664 (*putreal)(vdummy, 3);
665 }
666
667
668 static void
669 oputn( /* print perturbed normal */
670 RAY *r
671 )
672 {
673 FVECT pnorm;
674
675 if (r->rot >= FHUGE) {
676 (*putreal)(vdummy, 3);
677 return;
678 }
679 raynormal(pnorm, r);
680 (*putreal)(pnorm, 3);
681 }
682
683
684 static void
685 oputs( /* print name */
686 RAY *r
687 )
688 {
689 if (r->ro != NULL)
690 fputs(r->ro->oname, stdout);
691 else
692 putchar('*');
693 putchar('\t');
694 }
695
696
697 static void
698 oputw( /* print weight */
699 RAY *r
700 )
701 {
702 RREAL rwt = r->rweight;
703
704 (*putreal)(&rwt, 1);
705 }
706
707
708 static void
709 oputW( /* print coefficient */
710 RAY *r
711 )
712 {
713 RREAL contr[3];
714 /* shadow ray not on source? */
715 if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
716 setcolor(contr, 0.0, 0.0, 0.0);
717 else
718 raycontrib(contr, r, PRIMARY);
719
720 (*putreal)(contr, 3);
721 }
722
723
724 static void
725 oputm( /* print modifier */
726 RAY *r
727 )
728 {
729 if (r->ro != NULL)
730 if (r->ro->omod != OVOID)
731 fputs(objptr(r->ro->omod)->oname, stdout);
732 else
733 fputs(VOIDID, stdout);
734 else
735 putchar('*');
736 putchar('\t');
737 }
738
739
740 static void
741 oputM( /* print material */
742 RAY *r
743 )
744 {
745 OBJREC *mat;
746
747 if (r->ro != NULL) {
748 if ((mat = findmaterial(r->ro)) != NULL)
749 fputs(mat->oname, stdout);
750 else
751 fputs(VOIDID, stdout);
752 } else
753 putchar('*');
754 putchar('\t');
755 }
756
757
758 static void
759 oputtilde( /* output tilde (spacer) */
760 RAY *r
761 )
762 {
763 fputs("~\t", stdout);
764 }
765
766
767 static void
768 puta( /* print ascii value(s) */
769 RREAL *v, int n
770 )
771 {
772 if (n == 3) {
773 printf("%e\t%e\t%e\t", v[0], v[1], v[2]);
774 return;
775 }
776 while (n--)
777 printf("%e\t", *v++);
778 }
779
780
781 static void
782 putd(RREAL *v, int n) /* print binary double(s) */
783 {
784 #ifdef SMLFLT
785 double da[3];
786 int i;
787
788 if (n > 3)
789 error(INTERNAL, "code error in putd()");
790 for (i = n; i--; )
791 da[i] = v[i];
792 putbinary(da, sizeof(double), n, stdout);
793 #else
794 putbinary(v, sizeof(RREAL), n, stdout);
795 #endif
796 }
797
798
799 static void
800 putf(RREAL *v, int n) /* print binary float(s) */
801 {
802 #ifndef SMLFLT
803 float fa[3];
804 int i;
805
806 if (n > 3)
807 error(INTERNAL, "code error in putf()");
808 for (i = n; i--; )
809 fa[i] = v[i];
810 putbinary(fa, sizeof(float), n, stdout);
811 #else
812 putbinary(v, sizeof(RREAL), n, stdout);
813 #endif
814 }