ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rtrace.c
(Generate patch)

Comparing ray/src/rt/rtrace.c (file contents):
Revision 1.14 by greg, Tue May 21 17:41:23 1991 UTC vs.
Revision 2.105 by greg, Thu Feb 2 18:45:23 2023 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1986 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   *  rtrace.c - program and variables for individual ray tracing.
9 *
10 *     6/11/86
6   */
7  
8 + #include "copyright.h"
9 +
10   /*
11   *  Input is in the form:
12   *
# Line 24 | Line 21 | static char SCCSid[] = "$SunId$ LBL";
21   *  irradiance values are desired.
22   */
23  
24 < #include  "ray.h"
24 > #include  <time.h>
25  
26 < #include  "octree.h"
27 <
26 > #include  "platform.h"
27 > #include  "ray.h"
28 > #include  "ambient.h"
29 > #include  "source.h"
30   #include  "otypes.h"
31 + #include  "otspecial.h"
32 + #include  "resolu.h"
33 + #include  "random.h"
34  
35 < int  dimlist[MAXDIM];                   /* sampling dimensions */
36 < int  ndims = 0;                         /* number of sampling dimensions */
37 < int  samplendx = 0;                     /* index for this sample */
35 > extern int  inform;                     /* input format */
36 > extern int  outform;                    /* output format */
37 > extern char  *outvals;                  /* output values */
38  
39 < int  imm_irrad = 0;                     /* compute immediate irradiance? */
39 > extern int  imm_irrad;                  /* compute immediate irradiance? */
40 > extern int  lim_dist;                   /* limit distance? */
41  
42 < int  inform = 'a';                      /* input format */
43 < int  outform = 'a';                     /* output format */
41 < char  *outvals = "v";                   /* output specification */
42 > extern char  *tralist[];                /* list of modifers to trace (or no) */
43 > extern int  traincl;                    /* include == 1, exclude == 0 */
44  
45 < int  hresolu = 0;                       /* horizontal (scan) size */
46 < int  vresolu = 0;                       /* vertical resolution */
45 > extern int  hresolu;                    /* horizontal resolution */
46 > extern int  vresolu;                    /* vertical resolution */
47  
48 < double  dstrsrc = 0.0;                  /* square source distribution */
47 < double  shadthresh = .05;               /* shadow threshold */
48 < double  shadcert = .5;                  /* shadow certainty */
48 > extern int  castonly;                   /* only doing ray-casting? */
49  
50 < int  maxdepth = 6;                      /* maximum recursion depth */
51 < double  minweight = 4e-3;               /* minimum ray weight */
50 > #ifndef  MAXTSET
51 > #define  MAXTSET        8191            /* maximum number in trace set */
52 > #endif
53 > OBJECT  traset[MAXTSET+1]={0};          /* trace include/exclude set */
54  
55 < COLOR  ambval = BLKCOLOR;               /* ambient value */
54 < double  ambacc = 0.2;                   /* ambient accuracy */
55 < int  ambres = 32;                       /* ambient resolution */
56 < int  ambdiv = 128;                      /* ambient divisions */
57 < int  ambssamp = 0;                      /* ambient super-samples */
58 < int  ambounce = 0;                      /* ambient bounces */
59 < char  *amblist[128];                    /* ambient include/exclude list */
60 < int  ambincl = -1;                      /* include == 1, exclude == 0 */
55 > static int  Tflag = 0;                  /* source tracing enabled? */
56  
62 extern OBJREC  Lamb;                    /* a Lambertian surface */
63
57   static RAY  thisray;                    /* for our convenience */
58  
59 < static int  oputo(), oputd(), oputv(), oputl(),
67 <                oputp(), oputn(), oputs(), oputw(), oputm();
59 > static FILE  *inpfp = NULL;             /* input stream pointer */
60  
61 < static int  (*ray_out[10])(), (*every_out[10])();
62 < static int  castonly;
61 > static FVECT    *inp_queue = NULL;      /* ray input queue if flushing */
62 > static int      inp_qpos = 0;           /* next ray to return */
63 > static int      inp_qend = 0;           /* number of rays in this work group */
64  
65 < static int  puta(), putf(), putd();
65 > typedef void putf_t(RREAL *v, int n);
66 > static putf_t puta, putd, putf, putrgbe;
67  
68 < static int  (*putreal)();
68 > typedef void oputf_t(RAY *r);
69 > static oputf_t  oputo, oputd, oputv, oputV, oputl, oputL, oputc, oputp,
70 >                oputr, oputR, oputx, oputX, oputn, oputN, oputs,
71 >                oputw, oputW, oputm, oputM, oputtilde;
72  
73 + extern void tranotify(OBJECT obj);
74 + static int is_fifo(FILE *fp);
75 + static void bogusray(void);
76 + static void raycast(RAY *r);
77 + static void rayirrad(RAY *r);
78 + static void rtcompute(FVECT org, FVECT dir, double dmax);
79 + static int printvals(RAY *r);
80 + static int getvec(FVECT vec, int fmt, FILE *fp);
81 + static int iszerovec(const FVECT vec);
82 + static double nextray(FVECT org, FVECT dir);
83 + static void tabin(RAY *r);
84 + static void ourtrace(RAY *r);
85  
86 < quit(code)                      /* quit program */
87 < int  code;
86 > static oputf_t *ray_out[32], *every_out[32];
87 > static putf_t *putreal;
88 >
89 >
90 > void
91 > quit(                   /* quit program */
92 >        int  code
93 > )
94   {
95 +        if (ray_pnprocs > 0)    /* close children if any */
96 +                ray_pclose(0);          
97 +        else if (ray_pnprocs < 0)
98 +                _exit(code);    /* avoid flush() in child */
99 + #ifndef  NON_POSIX
100 +        else {
101 +                headclean();    /* delete header file */
102 +                pfclean();      /* clean up persist files */
103 +        }
104 + #endif
105          exit(code);
106   }
107  
108  
109 < rtrace(fname)                           /* trace rays from file */
110 < char  *fname;
109 > char *
110 > formstr(                                /* return format identifier */
111 >        int  f
112 > )
113   {
114 <        long  vcount = hresolu>1 ? hresolu*vresolu : vresolu;
115 <        long  nextflush = hresolu;
114 >        switch (f) {
115 >        case 'a': return("ascii");
116 >        case 'f': return("float");
117 >        case 'd': return("double");
118 >        case 'c': return(COLRFMT);
119 >        }
120 >        return("unknown");
121 > }
122 >
123 >
124 > static void
125 > trace_sources(void)                     /* trace rays to light sources, also */
126 > {
127 >        int     sn;
128 >
129 >        for (sn = 0; sn < nsources; sn++)
130 >                source[sn].sflags |= SFOLLOW;
131 > }
132 >
133 >
134 > void
135 > rtrace(                         /* trace rays from file */
136 >        char  *fname,
137 >        int  nproc
138 > )
139 > {
140 >        unsigned long  vcount = (hresolu > 1) ? (unsigned long)hresolu*vresolu
141 >                                              : (unsigned long)vresolu;
142 >        long  nextflush = (!vresolu | (hresolu <= 1)) * hresolu;
143 >        int  something2flush = 0;
144          FILE  *fp;
145 +        double  d;
146          FVECT  orig, direc;
147                                          /* set up input */
148          if (fname == NULL)
149 <                fp = stdin;
150 <        else if ((fp = fopen(fname, "r")) == NULL) {
149 >                inpfp = stdin;
150 >        else if ((inpfp = fopen(fname, "r")) == NULL) {
151                  sprintf(errmsg, "cannot open input file \"%s\"", fname);
152                  error(SYSTEM, errmsg);
153          }
154 + #ifdef getc_unlocked
155 +        flockfile(inpfp);               /* avoid lock/unlock overhead */
156 +        flockfile(stdout);
157 + #endif
158 +        if (inform != 'a')
159 +                SET_FILE_BINARY(inpfp);
160                                          /* set up output */
161 <        setoutput(outvals);
162 <        switch (outform) {
163 <        case 'a': putreal = puta; break;
164 <        case 'f': putreal = putf; break;
165 <        case 'd': putreal = putd; break;
161 >        if (castonly || every_out[0] != NULL)
162 >                nproc = 1;              /* don't bother multiprocessing */
163 >        if (every_out[0] != NULL) {
164 >                trace = ourtrace;       /* enable full tree tracing */
165 >                if (Tflag)              /* light sources, too? */
166 >                        trace_sources();
167          }
168 <                                        /* process file */
169 <        while (getvec(orig, inform, fp) == 0 &&
170 <                        getvec(direc, inform, fp) == 0) {
171 <
172 <                if (normalize(direc) == 0.0) {          /* zero ==> flush */
173 <                        fflush(stdout);
174 <                        continue;
175 <                }
176 <                samplendx++;
177 <                                                        /* compute and print */
178 <                if (imm_irrad)
116 <                        irrad(orig, direc);
168 >        if ((nextflush > 0) & (nproc > nextflush)) {
169 >                error(WARNING, "reducing number of processes to match flush interval");
170 >                nproc = nextflush;
171 >        }
172 >        if (nproc > 1) {                /* start multiprocessing */
173 >                ray_popen(nproc);
174 >                ray_fifo_out = printvals;
175 >        }
176 >        if (hresolu > 0) {
177 >                if (vresolu > 0)
178 >                        fprtresolu(hresolu, vresolu, stdout);
179                  else
118                        traceray(orig, direc);
119                                                        /* flush if time */
120                if (--nextflush == 0) {
180                          fflush(stdout);
181 <                        nextflush = hresolu;
181 >        }
182 >                                        /* process input rays */
183 >        while ((d = nextray(orig, direc)) >= 0.0) {
184 >                if (d == 0.0) {                         /* flush request? */
185 >                        if (something2flush) {
186 >                                if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
187 >                                        error(USER, "child(ren) died");
188 >                                bogusray();
189 >                                fflush(stdout);
190 >                                nextflush = (!vresolu | (hresolu <= 1)) * hresolu;
191 >                                something2flush = 0;
192 >                        } else
193 >                                bogusray();
194 >                } else {                                /* compute and print */
195 >                        rtcompute(orig, direc, lim_dist ? d : 0.0);
196 >                        if (!--nextflush) {             /* flush if time */
197 >                                if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
198 >                                        error(USER, "child(ren) died");
199 >                                fflush(stdout);
200 >                                nextflush = hresolu;
201 >                        } else
202 >                                something2flush = 1;
203                  }
204                  if (ferror(stdout))
205                          error(SYSTEM, "write error");
206 <                if (--vcount == 0)                      /* check for end */
206 >                if (vcount && !--vcount)                /* check for end */
207                          break;
208          }
209 <        if (vcount > 0)
210 <                error(USER, "read error");
211 <        fclose(fp);
209 >        if (ray_pnprocs > 1) {                          /* clean up children */
210 >                if (ray_fifo_flush() < 0)
211 >                        error(USER, "unable to complete processing");
212 >                ray_pclose(0);
213 >        }
214 >        if (vcount)
215 >                error(WARNING, "unexpected EOF on input");
216 >        if (fflush(stdout) < 0)
217 >                error(SYSTEM, "write error");
218 >        if (fname != NULL) {
219 >                fclose(inpfp);
220 >                inpfp = NULL;
221 >        }
222 >        nextray(NULL, NULL);
223   }
224  
225  
226 < setoutput(vs)                           /* set up output tables */
227 < register char  *vs;
226 > int
227 > setrtoutput(void)                       /* set up output tables, return #comp */
228   {
229 <        extern int  ourtrace(), (*trace)();
230 <        register int (**table)() = ray_out;
229 >        char  *vs = outvals;
230 >        oputf_t **table = ray_out;
231 >        int  ncomp = 0;
232  
233 <        castonly = 1;
234 <        while (*vs)
235 <                switch (*vs++) {
233 >        if (!*vs)
234 >                error(USER, "empty output specification");
235 >
236 >        switch (outform) {      /* make sure (*putreal)() calls someone! */
237 >        case 'a': putreal = puta; break;
238 >        case 'f': putreal = putf; break;
239 >        case 'd': putreal = putd; break;
240 >        case 'c':
241 >                if (outvals[1] || !strchr("vrx", outvals[0]))
242 >                        error(USER, "color format only with -ov, -or, -ox");
243 >                putreal = putrgbe; break;
244 >        default:
245 >                error(CONSISTENCY, "botched output format");
246 >        }
247 >        castonly = 1;                   /* sets castonly as side-effect */
248 >        do
249 >                switch (*vs) {
250 >                case 'T':                               /* trace sources */
251 >                        Tflag++;
252 >                        /* fall through */
253                  case 't':                               /* trace */
254 +                        if (!vs[1]) break;
255                          *table = NULL;
256                          table = every_out;
147                        trace = ourtrace;
257                          castonly = 0;
258                          break;
259                  case 'o':                               /* origin */
260                          *table++ = oputo;
261 +                        ncomp += 3;
262                          break;
263                  case 'd':                               /* direction */
264                          *table++ = oputd;
265 +                        ncomp += 3;
266                          break;
267 +                case 'r':                               /* reflected contrib. */
268 +                        *table++ = oputr;
269 +                        ncomp += 3;
270 +                        castonly = 0;
271 +                        break;
272 +                case 'R':                               /* reflected distance */
273 +                        *table++ = oputR;
274 +                        ncomp++;
275 +                        castonly = 0;
276 +                        break;
277 +                case 'x':                               /* xmit contrib. */
278 +                        *table++ = oputx;
279 +                        ncomp += 3;
280 +                        castonly = 0;
281 +                        break;
282 +                case 'X':                               /* xmit distance */
283 +                        *table++ = oputX;
284 +                        ncomp++;
285 +                        castonly = 0;
286 +                        break;
287                  case 'v':                               /* value */
288                          *table++ = oputv;
289 +                        ncomp += 3;
290                          castonly = 0;
291                          break;
292 <                case 'l':                               /* length */
292 >                case 'V':                               /* contribution */
293 >                        *table++ = oputV;
294 >                        ncomp += 3;
295 >                        castonly = 0;
296 >                        if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
297 >                                error(WARNING,
298 >                                        "-otV accuracy depends on -aa 0 -as 0");
299 >                        break;
300 >                case 'l':                               /* effective distance */
301                          *table++ = oputl;
302 +                        ncomp++;
303                          castonly = 0;
304                          break;
305 +                case 'c':                               /* local coordinates */
306 +                        *table++ = oputc;
307 +                        ncomp += 2;
308 +                        break;
309 +                case 'L':                               /* single ray length */
310 +                        *table++ = oputL;
311 +                        ncomp++;
312 +                        break;
313                  case 'p':                               /* point */
314                          *table++ = oputp;
315 +                        ncomp += 3;
316                          break;
317 <                case 'n':                               /* normal */
317 >                case 'n':                               /* perturbed normal */
318                          *table++ = oputn;
319 +                        ncomp += 3;
320 +                        castonly = 0;
321                          break;
322 +                case 'N':                               /* unperturbed normal */
323 +                        *table++ = oputN;
324 +                        ncomp += 3;
325 +                        break;
326                  case 's':                               /* surface */
327                          *table++ = oputs;
328 +                        ncomp++;
329                          break;
330                  case 'w':                               /* weight */
331                          *table++ = oputw;
332 +                        ncomp++;
333                          break;
334 +                case 'W':                               /* coefficient */
335 +                        *table++ = oputW;
336 +                        ncomp += 3;
337 +                        castonly = 0;
338 +                        if (ambounce > 0 && (ambacc > FTINY) | (ambssamp > 0))
339 +                                error(WARNING,
340 +                                        "-otW accuracy depends on -aa 0 -as 0");
341 +                        break;
342                  case 'm':                               /* modifier */
343                          *table++ = oputm;
344 +                        ncomp++;
345                          break;
346 +                case 'M':                               /* material */
347 +                        *table++ = oputM;
348 +                        ncomp++;
349 +                        break;
350 +                case '~':                               /* tilde */
351 +                        *table++ = oputtilde;
352 +                        break;
353 +                default:
354 +                        sprintf(errmsg, "unrecognized output option '%c'", *vs);
355 +                        error(USER, errmsg);
356                  }
357 +        while (*++vs);
358 +
359          *table = NULL;
360 +        if (*every_out != NULL)
361 +                ncomp = 0;
362 +                                                        /* compatibility */
363 +        if ((do_irrad | imm_irrad) && castonly)
364 +                error(USER, "-I+ and -i+ options require some value output");
365 +        for (table = ray_out; *table != NULL; table++) {
366 +                if ((*table == oputV) | (*table == oputW))
367 +                        error(WARNING, "-oVW options require trace mode");
368 +                if ((do_irrad | imm_irrad) &&
369 +                                (*table == oputr) | (*table == oputR) |
370 +                                (*table == oputx) | (*table == oputX))
371 +                        error(WARNING, "-orRxX options incompatible with -I+ and -i+");
372 +        }
373 +        return(ncomp);
374   }
375  
376  
377 < traceray(org, dir)              /* compute and print ray value(s) */
378 < FVECT  org, dir;
377 > static void
378 > bogusray(void)                  /* print out empty record */
379   {
380 <        register int  (**tp)();
380 >        rayorigin(&thisray, PRIMARY, NULL, NULL);
381 >        printvals(&thisray);
382 > }
383  
189        VCOPY(thisray.rorg, org);
190        VCOPY(thisray.rdir, dir);
191        rayorigin(&thisray, NULL, PRIMARY, 1.0);
192        if (castonly)
193                localhit(&thisray, &thescene) || sourcehit(&thisray);
194        else
195                rayvalue(&thisray);
384  
385 <        if (ray_out[0] == NULL)
385 > static void
386 > raycast(                        /* compute first ray intersection only */
387 >        RAY *r
388 > )
389 > {
390 >        if (!localhit(r, &thescene)) {
391 >                if (r->ro == &Aftplane) {       /* clipped */
392 >                        r->ro = NULL;
393 >                        r->rot = FHUGE;
394 >                } else
395 >                        sourcehit(r);
396 >        }
397 > }
398 >
399 >
400 > static void
401 > rayirrad(                       /* compute irradiance rather than radiance */
402 >        RAY *r
403 > )
404 > {
405 >        void    (*old_revf)(RAY *) = r->revf;
406 >                                        /* pretend we hit surface */
407 >        r->rxt = r->rot = 1e-5;
408 >        VSUM(r->rop, r->rorg, r->rdir, r->rot);
409 >        r->ron[0] = -r->rdir[0];
410 >        r->ron[1] = -r->rdir[1];
411 >        r->ron[2] = -r->rdir[2];
412 >        r->rod = 1.0;
413 >                                        /* compute result */
414 >        r->revf = raytrace;
415 >        (*ofun[Lamb.otype].funp)(&Lamb, r);
416 >        r->revf = old_revf;
417 > }
418 >
419 >
420 > static void
421 > rtcompute(                      /* compute and print ray value(s) */
422 >        FVECT  org,
423 >        FVECT  dir,
424 >        double  dmax
425 > )
426 > {
427 >                                        /* set up ray */
428 >        if (imm_irrad) {
429 >                VSUM(thisray.rorg, org, dir, 1.1e-4);
430 >                thisray.rdir[0] = -dir[0];
431 >                thisray.rdir[1] = -dir[1];
432 >                thisray.rdir[2] = -dir[2];
433 >                thisray.rmax = 0.0;
434 >        } else {
435 >                VCOPY(thisray.rorg, org);
436 >                VCOPY(thisray.rdir, dir);
437 >                thisray.rmax = dmax;
438 >        }
439 >        rayorigin(&thisray, PRIMARY, NULL, NULL);
440 >        if (imm_irrad)
441 >                thisray.revf = rayirrad;
442 >        else if (castonly)
443 >                thisray.revf = raycast;
444 >        if (ray_pnprocs > 1) {          /* multiprocessing FIFO? */
445 >                if (ray_fifo_in(&thisray) < 0)
446 >                        error(USER, "lost children");
447                  return;
448 +        }
449 +        samplendx++;                    /* else do it ourselves */
450 +        rayvalue(&thisray);
451 +        printvals(&thisray);
452 + }
453 +
454 +
455 + static int
456 + printvals(                      /* print requested ray values */
457 +        RAY  *r
458 + )
459 + {
460 +        oputf_t **tp;
461 +
462 +        if (ray_out[0] == NULL)
463 +                return(0);
464          for (tp = ray_out; *tp != NULL; tp++)
465 <                (**tp)(&thisray);
465 >                (**tp)(r);
466          if (outform == 'a')
467                  putchar('\n');
468 +        return(1);
469   }
470  
471  
472 < irrad(org, dir)                 /* compute immediate irradiance value */
473 < FVECT  org, dir;
472 > static int
473 > is_fifo(                /* check if file pointer connected to pipe */
474 >        FILE *fp
475 > )
476   {
477 <        register int  i;
477 > #ifdef S_ISFIFO
478 >        struct stat  sbuf;
479  
480 <        for (i = 0; i < 3; i++) {
481 <                thisray.rorg[i] = org[i] + dir[i];
482 <                thisray.rdir[i] = -dir[i];
483 <        }
484 <        rayorigin(&thisray, NULL, PRIMARY, 1.0);
485 <                                        /* pretend we hit surface */
217 <        thisray.rot = 1.0;
218 <        thisray.rod = 1.0;
219 <        VCOPY(thisray.ron, dir);
220 <        for (i = 0; i < 3; i++)         /* fudge factor */
221 <                thisray.rop[i] = org[i] + 1e-4*dir[i];
222 <                                        /* compute and print */
223 <        (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
224 <        oputv(&thisray);
225 <        if (outform == 'a')
226 <                putchar('\n');
480 >        if (fstat(fileno(fp), &sbuf) < 0)
481 >                error(SYSTEM, "fstat() failed on input stream");
482 >        return(S_ISFIFO(sbuf.st_mode));
483 > #else
484 >        return (fp == stdin);           /* just a guess, really */
485 > #endif
486   }
487  
488  
489 < getvec(vec, fmt, fp)            /* get a vector from fp */
490 < register FVECT  vec;
491 < int  fmt;
492 < FILE  *fp;
489 > static int
490 > getvec(                 /* get a vector from fp */
491 >        FVECT  vec,
492 >        int  fmt,
493 >        FILE  *fp
494 > )
495   {
496          static float  vf[3];
497 +        static double  vd[3];
498 +        char  buf[32];
499 +        int  i;
500  
501          switch (fmt) {
502          case 'a':                                       /* ascii */
503 <                if (fscanf(fp, "%lf %lf %lf", vec, vec+1, vec+2) != 3)
504 <                        return(-1);
503 >                for (i = 0; i < 3; i++) {
504 >                        if (fgetword(buf, sizeof(buf), fp) == NULL ||
505 >                                        !isflt(buf))
506 >                                return(-1);
507 >                        vec[i] = atof(buf);
508 >                }
509                  break;
510          case 'f':                                       /* binary float */
511 <                if (fread((char *)vf, sizeof(float), 3, fp) != 3)
511 >                if (getbinary(vf, sizeof(float), 3, fp) != 3)
512                          return(-1);
513 <                vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
513 >                VCOPY(vec, vf);
514                  break;
515          case 'd':                                       /* binary double */
516 <                if (fread((char *)vec, sizeof(double), 3, fp) != 3)
516 >                if (getbinary(vd, sizeof(double), 3, fp) != 3)
517                          return(-1);
518 +                VCOPY(vec, vd);
519                  break;
520 +        default:
521 +                error(CONSISTENCY, "botched input format");
522          }
523          return(0);
524   }
525  
526  
527 < static
528 < ourtrace(r)                             /* print ray values */
258 < RAY  *r;
527 > static int
528 > iszerovec(const FVECT vec)
529   {
530 <        register int  (**tp)();
530 >        return (vec[0] == 0.0) & (vec[1] == 0.0) & (vec[2] == 0.0);
531 > }
532  
533 +
534 + static double
535 + nextray(                /* return next ray in work group (-1.0 if EOF) */
536 +        FVECT org,
537 +        FVECT dir
538 + )
539 + {
540 +        const size_t    qlength = !vresolu * hresolu;
541 +
542 +        if ((org == NULL) | (dir == NULL)) {
543 +                if (inp_queue != NULL)  /* asking to free queue */
544 +                        free(inp_queue);
545 +                inp_queue = NULL;
546 +                inp_qpos = inp_qend = 0;
547 +                return(-1.);
548 +        }
549 +        if (!inp_qend) {                /* initialize FIFO queue */
550 +                int     rsiz = 6*20;    /* conservative ascii ray size */
551 +                if (inform == 'f') rsiz = 6*sizeof(float);
552 +                else if (inform == 'd') rsiz = 6*sizeof(double);
553 +                                        /* check against pipe limit */
554 +                if (qlength*rsiz > 512 && is_fifo(inpfp))
555 +                        inp_queue = (FVECT *)malloc(sizeof(FVECT)*2*qlength);
556 +                inp_qend = -(inp_queue == NULL);        /* flag for no queue */
557 +        }
558 +        if (inp_qend < 0) {             /* not queuing? */
559 +                if (getvec(org, inform, inpfp) < 0 ||
560 +                                getvec(dir, inform, inpfp) < 0)
561 +                        return(-1.);
562 +                return normalize(dir);
563 +        }
564 +        if (inp_qpos >= inp_qend) {     /* need to refill input queue? */
565 +                for (inp_qend = 0; inp_qend < qlength; inp_qend++) {
566 +                        if (getvec(inp_queue[2*inp_qend], inform, inpfp) < 0
567 +                                        || getvec(inp_queue[2*inp_qend+1],
568 +                                                        inform, inpfp) < 0)
569 +                                break;          /* hit EOF */
570 +                        if (iszerovec(inp_queue[2*inp_qend+1])) {
571 +                                ++inp_qend;     /* flush request */
572 +                                break;
573 +                        }
574 +                }
575 +                inp_qpos = 0;
576 +        }
577 +        if (inp_qpos >= inp_qend)       /* unexpected EOF? */
578 +                return(-1.);
579 +        VCOPY(org, inp_queue[2*inp_qpos]);
580 +        VCOPY(dir, inp_queue[2*inp_qpos+1]);
581 +        ++inp_qpos;
582 +        return normalize(dir);
583 + }
584 +
585 +
586 + void
587 + tranotify(                      /* record new modifier */
588 +        OBJECT  obj
589 + )
590 + {
591 +        static int  hitlimit = 0;
592 +        OBJREC   *o = objptr(obj);
593 +        char  **tralp;
594 +
595 +        if (obj == OVOID) {             /* starting over */
596 +                traset[0] = 0;
597 +                hitlimit = 0;
598 +                return;
599 +        }
600 +        if (hitlimit || !ismodifier(o->otype))
601 +                return;
602 +        for (tralp = tralist; *tralp != NULL; tralp++)
603 +                if (!strcmp(o->oname, *tralp)) {
604 +                        if (traset[0] >= MAXTSET) {
605 +                                error(WARNING, "too many modifiers in trace list");
606 +                                hitlimit++;
607 +                                return;         /* should this be fatal? */
608 +                        }
609 +                        insertelem(traset, obj);
610 +                        return;
611 +                }
612 + }
613 +
614 +
615 + static void
616 + ourtrace(                               /* print ray values */
617 +        RAY  *r
618 + )
619 + {
620 +        oputf_t **tp;
621 +
622          if (every_out[0] == NULL)
623                  return;
624 +        if (r->ro == NULL) {
625 +                if (traincl == 1)
626 +                        return;
627 +        } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
628 +                return;
629          tabin(r);
630          for (tp = every_out; *tp != NULL; tp++)
631                  (**tp)(r);
632 <        putchar('\n');
632 >        if (outform == 'a')
633 >                putchar('\n');
634   }
635  
636  
637 < static
638 < tabin(r)                                /* tab in appropriate amount */
639 < RAY  *r;
637 > static void
638 > tabin(                          /* tab in appropriate amount */
639 >        RAY  *r
640 > )
641   {
642 <        register RAY  *rp;
642 >        const RAY  *rp;
643  
644          for (rp = r->parent; rp != NULL; rp = rp->parent)
645                  putchar('\t');
646   }
647  
648  
649 < static
650 < oputo(r)                                /* print origin */
651 < register RAY  *r;
649 > static void
650 > oputo(                          /* print origin */
651 >        RAY  *r
652 > )
653   {
654 <        (*putreal)(r->rorg[0]);
287 <        (*putreal)(r->rorg[1]);
288 <        (*putreal)(r->rorg[2]);
654 >        (*putreal)(r->rorg, 3);
655   }
656  
657  
658 < static
659 < oputd(r)                                /* print direction */
660 < register RAY  *r;
658 > static void
659 > oputd(                          /* print direction */
660 >        RAY  *r
661 > )
662   {
663 <        (*putreal)(r->rdir[0]);
297 <        (*putreal)(r->rdir[1]);
298 <        (*putreal)(r->rdir[2]);
663 >        (*putreal)(r->rdir, 3);
664   }
665  
666  
667 < static
668 < oputv(r)                                /* print value */
669 < register RAY  *r;
667 > static void
668 > oputr(                          /* print mirrored contribution */
669 >        RAY  *r
670 > )
671   {
672 <        (*putreal)(colval(r->rcol,RED));
673 <        (*putreal)(colval(r->rcol,GRN));
674 <        (*putreal)(colval(r->rcol,BLU));
672 >        RREAL   cval[3];
673 >
674 >        cval[0] = colval(r->mcol,RED);
675 >        cval[1] = colval(r->mcol,GRN);
676 >        cval[2] = colval(r->mcol,BLU);
677 >        (*putreal)(cval, 3);
678   }
679  
680  
681 < static
682 < oputl(r)                                /* print length */
683 < register RAY  *r;
681 >
682 > static void
683 > oputR(                          /* print mirrored distance */
684 >        RAY  *r
685 > )
686   {
687 <        (*putreal)(r->rt);
687 >        (*putreal)(&r->rmt, 1);
688   }
689  
690  
691 < static
692 < oputp(r)                                /* print point */
693 < register RAY  *r;
691 > static void
692 > oputx(                          /* print unmirrored contribution */
693 >        RAY  *r
694 > )
695   {
696 <        if (r->rot < FHUGE) {
697 <                (*putreal)(r->rop[0]);
698 <                (*putreal)(r->rop[1]);
699 <                (*putreal)(r->rop[2]);
700 <        } else {
701 <                (*putreal)(0.0);
702 <                (*putreal)(0.0);
703 <                (*putreal)(0.0);
696 >        RREAL   cval[3];
697 >
698 >        cval[0] = colval(r->rcol,RED) - colval(r->mcol,RED);
699 >        cval[1] = colval(r->rcol,GRN) - colval(r->mcol,GRN);
700 >        cval[2] = colval(r->rcol,BLU) - colval(r->mcol,BLU);
701 >        (*putreal)(cval, 3);
702 > }
703 >
704 >
705 > static void
706 > oputX(                          /* print unmirrored distance */
707 >        RAY  *r
708 > )
709 > {
710 >        (*putreal)(&r->rxt, 1);
711 > }
712 >
713 >
714 > static void
715 > oputv(                          /* print value */
716 >        RAY  *r
717 > )
718 > {
719 >        RREAL   cval[3];
720 >
721 >        cval[0] = colval(r->rcol,RED);
722 >        cval[1] = colval(r->rcol,GRN);
723 >        cval[2] = colval(r->rcol,BLU);
724 >        (*putreal)(cval, 3);
725 > }
726 >
727 >
728 > static void
729 > oputV(                          /* print value contribution */
730 >        RAY *r
731 > )
732 > {
733 >        RREAL   contr[3];
734 >
735 >        raycontrib(contr, r, PRIMARY);
736 >        multcolor(contr, r->rcol);
737 >        (*putreal)(contr, 3);
738 > }
739 >
740 >
741 > static void
742 > oputl(                          /* print effective distance */
743 >        RAY  *r
744 > )
745 > {
746 >        RREAL   d = raydistance(r);
747 >
748 >        (*putreal)(&d, 1);
749 > }
750 >
751 >
752 > static void
753 > oputL(                          /* print single ray length */
754 >        RAY  *r
755 > )
756 > {
757 >        (*putreal)(&r->rot, 1);
758 > }
759 >
760 >
761 > static void
762 > oputc(                          /* print local coordinates */
763 >        RAY  *r
764 > )
765 > {
766 >        (*putreal)(r->uv, 2);
767 > }
768 >
769 >
770 > static RREAL    vdummy[3] = {0.0, 0.0, 0.0};
771 >
772 >
773 > static void
774 > oputp(                          /* print intersection point */
775 >        RAY  *r
776 > )
777 > {
778 >        (*putreal)(r->rop, 3);  /* set to ray origin if distant or no hit */
779 > }
780 >
781 >
782 > static void
783 > oputN(                          /* print unperturbed normal */
784 >        RAY  *r
785 > )
786 > {
787 >        if (r->ro == NULL) {    /* zero vector if clipped or no hit */
788 >                (*putreal)(vdummy, 3);
789 >                return;
790          }
791 +        if (r->rflips & 1) {    /* undo any flippin' flips */
792 +                FVECT   unrm;
793 +                unrm[0] = -r->ron[0];
794 +                unrm[1] = -r->ron[1];
795 +                unrm[2] = -r->ron[2];
796 +                (*putreal)(unrm, 3);
797 +        } else
798 +                (*putreal)(r->ron, 3);
799   }
800  
801  
802 < static
803 < oputn(r)                                /* print normal */
804 < register RAY  *r;
802 > static void
803 > oputn(                          /* print perturbed normal */
804 >        RAY  *r
805 > )
806   {
807 <        if (r->rot < FHUGE) {
808 <                (*putreal)(r->ron[0]);
809 <                (*putreal)(r->ron[1]);
810 <                (*putreal)(r->ron[2]);
811 <        } else {
345 <                (*putreal)(0.0);
346 <                (*putreal)(0.0);
347 <                (*putreal)(0.0);
807 >        FVECT  pnorm;
808 >
809 >        if (r->ro == NULL) {    /* clipped or no hit */
810 >                (*putreal)(vdummy, 3);
811 >                return;
812          }
813 +        raynormal(pnorm, r);
814 +        (*putreal)(pnorm, 3);
815   }
816  
817  
818 < static
819 < oputs(r)                                /* print name */
820 < register RAY  *r;
818 > static void
819 > oputs(                          /* print name */
820 >        RAY  *r
821 > )
822   {
823          if (r->ro != NULL)
824                  fputs(r->ro->oname, stdout);
# Line 361 | Line 828 | register RAY  *r;
828   }
829  
830  
831 < static
832 < oputw(r)                                /* print weight */
833 < register RAY  *r;
831 > static void
832 > oputw(                          /* print weight */
833 >        RAY  *r
834 > )
835   {
836 <        (*putreal)(r->rweight);
836 >        RREAL   rwt = r->rweight;
837 >        
838 >        (*putreal)(&rwt, 1);
839   }
840  
841  
842 < static
843 < oputm(r)                                /* print modifier */
844 < register RAY  *r;
842 > static void
843 > oputW(                          /* print coefficient */
844 >        RAY  *r
845 > )
846   {
847 +        RREAL   contr[3];
848 +                                /* shadow ray not on source? */
849 +        if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
850 +                setcolor(contr, 0.0, 0.0, 0.0);
851 +        else
852 +                raycontrib(contr, r, PRIMARY);
853 +
854 +        (*putreal)(contr, 3);
855 + }
856 +
857 +
858 + static void
859 + oputm(                          /* print modifier */
860 +        RAY  *r
861 + )
862 + {
863          if (r->ro != NULL)
864 <                fputs(objptr(r->ro->omod)->oname, stdout);
864 >                if (r->ro->omod != OVOID)
865 >                        fputs(objptr(r->ro->omod)->oname, stdout);
866 >                else
867 >                        fputs(VOIDID, stdout);
868          else
869                  putchar('*');
870          putchar('\t');
871   }
872  
873  
874 < static
875 < puta(v)                         /* print ascii value */
876 < double  v;
874 > static void
875 > oputM(                          /* print material */
876 >        RAY  *r
877 > )
878   {
879 <        printf("%e\t", v);
879 >        OBJREC  *mat;
880 >
881 >        if (r->ro != NULL) {
882 >                if ((mat = findmaterial(r->ro)) != NULL)
883 >                        fputs(mat->oname, stdout);
884 >                else
885 >                        fputs(VOIDID, stdout);
886 >        } else
887 >                putchar('*');
888 >        putchar('\t');
889   }
890  
891  
892 < static
893 < putd(v)                         /* print binary double */
894 < double  v;
892 > static void
893 > oputtilde(                      /* output tilde (spacer) */
894 >        RAY  *r
895 > )
896   {
897 <        fwrite((char *)&v, sizeof(v), 1, stdout);
897 >        fputs("~\t", stdout);
898   }
899  
900  
901 < static
902 < putf(v)                         /* print binary float */
903 < double  v;
901 > static void
902 > puta(                           /* print ascii value(s) */
903 >        RREAL *v, int n
904 > )
905   {
906 <        float f = v;
906 >        if (n == 3) {
907 >                printf("%e\t%e\t%e\t", v[0], v[1], v[2]);
908 >                return;
909 >        }
910 >        while (n--)
911 >                printf("%e\t", *v++);
912 > }
913  
914 <        fwrite((char *)&f, sizeof(f), 1, stdout);
914 >
915 > static void
916 > putd(RREAL *v, int n)           /* output binary double(s) */
917 > {
918 > #ifdef  SMLFLT
919 >        double  da[3];
920 >        int     i;
921 >
922 >        if (n > 3)
923 >                error(INTERNAL, "code error in putd()");
924 >        for (i = n; i--; )
925 >                da[i] = v[i];
926 >        putbinary(da, sizeof(double), n, stdout);
927 > #else
928 >        putbinary(v, sizeof(RREAL), n, stdout);
929 > #endif
930 > }
931 >
932 >
933 > static void
934 > putf(RREAL *v, int n)           /* output binary float(s) */
935 > {
936 > #ifndef SMLFLT
937 >        float   fa[3];
938 >        int     i;
939 >
940 >        if (n > 3)
941 >                error(INTERNAL, "code error in putf()");
942 >        for (i = n; i--; )
943 >                fa[i] = v[i];
944 >        putbinary(fa, sizeof(float), n, stdout);
945 > #else
946 >        putbinary(v, sizeof(RREAL), n, stdout);
947 > #endif
948 > }
949 >
950 >
951 > static void
952 > putrgbe(RREAL *v, int n)        /* output RGBE color */
953 > {
954 >        COLR  cout;
955 >
956 >        if (n != 3)
957 >                error(INTERNAL, "putrgbe() not called with 3 components");
958 >        setcolr(cout, v[0], v[1], v[2]);
959 >        putbinary(cout, sizeof(cout), 1, stdout);
960   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines