ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.57
Committed: Sat Dec 12 19:01:00 2009 UTC (14 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.56: +40 -77 lines
Log Message:
Added -n option to rtrace and moved quit() funciton out of raypcalls

File Contents

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