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 2.57 by greg, Sat Dec 12 19:01:00 2009 UTC vs.
Revision 2.105 by greg, Thu Feb 2 18:45:23 2023 UTC

# Line 28 | Line 28 | static const char      RCSid[] = "$Id$";
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  
# Line 44 | Line 45 | extern int  traincl;                   /* include == 1, exclude == 0 *
45   extern int  hresolu;                    /* horizontal resolution */
46   extern int  vresolu;                    /* vertical resolution */
47  
48 < static int  castonly = 0;
48 > extern int  castonly;                   /* only doing ray-casting? */
49  
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 + static int  Tflag = 0;                  /* source tracing enabled? */
56 +
57   static RAY  thisray;                    /* for our convenience */
58  
59 < typedef void putf_t(double v);
57 < static putf_t puta, putd, putf;
59 > static FILE  *inpfp = NULL;             /* input stream pointer */
60  
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 + typedef void putf_t(RREAL *v, int n);
66 + static putf_t puta, putd, putf, putrgbe;
67 +
68   typedef void oputf_t(RAY *r);
69   static oputf_t  oputo, oputd, oputv, oputV, oputl, oputL, oputc, oputp,
70 <                oputn, oputN, oputs, oputw, oputW, oputm, oputM, oputtilde;
70 >                oputr, oputR, oputx, oputX, oputn, oputN, oputs,
71 >                oputw, oputW, oputm, oputM, oputtilde;
72  
63 static void setoutput(char *vs);
73   extern void tranotify(OBJECT obj);
74 + static int is_fifo(FILE *fp);
75   static void bogusray(void);
76 < static void rad(FVECT org, FVECT dir, double dmax);
77 < static void irrad(FVECT org, FVECT dir);
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 < static oputf_t *ray_out[16], *every_out[16];
86 > static oputf_t *ray_out[32], *every_out[32];
87   static putf_t *putreal;
88  
89  
# Line 81 | Line 94 | quit(                  /* quit program */
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 <        headclean();            /* delete header file */
101 <        pfclean();              /* clean up persist files */
100 >        else {
101 >                headclean();    /* delete header file */
102 >                pfclean();      /* clean up persist files */
103 >        }
104   #endif
105          exit(code);
106   }
# Line 104 | Line 121 | formstr(                               /* return format identifier */
121   }
122  
123  
124 < extern void
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
136 >        char  *fname,
137 >        int  nproc
138   )
139   {
140          unsigned long  vcount = (hresolu > 1) ? (unsigned long)hresolu*vresolu
141 <                                              : vresolu;
142 <        long  nextflush = hresolu;
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(fp);
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;
166 <        case 'c':
134 <                if (strcmp(outvals, "v"))
135 <                        error(USER, "color format with value output only");
136 <                break;
137 <        default:
138 <                error(CONSISTENCY, "botched output format");
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 <        ray_fifo_out = printvals;
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 <                fflush(stdout);
179 >                else
180 >                        fflush(stdout);
181          }
182 <                                        /* process file */
183 <        while (getvec(orig, inform, fp) == 0 &&
184 <                        getvec(direc, inform, fp) == 0) {
185 <
186 <                d = normalize(direc);
187 <                if (d == 0.0) {                         /* zero ==> flush */
188 <                        if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
153 <                                error(USER, "lost children");
154 <                        bogusray();
155 <                        if (--nextflush <= 0 || !vcount) {
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 = hresolu;
191 <                        }
190 >                                nextflush = (!vresolu | (hresolu <= 1)) * hresolu;
191 >                                something2flush = 0;
192 >                        } else
193 >                                bogusray();
194                  } else {                                /* compute and print */
195 <                        if (imm_irrad)
196 <                                irrad(orig, direc);
162 <                        else
163 <                                rad(orig, direc, lim_dist ? d : 0.0);
164 <                                                        /* flush if time */
165 <                        if (!--nextflush) {
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, "lost children");
198 >                                        error(USER, "child(ren) died");
199                                  fflush(stdout);
200                                  nextflush = hresolu;
201 <                        }
201 >                        } else
202 >                                something2flush = 1;
203                  }
204                  if (ferror(stdout))
205                          error(SYSTEM, "write error");
206                  if (vcount && !--vcount)                /* check for end */
207                          break;
208          }
209 <        if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
210 <                error(USER, "unable to complete processing");
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 (vcount)
219 <                error(USER, "unexpected EOF on input");
220 <        if (fname != NULL)
221 <                fclose(fp);
218 >        if (fname != NULL) {
219 >                fclose(inpfp);
220 >                inpfp = NULL;
221 >        }
222 >        nextray(NULL, NULL);
223   }
224  
225  
226 < static void
227 < trace_sources(void)                     /* trace rays to light sources, also */
226 > int
227 > setrtoutput(void)                       /* set up output tables, return #comp */
228   {
229 <        int     sn;
192 <        
193 <        for (sn = 0; sn < nsources; sn++)
194 <                source[sn].sflags |= SFOLLOW;
195 < }
196 <
197 <
198 < static void
199 < setoutput(                              /* set up output tables */
200 <        char  *vs
201 < )
202 < {
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 <                        if (!*vs) break;
210 <                        trace_sources();
251 >                        Tflag++;
252                          /* fall through */
253                  case 't':                               /* trace */
254 <                        if (!*vs) break;
254 >                        if (!vs[1]) break;
255                          *table = NULL;
256                          table = every_out;
216                        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 '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':                               /* 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 <                        if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
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   static void
378   bogusray(void)                  /* print out empty record */
379   {
284        thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
285        thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
286        thisray.rmax = 0.0;
380          rayorigin(&thisray, PRIMARY, NULL, NULL);
381          printvals(&thisray);
382   }
383  
384  
385   static void
386 < rad(            /* compute and print ray value(s) */
387 <        FVECT  org,
295 <        FVECT  dir,
296 <        double  dmax
386 > raycast(                        /* compute first ray intersection only */
387 >        RAY *r
388   )
389   {
390 <        VCOPY(thisray.rorg, org);
391 <        VCOPY(thisray.rdir, dir);
392 <        thisray.rmax = dmax;
393 <        if (ray_pnprocs > 1) {
394 <                if (ray_fifo_in(&thisray) < 0)
395 <                        error(USER, "lost children");
305 <                return;
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          }
307        rayorigin(&thisray, PRIMARY, NULL, NULL);
308        if (castonly) {
309                if (!localhit(&thisray, &thescene)) {
310                        if (thisray.ro == &Aftplane) {  /* clipped */
311                                thisray.ro = NULL;
312                                thisray.rot = FHUGE;
313                        } else
314                                sourcehit(&thisray);
315                }
316        } else
317                ray_trace(&thisray);
318        printvals(&thisray);
397   }
398  
399  
400   static void
401 < irrad(                  /* compute immediate irradiance value */
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
423 >        FVECT  dir,
424 >        double  dmax
425   )
426   {
427 <        VSUM(thisray.rorg, org, dir, 1.1e-4);
428 <        thisray.rdir[0] = -dir[0];
429 <        thisray.rdir[1] = -dir[1];
430 <        thisray.rdir[2] = -dir[2];
431 <        thisray.rmax = 0.0;
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 <                                        /* pretend we hit surface */
441 <        thisray.rot = 1e-5;
442 <        thisray.rod = 1.0;
443 <        VCOPY(thisray.ron, dir);
444 <        VSUM(thisray.rop, org, dir, 1e-4);
445 <                                        /* compute and print */
446 <        (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
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  
# Line 360 | Line 470 | printvals(                     /* print requested ray values */
470  
471  
472   static int
473 < getvec(         /* get a vector from fp */
473 > is_fifo(                /* check if file pointer connected to pipe */
474 >        FILE *fp
475 > )
476 > {
477 > #ifdef S_ISFIFO
478 >        struct stat  sbuf;
479 >
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 > static int
490 > getvec(                 /* get a vector from fp */
491          FVECT  vec,
492          int  fmt,
493          FILE  *fp
# Line 381 | Line 508 | getvec(                /* get a vector from fp */
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 *)vd, sizeof(double), 3, fp) != 3)
516 >                if (getbinary(vd, sizeof(double), 3, fp) != 3)
517                          return(-1);
518 <                vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
518 >                VCOPY(vec, vd);
519                  break;
520          default:
521                  error(CONSISTENCY, "botched input format");
# Line 397 | Line 524 | getvec(                /* get a vector from fp */
524   }
525  
526  
527 + static int
528 + iszerovec(const FVECT vec)
529 + {
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
# Line 465 | Line 651 | oputo(                         /* print origin */
651          RAY  *r
652   )
653   {
654 <        (*putreal)(r->rorg[0]);
469 <        (*putreal)(r->rorg[1]);
470 <        (*putreal)(r->rorg[2]);
654 >        (*putreal)(r->rorg, 3);
655   }
656  
657  
# Line 476 | Line 660 | oputd(                         /* print direction */
660          RAY  *r
661   )
662   {
663 <        (*putreal)(r->rdir[0]);
480 <        (*putreal)(r->rdir[1]);
481 <        (*putreal)(r->rdir[2]);
663 >        (*putreal)(r->rdir, 3);
664   }
665  
666  
667   static void
668 + oputr(                          /* print mirrored contribution */
669 +        RAY  *r
670 + )
671 + {
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 +
682 + static void
683 + oputR(                          /* print mirrored distance */
684 +        RAY  *r
685 + )
686 + {
687 +        (*putreal)(&r->rmt, 1);
688 + }
689 +
690 +
691 + static void
692 + oputx(                          /* print unmirrored contribution */
693 +        RAY  *r
694 + )
695 + {
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 <        if (outform == 'c') {
720 <                COLR  cout;
721 <                setcolr(cout,   colval(r->rcol,RED),
722 <                                colval(r->rcol,GRN),
723 <                                colval(r->rcol,BLU));
724 <                fwrite((char *)cout, sizeof(cout), 1, stdout);
496 <                return;
497 <        }
498 <        (*putreal)(colval(r->rcol,RED));
499 <        (*putreal)(colval(r->rcol,GRN));
500 <        (*putreal)(colval(r->rcol,BLU));
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  
# Line 506 | Line 730 | oputV(                         /* print value contribution */
730          RAY *r
731   )
732   {
733 <        double  contr[3];
733 >        RREAL   contr[3];
734  
735          raycontrib(contr, r, PRIMARY);
736          multcolor(contr, r->rcol);
737 <        (*putreal)(contr[RED]);
514 <        (*putreal)(contr[GRN]);
515 <        (*putreal)(contr[BLU]);
737 >        (*putreal)(contr, 3);
738   }
739  
740  
# Line 521 | Line 743 | oputl(                         /* print effective distance */
743          RAY  *r
744   )
745   {
746 <        (*putreal)(r->rt);
746 >        RREAL   d = raydistance(r);
747 >
748 >        (*putreal)(&d, 1);
749   }
750  
751  
# Line 530 | Line 754 | oputL(                         /* print single ray length */
754          RAY  *r
755   )
756   {
757 <        (*putreal)(r->rot);
757 >        (*putreal)(&r->rot, 1);
758   }
759  
760  
# Line 539 | Line 763 | oputc(                         /* print local coordinates */
763          RAY  *r
764   )
765   {
766 <        (*putreal)(r->uv[0]);
543 <        (*putreal)(r->uv[1]);
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 point */
774 > oputp(                          /* print intersection point */
775          RAY  *r
776   )
777   {
778 <        if (r->rot < FHUGE) {
553 <                (*putreal)(r->rop[0]);
554 <                (*putreal)(r->rop[1]);
555 <                (*putreal)(r->rop[2]);
556 <        } else {
557 <                (*putreal)(0.0);
558 <                (*putreal)(0.0);
559 <                (*putreal)(0.0);
560 <        }
778 >        (*putreal)(r->rop, 3);  /* set to ray origin if distant or no hit */
779   }
780  
781  
# Line 566 | Line 784 | oputN(                         /* print unperturbed normal */
784          RAY  *r
785   )
786   {
787 <        if (r->rot < FHUGE) {
788 <                (*putreal)(r->ron[0]);
789 <                (*putreal)(r->ron[1]);
572 <                (*putreal)(r->ron[2]);
573 <        } else {
574 <                (*putreal)(0.0);
575 <                (*putreal)(0.0);
576 <                (*putreal)(0.0);
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  
# Line 585 | Line 806 | oputn(                         /* print perturbed normal */
806   {
807          FVECT  pnorm;
808  
809 <        if (r->rot >= FHUGE) {
810 <                (*putreal)(0.0);
590 <                (*putreal)(0.0);
591 <                (*putreal)(0.0);
809 >        if (r->ro == NULL) {    /* clipped or no hit */
810 >                (*putreal)(vdummy, 3);
811                  return;
812          }
813          raynormal(pnorm, r);
814 <        (*putreal)(pnorm[0]);
596 <        (*putreal)(pnorm[1]);
597 <        (*putreal)(pnorm[2]);
814 >        (*putreal)(pnorm, 3);
815   }
816  
817  
# Line 616 | Line 833 | 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  
# Line 625 | Line 844 | oputW(                         /* print coefficient */
844          RAY  *r
845   )
846   {
847 <        double  contr[3];
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 <        raycontrib(contr, r, PRIMARY);
631 <        (*putreal)(contr[RED]);
632 <        (*putreal)(contr[GRN]);
633 <        (*putreal)(contr[BLU]);
854 >        (*putreal)(contr, 3);
855   }
856  
857  
# Line 678 | Line 899 | oputtilde(                     /* output tilde (spacer) */
899  
900  
901   static void
902 < puta(                           /* print ascii value */
903 <        double  v
902 > puta(                           /* print ascii value(s) */
903 >        RREAL *v, int n
904   )
905   {
906 <        printf("%e\t", 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  
915   static void
916 < putd(v)                         /* print binary double */
691 < double  v;
916 > putd(RREAL *v, int n)           /* output binary double(s) */
917   {
918 <        fwrite((char *)&v, sizeof(v), 1, stdout);
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(v)                         /* print binary float */
699 < double  v;
934 > putf(RREAL *v, int n)           /* output binary float(s) */
935   {
936 <        float f = v;
936 > #ifndef SMLFLT
937 >        float   fa[3];
938 >        int     i;
939  
940 <        fwrite((char *)&f, sizeof(f), 1, stdout);
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