ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
Revision: 2.31
Committed: Mon Jun 30 14:59:12 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.30: +2 -2 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 2.31 static const char RCSid[] = "$Id: rtrace.c,v 2.30 2003/06/05 19:29:34 schorsch 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    
24 schorsch 2.30 #include "platform.h"
25 greg 1.1 #include "ray.h"
26     #include "otypes.h"
27 greg 2.6 #include "resolu.h"
28    
29 greg 2.27 CUBE thescene; /* our scene */
30     OBJECT nsceneobjs; /* number of objects in our scene */
31    
32 greg 1.14 int dimlist[MAXDIM]; /* sampling dimensions */
33     int ndims = 0; /* number of sampling dimensions */
34     int samplendx = 0; /* index for this sample */
35    
36 greg 1.13 int imm_irrad = 0; /* compute immediate irradiance? */
37 gregl 2.25 int lim_dist = 0; /* limit distance? */
38 greg 1.13
39 greg 1.1 int inform = 'a'; /* input format */
40     int outform = 'a'; /* output format */
41     char *outvals = "v"; /* output specification */
42    
43 greg 2.27 int do_irrad = 0; /* compute irradiance? */
44    
45     void (*trace)() = NULL; /* trace call */
46    
47     extern void ambnotify(), tranotify();
48     void (*addobjnotify[])() = {ambnotify, tranotify, NULL};
49 greg 2.15 char *tralist[128]; /* list of modifers to trace (or no) */
50     int traincl = -1; /* include == 1, exclude == 0 */
51     #define MAXTSET 511 /* maximum number in trace set */
52     OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */
53    
54 greg 1.1 int hresolu = 0; /* horizontal (scan) size */
55     int vresolu = 0; /* vertical resolution */
56    
57     double dstrsrc = 0.0; /* square source distribution */
58 greg 1.4 double shadthresh = .05; /* shadow threshold */
59 greg 1.5 double shadcert = .5; /* shadow certainty */
60 greg 2.19 int directrelay = 2; /* number of source relays */
61 greg 1.17 int vspretest = 512; /* virtual source pretest density */
62 greg 2.10 int directvis = 1; /* sources visible? */
63 greg 2.19 double srcsizerat = .2; /* maximum ratio source size/dist. */
64 greg 2.20
65     COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
66 greg 2.22 COLOR salbedo = BLKCOLOR; /* global scattering albedo */
67 greg 2.20 double seccg = 0.; /* global scattering eccentricity */
68     double ssampdist = 0.; /* scatter sampling distance */
69 greg 1.1
70 greg 2.4 double specthresh = .15; /* specular sampling threshold */
71 greg 2.3 double specjitter = 1.; /* specular sampling jitter */
72    
73 greg 2.18 int backvis = 1; /* back face visibility */
74    
75 greg 1.1 int maxdepth = 6; /* maximum recursion depth */
76     double minweight = 4e-3; /* minimum ray weight */
77    
78 greg 2.27 char *ambfile = NULL; /* ambient file name */
79 greg 1.1 COLOR ambval = BLKCOLOR; /* ambient value */
80 greg 2.21 int ambvwt = 0; /* initial weight for ambient value */
81 greg 1.1 double ambacc = 0.2; /* ambient accuracy */
82 greg 2.19 int ambres = 128; /* ambient resolution */
83     int ambdiv = 512; /* ambient divisions */
84 greg 1.1 int ambssamp = 0; /* ambient super-samples */
85     int ambounce = 0; /* ambient bounces */
86     char *amblist[128]; /* ambient include/exclude list */
87     int ambincl = -1; /* include == 1, exclude == 0 */
88    
89 gregl 2.25
90 greg 1.1 static RAY thisray; /* for our convenience */
91    
92 greg 2.29 static void oputo(), oputd(), oputv(), oputl(), oputL(), oputc(),
93 greg 2.9 oputp(), oputn(), oputN(), oputs(), oputw(), oputm();
94 greg 1.1
95 greg 2.27 static void ourtrace(), tabin();
96     static void (*ray_out[16])(), (*every_out[16])();
97 greg 2.14 static int castonly = 0;
98 greg 1.1
99 greg 2.27 static void puta(), putf(), putd();
100    
101     static void (*putreal)();
102 greg 1.1
103 greg 2.27 void bogusray(), rad(), irrad(), printvals();
104 greg 1.1
105    
106 greg 2.27 void
107 greg 1.1 quit(code) /* quit program */
108     int code;
109     {
110 schorsch 2.31 #ifndef NON_POSIX /* XXX we don't clean up elsewhere? */
111 greg 2.11 headclean(); /* delete header file */
112     pfclean(); /* clean up persist files */
113     #endif
114 greg 1.1 exit(code);
115     }
116    
117    
118 greg 2.6 char *
119     formstr(f) /* return format identifier */
120     int f;
121     {
122     switch (f) {
123     case 'a': return("ascii");
124     case 'f': return("float");
125     case 'd': return("double");
126     case 'c': return(COLRFMT);
127     }
128     return("unknown");
129     }
130    
131    
132 greg 2.27 void
133 greg 1.1 rtrace(fname) /* trace rays from file */
134     char *fname;
135     {
136     long vcount = hresolu>1 ? hresolu*vresolu : vresolu;
137     long nextflush = hresolu;
138     FILE *fp;
139 gregl 2.25 double d;
140 greg 1.2 FVECT orig, direc;
141 greg 1.1 /* set up input */
142     if (fname == NULL)
143     fp = stdin;
144     else if ((fp = fopen(fname, "r")) == NULL) {
145     sprintf(errmsg, "cannot open input file \"%s\"", fname);
146     error(SYSTEM, errmsg);
147     }
148 schorsch 2.30 #ifdef _WIN32
149 greg 2.8 if (inform != 'a')
150 schorsch 2.30 SET_FILE_BINARY(fp);
151 greg 2.8 #endif
152 greg 1.1 /* set up output */
153 greg 2.16 setoutput(outvals);
154 greg 1.1 switch (outform) {
155     case 'a': putreal = puta; break;
156     case 'f': putreal = putf; break;
157     case 'd': putreal = putd; break;
158 greg 2.6 case 'c':
159     if (strcmp(outvals, "v"))
160     error(USER, "color format with value output only");
161     break;
162     default:
163     error(CONSISTENCY, "botched output format");
164 greg 1.1 }
165 greg 2.12 if (hresolu > 0) {
166     if (vresolu > 0)
167     fprtresolu(hresolu, vresolu, stdout);
168     fflush(stdout);
169     }
170 greg 1.1 /* process file */
171     while (getvec(orig, inform, fp) == 0 &&
172     getvec(direc, inform, fp) == 0) {
173    
174 gregl 2.25 d = normalize(direc);
175     if (d == 0.0) { /* zero ==> flush */
176 gregl 2.24 bogusray();
177 gregl 2.26 if (--nextflush <= 0 || vcount <= 0) {
178 gregl 2.24 fflush(stdout);
179     nextflush = hresolu;
180     }
181     } else {
182     samplendx++;
183 greg 1.1 /* compute and print */
184 gregl 2.24 if (imm_irrad)
185     irrad(orig, direc);
186     else
187 gregl 2.25 rad(orig, direc, lim_dist ? d : 0.0);
188 greg 1.7 /* flush if time */
189 gregl 2.24 if (--nextflush == 0) {
190     fflush(stdout);
191     nextflush = hresolu;
192     }
193 greg 1.1 }
194     if (ferror(stdout))
195     error(SYSTEM, "write error");
196     if (--vcount == 0) /* check for end */
197     break;
198     }
199 greg 2.12 fflush(stdout);
200 greg 1.1 if (vcount > 0)
201     error(USER, "read error");
202 greg 2.12 if (fname != NULL)
203     fclose(fp);
204 greg 1.1 }
205    
206    
207     setoutput(vs) /* set up output tables */
208     register char *vs;
209     {
210 greg 2.27 extern void (*trace)();
211     register void (**table)() = ray_out;
212 greg 1.1
213 greg 1.11 castonly = 1;
214 greg 1.1 while (*vs)
215     switch (*vs++) {
216     case 't': /* trace */
217     *table = NULL;
218     table = every_out;
219     trace = ourtrace;
220 greg 1.11 castonly = 0;
221 greg 1.1 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 greg 1.11 castonly = 0;
231 greg 1.1 break;
232 greg 2.5 case 'l': /* effective distance */
233 greg 1.1 *table++ = oputl;
234 greg 1.11 castonly = 0;
235 greg 1.1 break;
236 greg 2.29 case 'c': /* local coordinates */
237     *table++ = oputc;
238     break;
239 greg 2.5 case 'L': /* single ray length */
240     *table++ = oputL;
241     break;
242 greg 1.1 case 'p': /* point */
243     *table++ = oputp;
244     break;
245 greg 2.9 case 'n': /* perturbed normal */
246 greg 1.1 *table++ = oputn;
247 greg 2.9 castonly = 0;
248 greg 1.1 break;
249 greg 2.9 case 'N': /* unperturbed normal */
250     *table++ = oputN;
251     break;
252 greg 1.1 case 's': /* surface */
253     *table++ = oputs;
254     break;
255     case 'w': /* weight */
256     *table++ = oputw;
257     break;
258     case 'm': /* modifier */
259     *table++ = oputm;
260     break;
261     }
262     *table = NULL;
263 gregl 2.24 }
264    
265    
266 greg 2.27 void
267 gregl 2.24 bogusray() /* print out empty record */
268     {
269     thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
270     thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
271     rayorigin(&thisray, NULL, PRIMARY, 1.0);
272     printvals(&thisray);
273 greg 1.1 }
274    
275    
276 greg 2.27 void
277 gregl 2.25 rad(org, dir, dmax) /* compute and print ray value(s) */
278 greg 1.1 FVECT org, dir;
279 gregl 2.25 double dmax;
280 greg 1.1 {
281     VCOPY(thisray.rorg, org);
282     VCOPY(thisray.rdir, dir);
283 gregl 2.25 thisray.rmax = dmax;
284 greg 1.1 rayorigin(&thisray, NULL, PRIMARY, 1.0);
285 gregl 2.25 if (castonly) {
286     if (!localhit(&thisray, &thescene))
287     if (thisray.ro == &Aftplane) { /* clipped */
288     thisray.ro = NULL;
289     thisray.rot = FHUGE;
290     } else
291     sourcehit(&thisray);
292     } else
293 greg 1.11 rayvalue(&thisray);
294 greg 2.16 printvals(&thisray);
295 greg 1.1 }
296    
297    
298 greg 2.27 void
299 greg 1.13 irrad(org, dir) /* compute immediate irradiance value */
300 greg 1.1 FVECT org, dir;
301     {
302     register int i;
303    
304     for (i = 0; i < 3; i++) {
305     thisray.rorg[i] = org[i] + dir[i];
306     thisray.rdir[i] = -dir[i];
307     }
308     rayorigin(&thisray, NULL, PRIMARY, 1.0);
309     /* pretend we hit surface */
310 greg 2.16 thisray.rot = 1.0-1e-4;
311 greg 1.1 thisray.rod = 1.0;
312     VCOPY(thisray.ron, dir);
313     for (i = 0; i < 3; i++) /* fudge factor */
314     thisray.rop[i] = org[i] + 1e-4*dir[i];
315     /* compute and print */
316     (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
317 greg 2.16 printvals(&thisray);
318     }
319    
320    
321 greg 2.27 void
322 greg 2.16 printvals(r) /* print requested ray values */
323     RAY *r;
324     {
325 greg 2.27 register void (**tp)();
326 greg 2.16
327     if (ray_out[0] == NULL)
328     return;
329     for (tp = ray_out; *tp != NULL; tp++)
330     (**tp)(r);
331 greg 1.1 if (outform == 'a')
332     putchar('\n');
333     }
334    
335    
336 greg 2.27 int
337 greg 1.1 getvec(vec, fmt, fp) /* get a vector from fp */
338     register FVECT vec;
339     int fmt;
340     FILE *fp;
341     {
342     static float vf[3];
343 greg 2.5 static double vd[3];
344 greg 1.19 char buf[32];
345     register int i;
346 greg 1.1
347     switch (fmt) {
348     case 'a': /* ascii */
349 greg 1.19 for (i = 0; i < 3; i++) {
350     if (fgetword(buf, sizeof(buf), fp) == NULL ||
351     !isflt(buf))
352     return(-1);
353     vec[i] = atof(buf);
354     }
355 greg 1.1 break;
356     case 'f': /* binary float */
357 greg 1.8 if (fread((char *)vf, sizeof(float), 3, fp) != 3)
358 greg 1.1 return(-1);
359     vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
360     break;
361     case 'd': /* binary double */
362 greg 2.5 if (fread((char *)vd, sizeof(double), 3, fp) != 3)
363 greg 1.1 return(-1);
364 greg 2.5 vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
365 greg 1.1 break;
366 greg 2.6 default:
367     error(CONSISTENCY, "botched input format");
368 greg 1.1 }
369     return(0);
370     }
371    
372    
373 greg 2.27 void
374 greg 2.15 tranotify(obj) /* record new modifier */
375     OBJECT obj;
376     {
377     static int hitlimit = 0;
378     register OBJREC *o = objptr(obj);
379     register char **tralp;
380    
381 greg 2.27 if (obj == OVOID) { /* starting over */
382     traset[0] = 0;
383     hitlimit = 0;
384     return;
385     }
386 greg 2.15 if (hitlimit || !ismodifier(o->otype))
387     return;
388     for (tralp = tralist; *tralp != NULL; tralp++)
389     if (!strcmp(o->oname, *tralp)) {
390     if (traset[0] >= MAXTSET) {
391     error(WARNING, "too many modifiers in trace list");
392     hitlimit++;
393     return; /* should this be fatal? */
394     }
395     insertelem(traset, obj);
396     return;
397     }
398     }
399    
400    
401 greg 2.27 static void
402 greg 1.1 ourtrace(r) /* print ray values */
403     RAY *r;
404     {
405 greg 2.27 register void (**tp)();
406 greg 1.1
407     if (every_out[0] == NULL)
408 greg 2.15 return;
409 greg 2.16 if (r->ro == NULL) {
410     if (traincl == 1)
411     return;
412     } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
413 greg 1.1 return;
414     tabin(r);
415     for (tp = every_out; *tp != NULL; tp++)
416     (**tp)(r);
417     putchar('\n');
418     }
419    
420    
421 greg 2.27 static void
422 greg 1.1 tabin(r) /* tab in appropriate amount */
423     RAY *r;
424     {
425     register RAY *rp;
426    
427     for (rp = r->parent; rp != NULL; rp = rp->parent)
428     putchar('\t');
429     }
430    
431    
432 greg 2.27 static void
433 greg 1.1 oputo(r) /* print origin */
434 greg 2.29 RAY *r;
435 greg 1.1 {
436     (*putreal)(r->rorg[0]);
437     (*putreal)(r->rorg[1]);
438     (*putreal)(r->rorg[2]);
439     }
440    
441    
442 greg 2.27 static void
443 greg 1.1 oputd(r) /* print direction */
444 greg 2.29 RAY *r;
445 greg 1.1 {
446     (*putreal)(r->rdir[0]);
447     (*putreal)(r->rdir[1]);
448     (*putreal)(r->rdir[2]);
449     }
450    
451    
452 greg 2.27 static void
453 greg 1.1 oputv(r) /* print value */
454 greg 2.29 RAY *r;
455 greg 1.1 {
456 greg 2.6 COLR cout;
457    
458     if (outform == 'c') {
459     setcolr(cout, colval(r->rcol,RED),
460     colval(r->rcol,GRN),
461     colval(r->rcol,BLU));
462     fwrite((char *)cout, sizeof(cout), 1, stdout);
463     return;
464     }
465 greg 1.1 (*putreal)(colval(r->rcol,RED));
466     (*putreal)(colval(r->rcol,GRN));
467     (*putreal)(colval(r->rcol,BLU));
468     }
469    
470    
471 greg 2.27 static void
472 greg 2.5 oputl(r) /* print effective distance */
473 greg 2.29 RAY *r;
474 greg 1.1 {
475 greg 1.9 (*putreal)(r->rt);
476 greg 2.5 }
477    
478    
479 greg 2.27 static void
480 greg 2.5 oputL(r) /* print single ray length */
481 greg 2.29 RAY *r;
482 greg 2.5 {
483     (*putreal)(r->rot);
484 greg 1.1 }
485    
486    
487 greg 2.27 static void
488 greg 2.29 oputc(r) /* print local coordinates */
489     RAY *r;
490     {
491     (*putreal)(r->uv[0]);
492     (*putreal)(r->uv[1]);
493     }
494    
495    
496     static void
497 greg 1.1 oputp(r) /* print point */
498 greg 2.29 RAY *r;
499 greg 1.1 {
500     if (r->rot < FHUGE) {
501     (*putreal)(r->rop[0]);
502     (*putreal)(r->rop[1]);
503     (*putreal)(r->rop[2]);
504     } else {
505     (*putreal)(0.0);
506     (*putreal)(0.0);
507     (*putreal)(0.0);
508     }
509     }
510    
511    
512 greg 2.27 static void
513 greg 2.9 oputN(r) /* print unperturbed normal */
514 greg 2.29 RAY *r;
515 greg 1.1 {
516     if (r->rot < FHUGE) {
517     (*putreal)(r->ron[0]);
518     (*putreal)(r->ron[1]);
519     (*putreal)(r->ron[2]);
520     } else {
521     (*putreal)(0.0);
522     (*putreal)(0.0);
523     (*putreal)(0.0);
524     }
525 greg 2.9 }
526    
527    
528 greg 2.27 static void
529 greg 2.9 oputn(r) /* print perturbed normal */
530     RAY *r;
531     {
532     FVECT pnorm;
533    
534     if (r->rot >= FHUGE) {
535     (*putreal)(0.0);
536     (*putreal)(0.0);
537     (*putreal)(0.0);
538     return;
539     }
540     raynormal(pnorm, r);
541     (*putreal)(pnorm[0]);
542     (*putreal)(pnorm[1]);
543     (*putreal)(pnorm[2]);
544 greg 1.1 }
545    
546    
547 greg 2.27 static void
548 greg 1.1 oputs(r) /* print name */
549 greg 2.29 RAY *r;
550 greg 1.1 {
551     if (r->ro != NULL)
552     fputs(r->ro->oname, stdout);
553     else
554     putchar('*');
555     putchar('\t');
556     }
557    
558    
559 greg 2.27 static void
560 greg 1.1 oputw(r) /* print weight */
561 greg 2.29 RAY *r;
562 greg 1.1 {
563     (*putreal)(r->rweight);
564     }
565    
566    
567 greg 2.27 static void
568 greg 1.1 oputm(r) /* print modifier */
569 greg 2.29 RAY *r;
570 greg 1.1 {
571     if (r->ro != NULL)
572 greg 2.23 if (r->ro->omod != OVOID)
573     fputs(objptr(r->ro->omod)->oname, stdout);
574     else
575     fputs(VOIDID, stdout);
576 greg 1.1 else
577     putchar('*');
578     putchar('\t');
579     }
580    
581    
582 greg 2.27 static void
583 greg 1.1 puta(v) /* print ascii value */
584     double v;
585     {
586     printf("%e\t", v);
587     }
588    
589    
590 greg 2.27 static void
591 greg 1.1 putd(v) /* print binary double */
592     double v;
593     {
594 greg 1.8 fwrite((char *)&v, sizeof(v), 1, stdout);
595 greg 1.1 }
596    
597    
598 greg 2.27 static void
599 greg 1.1 putf(v) /* print binary float */
600     double v;
601     {
602     float f = v;
603    
604 greg 1.8 fwrite((char *)&f, sizeof(f), 1, stdout);
605 greg 1.1 }