ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.58
Committed: Sat Dec 12 23:08:13 2009 UTC (14 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.57: +10 -7 lines
Log Message:
Bug fixes and performance improvements to rtrace -n option

File Contents

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