ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.49
Committed: Mon Sep 19 11:30:10 2005 UTC (18 years, 7 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.48: +2 -1 lines
Log Message:
Removed SPEED from SCons. Changes to build with mingw, as suggested by Francesco Anselmo.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rtrace.c,v 2.48 2005/06/21 15:06:50 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 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 fflush(stdout);
219 if (vcount)
220 error(USER, "unexpected EOF on input");
221 if (fname != NULL)
222 fclose(fp);
223 }
224
225
226 static void
227 trace_sources(void) /* trace rays to light sources, also */
228 {
229 int sn;
230
231 for (sn = 0; sn < nsources; sn++)
232 source[sn].sflags |= SFOLLOW;
233 }
234
235
236 static void
237 setoutput( /* set up output tables */
238 register char *vs
239 )
240 {
241 register oputf_t **table = ray_out;
242
243 castonly = 1;
244 while (*vs)
245 switch (*vs++) {
246 case 'T': /* trace sources */
247 if (!*vs) break;
248 trace_sources();
249 /* fall through */
250 case 't': /* trace */
251 if (!*vs) break;
252 *table = NULL;
253 table = every_out;
254 trace = ourtrace;
255 castonly = 0;
256 break;
257 case 'o': /* origin */
258 *table++ = oputo;
259 break;
260 case 'd': /* direction */
261 *table++ = oputd;
262 break;
263 case 'v': /* value */
264 *table++ = oputv;
265 castonly = 0;
266 break;
267 case 'l': /* effective distance */
268 *table++ = oputl;
269 castonly = 0;
270 break;
271 case 'c': /* local coordinates */
272 *table++ = oputc;
273 break;
274 case 'L': /* single ray length */
275 *table++ = oputL;
276 break;
277 case 'p': /* point */
278 *table++ = oputp;
279 break;
280 case 'n': /* perturbed normal */
281 *table++ = oputn;
282 castonly = 0;
283 break;
284 case 'N': /* unperturbed normal */
285 *table++ = oputN;
286 break;
287 case 's': /* surface */
288 *table++ = oputs;
289 break;
290 case 'w': /* weight */
291 *table++ = oputw;
292 break;
293 case 'W': /* coefficient */
294 *table++ = oputW;
295 if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
296 error(WARNING,
297 "-otW accuracy depends on -aa 0 -as 0");
298 break;
299 case 'm': /* modifier */
300 *table++ = oputm;
301 break;
302 case 'M': /* material */
303 *table++ = oputM;
304 break;
305 case '~': /* tilde */
306 *table++ = oputtilde;
307 break;
308 }
309 *table = NULL;
310 }
311
312
313 static void
314 bogusray(void) /* print out empty record */
315 {
316 thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
317 thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
318 thisray.rmax = 0.0;
319 rayorigin(&thisray, PRIMARY, NULL, NULL);
320 printvals(&thisray);
321 }
322
323
324 static void
325 rad( /* compute and print ray value(s) */
326 FVECT org,
327 FVECT dir,
328 double dmax
329 )
330 {
331 VCOPY(thisray.rorg, org);
332 VCOPY(thisray.rdir, dir);
333 thisray.rmax = dmax;
334 rayorigin(&thisray, PRIMARY, NULL, NULL);
335 if (castonly) {
336 if (!localhit(&thisray, &thescene)) {
337 if (thisray.ro == &Aftplane) { /* clipped */
338 thisray.ro = NULL;
339 thisray.rot = FHUGE;
340 } else
341 sourcehit(&thisray);
342 }
343 } else
344 rayvalue(&thisray);
345 printvals(&thisray);
346 }
347
348
349 static void
350 irrad( /* compute immediate irradiance value */
351 FVECT org,
352 FVECT dir
353 )
354 {
355 register int i;
356
357 for (i = 0; i < 3; i++) {
358 thisray.rorg[i] = org[i] + dir[i];
359 thisray.rdir[i] = -dir[i];
360 }
361 thisray.rmax = 0.0;
362 rayorigin(&thisray, PRIMARY, NULL, NULL);
363 /* pretend we hit surface */
364 thisray.rot = 1.0-1e-4;
365 thisray.rod = 1.0;
366 VCOPY(thisray.ron, dir);
367 for (i = 0; i < 3; i++) /* fudge factor */
368 thisray.rop[i] = org[i] + 1e-4*dir[i];
369 /* compute and print */
370 (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
371 printvals(&thisray);
372 }
373
374
375 static void
376 printvals( /* print requested ray values */
377 RAY *r
378 )
379 {
380 register oputf_t **tp;
381
382 if (ray_out[0] == NULL)
383 return;
384 for (tp = ray_out; *tp != NULL; tp++)
385 (**tp)(r);
386 if (outform == 'a')
387 putchar('\n');
388 }
389
390
391 static int
392 getvec( /* get a vector from fp */
393 register FVECT vec,
394 int fmt,
395 FILE *fp
396 )
397 {
398 static float vf[3];
399 static double vd[3];
400 char buf[32];
401 register int i;
402
403 switch (fmt) {
404 case 'a': /* ascii */
405 for (i = 0; i < 3; i++) {
406 if (fgetword(buf, sizeof(buf), fp) == NULL ||
407 !isflt(buf))
408 return(-1);
409 vec[i] = atof(buf);
410 }
411 break;
412 case 'f': /* binary float */
413 if (fread((char *)vf, sizeof(float), 3, fp) != 3)
414 return(-1);
415 vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
416 break;
417 case 'd': /* binary double */
418 if (fread((char *)vd, sizeof(double), 3, fp) != 3)
419 return(-1);
420 vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
421 break;
422 default:
423 error(CONSISTENCY, "botched input format");
424 }
425 return(0);
426 }
427
428
429 static void
430 tranotify( /* record new modifier */
431 OBJECT obj
432 )
433 {
434 static int hitlimit = 0;
435 register OBJREC *o = objptr(obj);
436 register char **tralp;
437
438 if (obj == OVOID) { /* starting over */
439 traset[0] = 0;
440 hitlimit = 0;
441 return;
442 }
443 if (hitlimit || !ismodifier(o->otype))
444 return;
445 for (tralp = tralist; *tralp != NULL; tralp++)
446 if (!strcmp(o->oname, *tralp)) {
447 if (traset[0] >= MAXTSET) {
448 error(WARNING, "too many modifiers in trace list");
449 hitlimit++;
450 return; /* should this be fatal? */
451 }
452 insertelem(traset, obj);
453 return;
454 }
455 }
456
457
458 static void
459 ourtrace( /* print ray values */
460 RAY *r
461 )
462 {
463 register oputf_t **tp;
464
465 if (every_out[0] == NULL)
466 return;
467 if (r->ro == NULL) {
468 if (traincl == 1)
469 return;
470 } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
471 return;
472 tabin(r);
473 for (tp = every_out; *tp != NULL; tp++)
474 (**tp)(r);
475 if (outform == 'a')
476 putchar('\n');
477 }
478
479
480 static void
481 tabin( /* tab in appropriate amount */
482 RAY *r
483 )
484 {
485 const RAY *rp;
486
487 for (rp = r->parent; rp != NULL; rp = rp->parent)
488 putchar('\t');
489 }
490
491
492 static void
493 oputo( /* print origin */
494 RAY *r
495 )
496 {
497 (*putreal)(r->rorg[0]);
498 (*putreal)(r->rorg[1]);
499 (*putreal)(r->rorg[2]);
500 }
501
502
503 static void
504 oputd( /* print direction */
505 RAY *r
506 )
507 {
508 (*putreal)(r->rdir[0]);
509 (*putreal)(r->rdir[1]);
510 (*putreal)(r->rdir[2]);
511 }
512
513
514 static void
515 oputv( /* print value */
516 RAY *r
517 )
518 {
519 if (outform == 'c') {
520 COLR cout;
521 setcolr(cout, colval(r->rcol,RED),
522 colval(r->rcol,GRN),
523 colval(r->rcol,BLU));
524 fwrite((char *)cout, sizeof(cout), 1, stdout);
525 return;
526 }
527 (*putreal)(colval(r->rcol,RED));
528 (*putreal)(colval(r->rcol,GRN));
529 (*putreal)(colval(r->rcol,BLU));
530 }
531
532
533 static void
534 oputl( /* print effective distance */
535 RAY *r
536 )
537 {
538 (*putreal)(r->rt);
539 }
540
541
542 static void
543 oputL( /* print single ray length */
544 RAY *r
545 )
546 {
547 (*putreal)(r->rot);
548 }
549
550
551 static void
552 oputc( /* print local coordinates */
553 RAY *r
554 )
555 {
556 (*putreal)(r->uv[0]);
557 (*putreal)(r->uv[1]);
558 }
559
560
561 static void
562 oputp( /* print point */
563 RAY *r
564 )
565 {
566 if (r->rot < FHUGE) {
567 (*putreal)(r->rop[0]);
568 (*putreal)(r->rop[1]);
569 (*putreal)(r->rop[2]);
570 } else {
571 (*putreal)(0.0);
572 (*putreal)(0.0);
573 (*putreal)(0.0);
574 }
575 }
576
577
578 static void
579 oputN( /* print unperturbed normal */
580 RAY *r
581 )
582 {
583 if (r->rot < FHUGE) {
584 (*putreal)(r->ron[0]);
585 (*putreal)(r->ron[1]);
586 (*putreal)(r->ron[2]);
587 } else {
588 (*putreal)(0.0);
589 (*putreal)(0.0);
590 (*putreal)(0.0);
591 }
592 }
593
594
595 static void
596 oputn( /* print perturbed normal */
597 RAY *r
598 )
599 {
600 FVECT pnorm;
601
602 if (r->rot >= FHUGE) {
603 (*putreal)(0.0);
604 (*putreal)(0.0);
605 (*putreal)(0.0);
606 return;
607 }
608 raynormal(pnorm, r);
609 (*putreal)(pnorm[0]);
610 (*putreal)(pnorm[1]);
611 (*putreal)(pnorm[2]);
612 }
613
614
615 static void
616 oputs( /* print name */
617 RAY *r
618 )
619 {
620 if (r->ro != NULL)
621 fputs(r->ro->oname, stdout);
622 else
623 putchar('*');
624 putchar('\t');
625 }
626
627
628 static void
629 oputw( /* print weight */
630 RAY *r
631 )
632 {
633 (*putreal)(r->rweight);
634 }
635
636
637 static void
638 oputW( /* print contribution */
639 RAY *r
640 )
641 {
642 double contr[3];
643
644 raycontrib(contr, r, PRIMARY);
645 (*putreal)(contr[RED]);
646 (*putreal)(contr[GRN]);
647 (*putreal)(contr[BLU]);
648 }
649
650
651 static void
652 oputm( /* print modifier */
653 RAY *r
654 )
655 {
656 if (r->ro != NULL)
657 if (r->ro->omod != OVOID)
658 fputs(objptr(r->ro->omod)->oname, stdout);
659 else
660 fputs(VOIDID, stdout);
661 else
662 putchar('*');
663 putchar('\t');
664 }
665
666
667 static void
668 oputM( /* print material */
669 RAY *r
670 )
671 {
672 OBJREC *mat;
673
674 if (r->ro != NULL) {
675 if ((mat = findmaterial(r->ro)) != NULL)
676 fputs(mat->oname, stdout);
677 else
678 fputs(VOIDID, stdout);
679 } else
680 putchar('*');
681 putchar('\t');
682 }
683
684
685 static void
686 oputtilde( /* output tilde (spacer) */
687 RAY *r
688 )
689 {
690 fputs("~\t", stdout);
691 }
692
693
694 static void
695 puta( /* print ascii value */
696 double v
697 )
698 {
699 printf("%e\t", v);
700 }
701
702
703 static void
704 putd(v) /* print binary double */
705 double v;
706 {
707 fwrite((char *)&v, sizeof(v), 1, stdout);
708 }
709
710
711 static void
712 putf(v) /* print binary float */
713 double v;
714 {
715 float f = v;
716
717 fwrite((char *)&f, sizeof(f), 1, stdout);
718 }