ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.48
Committed: Tue Jun 21 15:06:50 2005 UTC (18 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1
Changes since 2.47: +5 -5 lines
Log Message:
Fixed bugs in black glass transmission and source weight computation

File Contents

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