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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines