ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.50
Committed: Fri Oct 7 03:45:14 2005 UTC (18 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.49: +3 -2 lines
Log Message:
Added final write error check

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rtrace.c,v 2.49 2005/09/19 11:30:10 schorsch 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 CUBE thescene; /* our scene */
35 OBJECT nsceneobjs; /* number of objects in our scene */
36
37 int dimlist[MAXDIM]; /* sampling dimensions */
38 int ndims = 0; /* number of sampling dimensions */
39 int samplendx = 0; /* index for this sample */
40
41 int imm_irrad = 0; /* compute immediate irradiance? */
42 int lim_dist = 0; /* limit distance? */
43
44 int inform = 'a'; /* input format */
45 int outform = 'a'; /* output format */
46 char *outvals = "v"; /* output specification */
47
48 int do_irrad = 0; /* compute irradiance? */
49
50 int rand_samp = 0; /* pure Monte Carlo sampling? */
51
52 void (*trace)() = NULL; /* trace call */
53
54 char *tralist[128]; /* list of modifers to trace (or no) */
55 int traincl = -1; /* include == 1, exclude == 0 */
56 #ifndef MAXTSET
57 #define MAXTSET 1024 /* maximum number in trace set */
58 #endif
59 OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */
60
61 int hresolu = 0; /* horizontal (scan) size */
62 int vresolu = 0; /* vertical resolution */
63
64 double dstrsrc = 0.0; /* square source distribution */
65 double shadthresh = .03; /* shadow threshold */
66 double shadcert = .75; /* shadow certainty */
67 int directrelay = 2; /* number of source relays */
68 int vspretest = 512; /* virtual source pretest density */
69 int directvis = 1; /* sources visible? */
70 double srcsizerat = .2; /* maximum ratio source size/dist. */
71
72 COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
73 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
74 double seccg = 0.; /* global scattering eccentricity */
75 double ssampdist = 0.; /* scatter sampling distance */
76
77 double specthresh = .15; /* specular sampling threshold */
78 double specjitter = 1.; /* specular sampling jitter */
79
80 int backvis = 1; /* back face visibility */
81
82 int maxdepth = -10; /* maximum recursion depth */
83 double minweight = 2e-3; /* minimum ray weight */
84
85 char *ambfile = NULL; /* ambient file name */
86 COLOR ambval = BLKCOLOR; /* ambient value */
87 int ambvwt = 0; /* initial weight for ambient value */
88 double ambacc = 0.15; /* ambient accuracy */
89 int ambres = 256; /* ambient resolution */
90 int ambdiv = 1024; /* ambient divisions */
91 int ambssamp = 512; /* ambient super-samples */
92 int ambounce = 0; /* ambient bounces */
93 char *amblist[AMBLLEN]; /* ambient include/exclude list */
94 int ambincl = -1; /* include == 1, exclude == 0 */
95
96 static int castonly = 0;
97
98 static RAY thisray; /* for our convenience */
99
100 typedef void putf_t(double v);
101 static putf_t puta, putd, putf;
102
103 typedef void oputf_t(RAY *r);
104 static oputf_t oputo, oputd, oputv, oputl, oputL, oputc, oputp,
105 oputn, oputN, oputs, oputw, oputW, oputm, oputM, oputtilde;
106
107 static void setoutput(char *vs);
108 static void tranotify(OBJECT obj);
109 static void bogusray(void);
110 static void rad(FVECT org, FVECT dir, double dmax);
111 static void irrad(FVECT org, FVECT dir);
112 static void printvals(RAY *r);
113 static int getvec(FVECT vec, int fmt, FILE *fp);
114 static void tabin(RAY *r);
115 static void ourtrace(RAY *r);
116
117 static oputf_t *ray_out[16], *every_out[16];
118 static putf_t *putreal;
119
120 void (*addobjnotify[])() = {ambnotify, tranotify, NULL};
121
122
123 void
124 quit( /* quit program */
125 int code
126 )
127 {
128 #ifndef NON_POSIX /* XXX we don't clean up elsewhere? */
129 headclean(); /* delete header file */
130 pfclean(); /* clean up persist files */
131 #endif
132 exit(code);
133 }
134
135
136 extern char *
137 formstr( /* return format identifier */
138 int f
139 )
140 {
141 switch (f) {
142 case 'a': return("ascii");
143 case 'f': return("float");
144 case 'd': return("double");
145 case 'c': return(COLRFMT);
146 }
147 return("unknown");
148 }
149
150
151 extern void
152 rtrace( /* trace rays from file */
153 char *fname
154 )
155 {
156 unsigned long vcount = (hresolu > 1) ? (unsigned long)hresolu*vresolu
157 : vresolu;
158 long nextflush = hresolu;
159 FILE *fp;
160 double d;
161 FVECT orig, direc;
162 /* set up input */
163 if (fname == NULL)
164 fp = stdin;
165 else if ((fp = fopen(fname, "r")) == NULL) {
166 sprintf(errmsg, "cannot open input file \"%s\"", fname);
167 error(SYSTEM, errmsg);
168 }
169 if (inform != 'a')
170 SET_FILE_BINARY(fp);
171 /* set up output */
172 setoutput(outvals);
173 switch (outform) {
174 case 'a': putreal = puta; break;
175 case 'f': putreal = putf; break;
176 case 'd': putreal = putd; break;
177 case 'c':
178 if (strcmp(outvals, "v"))
179 error(USER, "color format with value output only");
180 break;
181 default:
182 error(CONSISTENCY, "botched output format");
183 }
184 if (hresolu > 0) {
185 if (vresolu > 0)
186 fprtresolu(hresolu, vresolu, stdout);
187 fflush(stdout);
188 }
189 /* process file */
190 while (getvec(orig, inform, fp) == 0 &&
191 getvec(direc, inform, fp) == 0) {
192
193 d = normalize(direc);
194 if (d == 0.0) { /* zero ==> flush */
195 bogusray();
196 if (--nextflush <= 0 || !vcount) {
197 fflush(stdout);
198 nextflush = hresolu;
199 }
200 } else {
201 samplendx = rand_samp ? random() : samplendx+1;
202 /* compute and print */
203 if (imm_irrad)
204 irrad(orig, direc);
205 else
206 rad(orig, direc, lim_dist ? d : 0.0);
207 /* flush if time */
208 if (!--nextflush) {
209 fflush(stdout);
210 nextflush = hresolu;
211 }
212 }
213 if (ferror(stdout))
214 error(SYSTEM, "write error");
215 if (vcount && !--vcount) /* check for end */
216 break;
217 }
218 if (fflush(stdout) < 0)
219 error(SYSTEM, "write error");
220 if (vcount)
221 error(USER, "unexpected EOF on input");
222 if (fname != NULL)
223 fclose(fp);
224 }
225
226
227 static void
228 trace_sources(void) /* trace rays to light sources, also */
229 {
230 int sn;
231
232 for (sn = 0; sn < nsources; sn++)
233 source[sn].sflags |= SFOLLOW;
234 }
235
236
237 static void
238 setoutput( /* set up output tables */
239 register char *vs
240 )
241 {
242 register oputf_t **table = ray_out;
243
244 castonly = 1;
245 while (*vs)
246 switch (*vs++) {
247 case 'T': /* trace sources */
248 if (!*vs) break;
249 trace_sources();
250 /* fall through */
251 case 't': /* trace */
252 if (!*vs) break;
253 *table = NULL;
254 table = every_out;
255 trace = ourtrace;
256 castonly = 0;
257 break;
258 case 'o': /* origin */
259 *table++ = oputo;
260 break;
261 case 'd': /* direction */
262 *table++ = oputd;
263 break;
264 case 'v': /* value */
265 *table++ = oputv;
266 castonly = 0;
267 break;
268 case 'l': /* effective distance */
269 *table++ = oputl;
270 castonly = 0;
271 break;
272 case 'c': /* local coordinates */
273 *table++ = oputc;
274 break;
275 case 'L': /* single ray length */
276 *table++ = oputL;
277 break;
278 case 'p': /* point */
279 *table++ = oputp;
280 break;
281 case 'n': /* perturbed normal */
282 *table++ = oputn;
283 castonly = 0;
284 break;
285 case 'N': /* unperturbed normal */
286 *table++ = oputN;
287 break;
288 case 's': /* surface */
289 *table++ = oputs;
290 break;
291 case 'w': /* weight */
292 *table++ = oputw;
293 break;
294 case 'W': /* coefficient */
295 *table++ = oputW;
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 rad( /* compute and print ray value(s) */
327 FVECT org,
328 FVECT dir,
329 double dmax
330 )
331 {
332 VCOPY(thisray.rorg, org);
333 VCOPY(thisray.rdir, dir);
334 thisray.rmax = dmax;
335 rayorigin(&thisray, PRIMARY, NULL, NULL);
336 if (castonly) {
337 if (!localhit(&thisray, &thescene)) {
338 if (thisray.ro == &Aftplane) { /* clipped */
339 thisray.ro = NULL;
340 thisray.rot = FHUGE;
341 } else
342 sourcehit(&thisray);
343 }
344 } else
345 rayvalue(&thisray);
346 printvals(&thisray);
347 }
348
349
350 static void
351 irrad( /* compute immediate irradiance value */
352 FVECT org,
353 FVECT dir
354 )
355 {
356 register int i;
357
358 for (i = 0; i < 3; i++) {
359 thisray.rorg[i] = org[i] + dir[i];
360 thisray.rdir[i] = -dir[i];
361 }
362 thisray.rmax = 0.0;
363 rayorigin(&thisray, PRIMARY, NULL, NULL);
364 /* pretend we hit surface */
365 thisray.rot = 1.0-1e-4;
366 thisray.rod = 1.0;
367 VCOPY(thisray.ron, dir);
368 for (i = 0; i < 3; i++) /* fudge factor */
369 thisray.rop[i] = org[i] + 1e-4*dir[i];
370 /* compute and print */
371 (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
372 printvals(&thisray);
373 }
374
375
376 static void
377 printvals( /* print requested ray values */
378 RAY *r
379 )
380 {
381 register oputf_t **tp;
382
383 if (ray_out[0] == NULL)
384 return;
385 for (tp = ray_out; *tp != NULL; tp++)
386 (**tp)(r);
387 if (outform == 'a')
388 putchar('\n');
389 }
390
391
392 static int
393 getvec( /* get a vector from fp */
394 register 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 register 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 (fread((char *)vf, sizeof(float), 3, fp) != 3)
415 return(-1);
416 vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
417 break;
418 case 'd': /* binary double */
419 if (fread((char *)vd, sizeof(double), 3, fp) != 3)
420 return(-1);
421 vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
422 break;
423 default:
424 error(CONSISTENCY, "botched input format");
425 }
426 return(0);
427 }
428
429
430 static void
431 tranotify( /* record new modifier */
432 OBJECT obj
433 )
434 {
435 static int hitlimit = 0;
436 register OBJREC *o = objptr(obj);
437 register 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 register 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[0]);
499 (*putreal)(r->rorg[1]);
500 (*putreal)(r->rorg[2]);
501 }
502
503
504 static void
505 oputd( /* print direction */
506 RAY *r
507 )
508 {
509 (*putreal)(r->rdir[0]);
510 (*putreal)(r->rdir[1]);
511 (*putreal)(r->rdir[2]);
512 }
513
514
515 static void
516 oputv( /* print value */
517 RAY *r
518 )
519 {
520 if (outform == 'c') {
521 COLR cout;
522 setcolr(cout, colval(r->rcol,RED),
523 colval(r->rcol,GRN),
524 colval(r->rcol,BLU));
525 fwrite((char *)cout, sizeof(cout), 1, stdout);
526 return;
527 }
528 (*putreal)(colval(r->rcol,RED));
529 (*putreal)(colval(r->rcol,GRN));
530 (*putreal)(colval(r->rcol,BLU));
531 }
532
533
534 static void
535 oputl( /* print effective distance */
536 RAY *r
537 )
538 {
539 (*putreal)(r->rt);
540 }
541
542
543 static void
544 oputL( /* print single ray length */
545 RAY *r
546 )
547 {
548 (*putreal)(r->rot);
549 }
550
551
552 static void
553 oputc( /* print local coordinates */
554 RAY *r
555 )
556 {
557 (*putreal)(r->uv[0]);
558 (*putreal)(r->uv[1]);
559 }
560
561
562 static void
563 oputp( /* print point */
564 RAY *r
565 )
566 {
567 if (r->rot < FHUGE) {
568 (*putreal)(r->rop[0]);
569 (*putreal)(r->rop[1]);
570 (*putreal)(r->rop[2]);
571 } else {
572 (*putreal)(0.0);
573 (*putreal)(0.0);
574 (*putreal)(0.0);
575 }
576 }
577
578
579 static void
580 oputN( /* print unperturbed normal */
581 RAY *r
582 )
583 {
584 if (r->rot < FHUGE) {
585 (*putreal)(r->ron[0]);
586 (*putreal)(r->ron[1]);
587 (*putreal)(r->ron[2]);
588 } else {
589 (*putreal)(0.0);
590 (*putreal)(0.0);
591 (*putreal)(0.0);
592 }
593 }
594
595
596 static void
597 oputn( /* print perturbed normal */
598 RAY *r
599 )
600 {
601 FVECT pnorm;
602
603 if (r->rot >= FHUGE) {
604 (*putreal)(0.0);
605 (*putreal)(0.0);
606 (*putreal)(0.0);
607 return;
608 }
609 raynormal(pnorm, r);
610 (*putreal)(pnorm[0]);
611 (*putreal)(pnorm[1]);
612 (*putreal)(pnorm[2]);
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 (*putreal)(r->rweight);
635 }
636
637
638 static void
639 oputW( /* print contribution */
640 RAY *r
641 )
642 {
643 double contr[3];
644
645 raycontrib(contr, r, PRIMARY);
646 (*putreal)(contr[RED]);
647 (*putreal)(contr[GRN]);
648 (*putreal)(contr[BLU]);
649 }
650
651
652 static void
653 oputm( /* print modifier */
654 RAY *r
655 )
656 {
657 if (r->ro != NULL)
658 if (r->ro->omod != OVOID)
659 fputs(objptr(r->ro->omod)->oname, stdout);
660 else
661 fputs(VOIDID, stdout);
662 else
663 putchar('*');
664 putchar('\t');
665 }
666
667
668 static void
669 oputM( /* print material */
670 RAY *r
671 )
672 {
673 OBJREC *mat;
674
675 if (r->ro != NULL) {
676 if ((mat = findmaterial(r->ro)) != NULL)
677 fputs(mat->oname, stdout);
678 else
679 fputs(VOIDID, stdout);
680 } else
681 putchar('*');
682 putchar('\t');
683 }
684
685
686 static void
687 oputtilde( /* output tilde (spacer) */
688 RAY *r
689 )
690 {
691 fputs("~\t", stdout);
692 }
693
694
695 static void
696 puta( /* print ascii value */
697 double v
698 )
699 {
700 printf("%e\t", v);
701 }
702
703
704 static void
705 putd(v) /* print binary double */
706 double v;
707 {
708 fwrite((char *)&v, sizeof(v), 1, stdout);
709 }
710
711
712 static void
713 putf(v) /* print binary float */
714 double v;
715 {
716 float f = v;
717
718 fwrite((char *)&f, sizeof(f), 1, stdout);
719 }