ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.72
Committed: Thu Nov 8 00:54:07 2018 UTC (5 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.71: +2 -1 lines
Log Message:
Moved findmaterial() from source.c to initotypes.c

File Contents

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