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.17 by greg, Tue Dec 20 20:18:34 1994 UTC vs.
Revision 2.107 by greg, Wed Nov 15 18:02:53 2023 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1994 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 <
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 */
43 < 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 < char  *tralist[128];                    /* list of modifers to trace (or no) */
46 < int  traincl = -1;                      /* include == 1, exclude == 0 */
47 < #define  MAXTSET        511             /* maximum number in trace set */
48 < OBJECT  traset[MAXTSET+1]={0};          /* trace include/exclude set */
45 > extern int  hresolu;                    /* horizontal resolution */
46 > extern int  vresolu;                    /* vertical resolution */
47  
48 < int  hresolu = 0;                       /* horizontal (scan) size */
51 < int  vresolu = 0;                       /* vertical resolution */
48 > extern int  castonly;                   /* only doing ray-casting? */
49  
50 < double  dstrsrc = 0.0;                  /* square source distribution */
51 < double  shadthresh = .05;               /* shadow threshold */
52 < double  shadcert = .5;                  /* shadow certainty */
56 < int  directrelay = 1;                   /* number of source relays */
57 < int  vspretest = 512;                   /* virtual source pretest density */
58 < int  directvis = 1;                     /* sources visible? */
59 < double  srcsizerat = .25;               /* maximum ratio source size/dist. */
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 < double  specthresh = .15;               /* specular sampling threshold */
55 < double  specjitter = 1.;                /* specular sampling jitter */
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  maxdepth = 6;                      /* maximum recursion depth */
65 < double  minweight = 4e-3;               /* minimum ray weight */
59 > static int  Tflag = 0;                  /* source tracing enabled? */
60  
61 < COLOR  ambval = BLKCOLOR;               /* ambient value */
68 < double  ambacc = 0.2;                   /* ambient accuracy */
69 < int  ambres = 32;                       /* ambient resolution */
70 < int  ambdiv = 128;                      /* ambient divisions */
71 < int  ambssamp = 0;                      /* ambient super-samples */
72 < int  ambounce = 0;                      /* ambient bounces */
73 < char  *amblist[128];                    /* ambient include/exclude list */
74 < int  ambincl = -1;                      /* include == 1, exclude == 0 */
61 > static RAY  thisray;                    /* for our convenience */
62  
63 < extern OBJREC  Lamb;                    /* a Lambertian surface */
63 > static FILE  *inpfp = NULL;             /* input stream pointer */
64  
65 < static RAY  thisray;                    /* for our convenience */
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 < static int  oputo(), oputd(), oputv(), oputl(), oputL(),
70 <                oputp(), oputn(), oputN(), oputs(), oputw(), oputm();
69 > typedef void putf_t(RREAL *v, int n);
70 > static putf_t puta, putd, putf;
71  
72 < static int  ourtrace(), tabin();
73 < static int  (*ray_out[16])(), (*every_out[16])();
74 < static int  castonly = 0;
72 > typedef void oputf_t(RAY *r);
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 int  puta(), putf(), putd();
77 > extern void tranotify(OBJECT obj);
78 > static int is_fifo(FILE *fp);
79 > static void bogusray(void);
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 int  (*putreal)();
90 > static void  putscolor(const COLORV *scol);
91  
92 + static oputf_t *ray_out[32], *every_out[32];
93 + static putf_t *putreal;
94  
95 < quit(code)                      /* quit program */
96 < int  code;
95 >
96 > void
97 > quit(                   /* quit program */
98 >        int  code
99 > )
100   {
101 < #ifndef  NIX
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 < char *
116 < formstr(f)                              /* return format identifier */
117 < int  f;
115 > const char *
116 > formstr(                                /* return format identifier */
117 >        int  f
118 > )
119   {
120          switch (f) {
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 < rtrace(fname)                           /* trace rays from file */
136 < char  *fname;
135 > static void
136 > trace_sources(void)                     /* trace rays to light sources, also */
137   {
138 <        long  vcount = hresolu>1 ? hresolu*vresolu : vresolu;
139 <        long  nextflush = hresolu;
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,
148 >        int  nproc
149 > )
150 > {
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 MSDOS
166 <        if (inform != 'a')
167 <                setmode(fileno(fp), O_BINARY);
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':
142 <                if (strcmp(outvals, "v"))
143 <                        error(USER, "color format with value output only");
144 <                break;
145 <        default:
146 <                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);
151                fflush(stdout);
152        }
153                                        /* process file */
154        while (getvec(orig, inform, fp) == 0 &&
155                        getvec(direc, inform, fp) == 0) {
156
157                if (normalize(direc) == 0.0) {          /* zero ==> flush */
158                        fflush(stdout);
159                        continue;
160                }
161                samplendx++;
162                                                        /* compute and print */
163                if (imm_irrad)
164                        irrad(orig, direc);
190                  else
166                        rad(orig, direc);
167                                                        /* flush if time */
168                if (--nextflush == 0) {
191                          fflush(stdout);
192 <                        nextflush = hresolu;
192 >        }
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 = (!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 >                        } 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 < setoutput(vs)                           /* set up output tables */
238 < register char  *vs;
237 > int
238 > setrtoutput(void)                       /* set up output tables, return #comp */
239   {
240 <        extern int  (*trace)();
241 <        register int (**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;
197                        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 < rad(org, dir)                   /* compute and print ray value(s) */
391 < FVECT  org, dir;
390 > static void
391 > bogusray(void)                  /* print out empty record */
392   {
393 <        VCOPY(thisray.rorg, org);
245 <        VCOPY(thisray.rdir, dir);
246 <        thisray.rmax = 0.0;
247 <        rayorigin(&thisray, NULL, PRIMARY, 1.0);
248 <        if (castonly)
249 <                localhit(&thisray, &thescene) || sourcehit(&thisray);
250 <        else
251 <                rayvalue(&thisray);
393 >        rayorigin(&thisray, PRIMARY, NULL, NULL);
394          printvals(&thisray);
395   }
396  
397  
398 < irrad(org, dir)                 /* compute immediate irradiance value */
399 < FVECT  org, dir;
398 > static void
399 > raycast(                        /* compute first ray intersection only */
400 >        RAY *r
401 > )
402   {
403 <        register int  i;
404 <
405 <        for (i = 0; i < 3; i++) {
406 <                thisray.rorg[i] = org[i] + dir[i];
407 <                thisray.rdir[i] = -dir[i];
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 <        rayorigin(&thisray, NULL, PRIMARY, 1.0);
410 > }
411 >
412 >
413 > static void
414 > rayirrad(                       /* compute irradiance rather than radiance */
415 >        RAY *r
416 > )
417 > {
418 >        void    (*old_revf)(RAY *) = r->revf;
419                                          /* pretend we hit surface */
420 <        thisray.rot = 1.0-1e-4;
421 <        thisray.rod = 1.0;
422 <        VCOPY(thisray.ron, dir);
423 <        for (i = 0; i < 3; i++)         /* fudge factor */
424 <                thisray.rop[i] = org[i] + 1e-4*dir[i];
425 <                                        /* compute and print */
426 <        (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
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 >
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, 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 < printvals(r)                    /* print requested ray values */
469 < RAY  *r;
468 > static int
469 > printvals(                      /* print requested ray values */
470 >        RAY  *r
471 > )
472   {
473 <        register int  (**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 < getvec(vec, fmt, fp)            /* get a vector from fp */
486 < register FVECT  vec;
487 < int  fmt;
488 < FILE  *fp;
485 > static int
486 > is_fifo(                /* check if file pointer connected to pipe */
487 >        FILE *fp
488 > )
489   {
490 <        extern char  *fgetword();
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 > )
508 > {
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 310 | Line 521 | FILE  *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 326 | Line 537 | FILE  *fp;
537   }
538  
539  
540 < tranotify(obj)                  /* record new modifier */
541 < OBJECT  obj;
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;
610 +                hitlimit = 0;
611 +                return;
612 +        }
613          if (hitlimit || !ismodifier(o->otype))
614                  return;
615          for (tralp = tralist; *tralp != NULL; tralp++)
# Line 348 | Line 625 | OBJECT obj;
625   }
626  
627  
628 < static
629 < ourtrace(r)                             /* print ray values */
630 < RAY  *r;
628 > static void
629 > ourtrace(                               /* print ray values */
630 >        RAY  *r
631 > )
632   {
633 <        register int  (**tp)();
633 >        oputf_t **tp;
634  
635          if (every_out[0] == NULL)
636                  return;
# Line 364 | Line 642 | RAY  *r;
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  
650 < static
651 < tabin(r)                                /* tab in appropriate amount */
652 < RAY  *r;
650 > static void
651 > 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');
659   }
660  
661  
662 < static
663 < oputo(r)                                /* print origin */
664 < register RAY  *r;
662 > static void
663 > oputo(                          /* print origin */
664 >        RAY  *r
665 > )
666   {
667 <        (*putreal)(r->rorg[0]);
387 <        (*putreal)(r->rorg[1]);
388 <        (*putreal)(r->rorg[2]);
667 >        (*putreal)(r->rorg, 3);
668   }
669  
670  
671 < static
672 < oputd(r)                                /* print direction */
673 < register RAY  *r;
671 > static void
672 > oputd(                          /* print direction */
673 >        RAY  *r
674 > )
675   {
676 <        (*putreal)(r->rdir[0]);
397 <        (*putreal)(r->rdir[1]);
398 <        (*putreal)(r->rdir[2]);
676 >        (*putreal)(r->rdir, 3);
677   }
678  
679  
680 < static
681 < oputv(r)                                /* print value */
682 < register RAY  *r;
680 > static void
681 > oputr(                          /* print mirrored contribution */
682 >        RAY  *r
683 > )
684   {
685 <        COLR  cout;
686 <        
687 <        if (outform == 'c') {
688 <                setcolr(cout,   colval(r->rcol,RED),
689 <                                colval(r->rcol,GRN),
690 <                                colval(r->rcol,BLU));
412 <                fwrite((char *)cout, sizeof(cout), 1, stdout);
413 <                return;
414 <        }
415 <        (*putreal)(colval(r->rcol,RED));
416 <        (*putreal)(colval(r->rcol,GRN));
417 <        (*putreal)(colval(r->rcol,BLU));
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 < static
695 < oputl(r)                                /* print effective distance */
696 < register RAY  *r;
694 >
695 > static void
696 > oputR(                          /* print mirrored distance */
697 >        RAY  *r
698 > )
699   {
700 <        (*putreal)(r->rt);
700 >        (*putreal)(&r->rmt, 1);
701   }
702  
703  
704 < static
705 < oputL(r)                                /* print single ray length */
706 < register RAY  *r;
704 > static void
705 > oputx(                          /* print unmirrored contribution */
706 >        RAY  *r
707 > )
708   {
709 <        (*putreal)(r->rot);
709 >        SCOLOR  cdiff;
710 >
711 >        copyscolor(cdiff, r->rcol);
712 >        sopscolor(cdiff, -=, r->mcol);
713 >
714 >        putscolor(cdiff);
715   }
716  
717  
718 < static
719 < oputp(r)                                /* print point */
720 < register RAY  *r;
718 > static void
719 > oputX(                          /* print unmirrored distance */
720 >        RAY  *r
721 > )
722   {
723 <        if (r->rot < FHUGE) {
442 <                (*putreal)(r->rop[0]);
443 <                (*putreal)(r->rop[1]);
444 <                (*putreal)(r->rop[2]);
445 <        } else {
446 <                (*putreal)(0.0);
447 <                (*putreal)(0.0);
448 <                (*putreal)(0.0);
449 <        }
723 >        (*putreal)(&r->rxt, 1);
724   }
725  
726  
727 < static
728 < oputN(r)                                /* print unperturbed normal */
729 < register RAY  *r;
727 > static void
728 > oputv(                          /* print value */
729 >        RAY  *r
730 > )
731   {
732 <        if (r->rot < FHUGE) {
733 <                (*putreal)(r->ron[0]);
734 <                (*putreal)(r->ron[1]);
735 <                (*putreal)(r->ron[2]);
736 <        } else {
737 <                (*putreal)(0.0);
738 <                (*putreal)(0.0);
739 <                (*putreal)(0.0);
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 >        RREAL   d = raydistance(r);
755 >
756 >        (*putreal)(&d, 1);
757 > }
758 >
759 >
760 > static void
761 > oputL(                          /* print single ray length */
762 >        RAY  *r
763 > )
764 > {
765 >        (*putreal)(&r->rot, 1);
766 > }
767 >
768 >
769 > static void
770 > oputc(                          /* print local coordinates */
771 >        RAY  *r
772 > )
773 > {
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 intersection point */
783 >        RAY  *r
784 > )
785 > {
786 >        (*putreal)(r->rop, 3);  /* set to ray origin if distant or no hit */
787 > }
788 >
789 >
790 > static void
791 > oputN(                          /* print unperturbed normal */
792 >        RAY  *r
793 > )
794 > {
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  
810 < static
811 < oputn(r)                                /* print perturbed normal */
812 < RAY  *r;
810 > static void
811 > oputn(                          /* print perturbed normal */
812 >        RAY  *r
813 > )
814   {
815          FVECT  pnorm;
816  
817 <        if (r->rot >= FHUGE) {
818 <                (*putreal)(0.0);
477 <                (*putreal)(0.0);
478 <                (*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]);
483 <        (*putreal)(pnorm[1]);
484 <        (*putreal)(pnorm[2]);
822 >        (*putreal)(pnorm, 3);
823   }
824  
825  
826 < static
827 < oputs(r)                                /* print name */
828 < register RAY  *r;
826 > static void
827 > oputs(                          /* print name */
828 >        RAY  *r
829 > )
830   {
831          if (r->ro != NULL)
832                  fputs(r->ro->oname, stdout);
# Line 497 | Line 836 | register RAY  *r;
836   }
837  
838  
839 < static
840 < oputw(r)                                /* print weight */
841 < register RAY  *r;
839 > static void
840 > 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
851 < oputm(r)                                /* print modifier */
852 < register RAY  *r;
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 + )
870 + {
871          if (r->ro != NULL)
872 <                fputs(objptr(r->ro->omod)->oname, stdout);
872 >                if (r->ro->omod != OVOID)
873 >                        fputs(objptr(r->ro->omod)->oname, stdout);
874 >                else
875 >                        fputs(VOIDID, stdout);
876          else
877                  putchar('*');
878          putchar('\t');
879   }
880  
881  
882 < static
883 < puta(v)                         /* print ascii value */
884 < double  v;
882 > static void
883 > oputM(                          /* print material */
884 >        RAY  *r
885 > )
886   {
887 <        printf("%e\t", v);
887 >        OBJREC  *mat;
888 >
889 >        if (r->ro != NULL) {
890 >                if ((mat = findmaterial(r->ro)) != NULL)
891 >                        fputs(mat->oname, stdout);
892 >                else
893 >                        fputs(VOIDID, stdout);
894 >        } else
895 >                putchar('*');
896 >        putchar('\t');
897   }
898  
899  
900 < static
901 < putd(v)                         /* print binary double */
902 < double  v;
900 > static void
901 > oputtilde(                      /* output tilde (spacer) */
902 >        RAY  *r
903 > )
904   {
905 <        fwrite((char *)&v, sizeof(v), 1, stdout);
905 >        fputs("~\t", stdout);
906   }
907  
908  
909 < static
910 < putf(v)                         /* print binary float */
911 < double  v;
909 > static void
910 > puta(                           /* print ascii value(s) */
911 >        RREAL *v, int n
912 > )
913   {
914 <        float f = v;
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 <        fwrite((char *)&f, sizeof(f), 1, stdout);
922 >
923 > static void
924 > putd(RREAL *v, int n)           /* output binary double(s) */
925 > {
926 > #ifdef  SMLFLT
927 >        double  da[3];
928 >        int     i;
929 >
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