--- ray/src/rt/rtrace.c 2003/02/22 02:07:29 2.27
+++ ray/src/rt/rtrace.c 2023/11/18 16:21:58 2.108
@@ -1,66 +1,11 @@
#ifndef lint
-static const char RCSid[] = "$Id: rtrace.c,v 2.27 2003/02/22 02:07:29 greg Exp $";
+static const char RCSid[] = "$Id: rtrace.c,v 2.108 2023/11/18 16:21:58 greg Exp $";
#endif
/*
* rtrace.c - program and variables for individual ray tracing.
*/
-/* ====================================================================
- * The Radiance Software License, Version 1.0
- *
- * Copyright (c) 1990 - 2002 The Regents of the University of California,
- * through Lawrence Berkeley National Laboratory. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes Radiance software
- * (http://radsite.lbl.gov/)
- * developed by the Lawrence Berkeley National Laboratory
- * (http://www.lbl.gov/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
- * and "The Regents of the University of California" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact radiance@radsite.lbl.gov.
- *
- * 5. Products derived from this software may not be called "Radiance",
- * nor may "Radiance" appear in their name, without prior written
- * permission of Lawrence Berkeley National Laboratory.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of Lawrence Berkeley National Laboratory. For more
- * information on Lawrence Berkeley National Laboratory, please see
- * .
- */
+#include "copyright.h"
/*
* Input is in the form:
@@ -76,326 +21,497 @@ static const char RCSid[] = "$Id: rtrace.c,v 2.27 2003
* irradiance values are desired.
*/
-#include "ray.h"
+#include
+#include "platform.h"
+#include "ray.h"
+#include "ambient.h"
+#include "source.h"
#include "otypes.h"
-
+#include "otspecial.h"
#include "resolu.h"
+#include "random.h"
-CUBE thescene; /* our scene */
-OBJECT nsceneobjs; /* number of objects in our scene */
+extern int inform; /* input format */
+extern int outform; /* output format */
+extern char *outvals; /* output values */
-int dimlist[MAXDIM]; /* sampling dimensions */
-int ndims = 0; /* number of sampling dimensions */
-int samplendx = 0; /* index for this sample */
+extern int imm_irrad; /* compute immediate irradiance? */
+extern int lim_dist; /* limit distance? */
-int imm_irrad = 0; /* compute immediate irradiance? */
-int lim_dist = 0; /* limit distance? */
+extern char *tralist[]; /* list of modifers to trace (or no) */
+extern int traincl; /* include == 1, exclude == 0 */
-int inform = 'a'; /* input format */
-int outform = 'a'; /* output format */
-char *outvals = "v"; /* output specification */
+extern int hresolu; /* horizontal resolution */
+extern int vresolu; /* vertical resolution */
-int do_irrad = 0; /* compute irradiance? */
+extern int castonly; /* only doing ray-casting? */
-void (*trace)() = NULL; /* trace call */
+extern double (*sens_curve)(SCOLOR scol); /* spectral conversion for 1-channel */
+extern double out_scalefactor; /* output calibration scale factor */
+extern RGBPRIMP out_prims; /* output color primitives (NULL if spectral) */
-extern void ambnotify(), tranotify();
-void (*addobjnotify[])() = {ambnotify, tranotify, NULL};
-char *tralist[128]; /* list of modifers to trace (or no) */
-int traincl = -1; /* include == 1, exclude == 0 */
-#define MAXTSET 511 /* maximum number in trace set */
+#ifndef MAXTSET
+#define MAXTSET 8191 /* maximum number in trace set */
+#endif
OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */
-int hresolu = 0; /* horizontal (scan) size */
-int vresolu = 0; /* vertical resolution */
+static int Tflag = 0; /* source tracing enabled? */
-double dstrsrc = 0.0; /* square source distribution */
-double shadthresh = .05; /* shadow threshold */
-double shadcert = .5; /* shadow certainty */
-int directrelay = 2; /* number of source relays */
-int vspretest = 512; /* virtual source pretest density */
-int directvis = 1; /* sources visible? */
-double srcsizerat = .2; /* maximum ratio source size/dist. */
+static RAY thisray; /* for our convenience */
-COLOR cextinction = BLKCOLOR; /* global extinction coefficient */
-COLOR salbedo = BLKCOLOR; /* global scattering albedo */
-double seccg = 0.; /* global scattering eccentricity */
-double ssampdist = 0.; /* scatter sampling distance */
+static FILE *inpfp = NULL; /* input stream pointer */
-double specthresh = .15; /* specular sampling threshold */
-double specjitter = 1.; /* specular sampling jitter */
+static FVECT *inp_queue = NULL; /* ray input queue if flushing */
+static int inp_qpos = 0; /* next ray to return */
+static int inp_qend = 0; /* number of rays in this work group */
-int backvis = 1; /* back face visibility */
+typedef void putf_t(RREAL *v, int n);
+static putf_t puta, putd, putf;
-int maxdepth = 6; /* maximum recursion depth */
-double minweight = 4e-3; /* minimum ray weight */
+typedef void oputf_t(RAY *r);
+static oputf_t oputo, oputd, oputv, oputV, oputl, oputL, oputc, oputp,
+ oputr, oputR, oputx, oputX, oputn, oputN, oputs,
+ oputw, oputW, oputm, oputM, oputtilde;
-char *ambfile = NULL; /* ambient file name */
-COLOR ambval = BLKCOLOR; /* ambient value */
-int ambvwt = 0; /* initial weight for ambient value */
-double ambacc = 0.2; /* ambient accuracy */
-int ambres = 128; /* ambient resolution */
-int ambdiv = 512; /* ambient divisions */
-int ambssamp = 0; /* ambient super-samples */
-int ambounce = 0; /* ambient bounces */
-char *amblist[128]; /* ambient include/exclude list */
-int ambincl = -1; /* include == 1, exclude == 0 */
+extern void tranotify(OBJECT obj);
+static int is_fifo(FILE *fp);
+static void bogusray(void);
+static void raycast(RAY *r);
+static void rayirrad(RAY *r);
+static void rtcompute(FVECT org, FVECT dir, double dmax);
+static int printvals(RAY *r);
+static int getvec(FVECT vec, int fmt, FILE *fp);
+static int iszerovec(const FVECT vec);
+static double nextray(FVECT org, FVECT dir);
+static void tabin(RAY *r);
+static void ourtrace(RAY *r);
+static void putscolor(const COLORV *scol);
-static RAY thisray; /* for our convenience */
+static oputf_t *ray_out[32], *every_out[32];
+static putf_t *putreal;
-static void oputo(), oputd(), oputv(), oputl(), oputL(),
- oputp(), oputn(), oputN(), oputs(), oputw(), oputm();
-static void ourtrace(), tabin();
-static void (*ray_out[16])(), (*every_out[16])();
-static int castonly = 0;
-
-static void puta(), putf(), putd();
-
-static void (*putreal)();
-
-void bogusray(), rad(), irrad(), printvals();
-
-
void
-quit(code) /* quit program */
-int code;
+quit( /* quit program */
+ int code
+)
{
-#ifndef NIX
- headclean(); /* delete header file */
- pfclean(); /* clean up persist files */
+ if (ray_pnprocs > 0) /* close children if any */
+ ray_pclose(0);
+ else if (ray_pnprocs < 0)
+ _exit(code); /* avoid flush() in child */
+#ifndef NON_POSIX
+ else {
+ headclean(); /* delete header file */
+ pfclean(); /* clean up persist files */
+ }
#endif
exit(code);
}
-char *
-formstr(f) /* return format identifier */
-int f;
+const char *
+formstr( /* return format identifier */
+ int f
+)
{
switch (f) {
case 'a': return("ascii");
case 'f': return("float");
case 'd': return("double");
- case 'c': return(COLRFMT);
+ case 'c':
+ if (out_prims == NULL)
+ return(SPECFMT);
+ if (out_prims == xyzprims)
+ return(CIEFMT);
+ return(COLRFMT);
}
return("unknown");
}
+static void
+trace_sources(void) /* trace rays to light sources, also */
+{
+ int sn;
+
+ for (sn = 0; sn < nsources; sn++)
+ source[sn].sflags |= SFOLLOW;
+}
+
+
void
-rtrace(fname) /* trace rays from file */
-char *fname;
+rtrace( /* trace rays from file */
+ char *fname,
+ int nproc
+)
{
- long vcount = hresolu>1 ? hresolu*vresolu : vresolu;
- long nextflush = hresolu;
+ unsigned long vcount = (hresolu > 1) ? (unsigned long)hresolu*vresolu
+ : (unsigned long)vresolu;
+ long nextflush = (!vresolu | (hresolu <= 1)) * hresolu;
+ int something2flush = 0;
FILE *fp;
double d;
FVECT orig, direc;
/* set up input */
if (fname == NULL)
- fp = stdin;
- else if ((fp = fopen(fname, "r")) == NULL) {
+ inpfp = stdin;
+ else if ((inpfp = fopen(fname, "r")) == NULL) {
sprintf(errmsg, "cannot open input file \"%s\"", fname);
error(SYSTEM, errmsg);
}
-#ifdef MSDOS
- if (inform != 'a')
- setmode(fileno(fp), O_BINARY);
+#ifdef getc_unlocked
+ flockfile(inpfp); /* avoid lock/unlock overhead */
+ flockfile(stdout);
#endif
+ if (inform != 'a')
+ SET_FILE_BINARY(inpfp);
/* set up output */
- setoutput(outvals);
- switch (outform) {
- case 'a': putreal = puta; break;
- case 'f': putreal = putf; break;
- case 'd': putreal = putd; break;
- case 'c':
- if (strcmp(outvals, "v"))
- error(USER, "color format with value output only");
- break;
- default:
- error(CONSISTENCY, "botched output format");
+ if (castonly || every_out[0] != NULL)
+ nproc = 1; /* don't bother multiprocessing */
+ if (every_out[0] != NULL) {
+ trace = ourtrace; /* enable full tree tracing */
+ if (Tflag) /* light sources, too? */
+ trace_sources();
}
+ if ((nextflush > 0) & (nproc > nextflush)) {
+ error(WARNING, "reducing number of processes to match flush interval");
+ nproc = nextflush;
+ }
+ if (nproc > 1) { /* start multiprocessing */
+ ray_popen(nproc);
+ ray_fifo_out = printvals;
+ }
if (hresolu > 0) {
if (vresolu > 0)
fprtresolu(hresolu, vresolu, stdout);
- fflush(stdout);
+ else
+ fflush(stdout);
}
- /* process file */
- while (getvec(orig, inform, fp) == 0 &&
- getvec(direc, inform, fp) == 0) {
-
- d = normalize(direc);
- if (d == 0.0) { /* zero ==> flush */
- bogusray();
- if (--nextflush <= 0 || vcount <= 0) {
+ /* process input rays */
+ while ((d = nextray(orig, direc)) >= 0.0) {
+ if (d == 0.0) { /* flush request? */
+ if (something2flush) {
+ if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
+ error(USER, "child(ren) died");
+ bogusray();
fflush(stdout);
- nextflush = hresolu;
- }
- } else {
- samplendx++;
- /* compute and print */
- if (imm_irrad)
- irrad(orig, direc);
- else
- rad(orig, direc, lim_dist ? d : 0.0);
- /* flush if time */
- if (--nextflush == 0) {
+ nextflush = (!vresolu | (hresolu <= 1)) * hresolu;
+ something2flush = 0;
+ } else
+ bogusray();
+ } else { /* compute and print */
+ rtcompute(orig, direc, lim_dist ? d : 0.0);
+ if (!--nextflush) { /* flush if time */
+ if (ray_pnprocs > 1 && ray_fifo_flush() < 0)
+ error(USER, "child(ren) died");
fflush(stdout);
nextflush = hresolu;
- }
+ } else
+ something2flush = 1;
}
if (ferror(stdout))
error(SYSTEM, "write error");
- if (--vcount == 0) /* check for end */
+ if (vcount && !--vcount) /* check for end */
break;
}
- fflush(stdout);
- if (vcount > 0)
- error(USER, "read error");
- if (fname != NULL)
- fclose(fp);
+ if (ray_pnprocs > 1) { /* clean up children */
+ if (ray_fifo_flush() < 0)
+ error(USER, "unable to complete processing");
+ ray_pclose(0);
+ }
+ if (vcount)
+ error(WARNING, "unexpected EOF on input");
+ if (fflush(stdout) < 0)
+ error(SYSTEM, "write error");
+ if (fname != NULL) {
+ fclose(inpfp);
+ inpfp = NULL;
+ }
+ nextray(NULL, NULL);
}
-setoutput(vs) /* set up output tables */
-register char *vs;
+int
+setrtoutput(void) /* set up output tables, return #comp */
{
- extern void (*trace)();
- register void (**table)() = ray_out;
+ char *vs = outvals;
+ oputf_t **table = ray_out;
+ const int nco = (sens_curve != NULL) ? 1 :
+ (out_prims != NULL) ? 3 : NCSAMP;
+ int ncomp = 0;
- castonly = 1;
- while (*vs)
- switch (*vs++) {
+ if (!*vs)
+ error(USER, "empty output specification");
+
+ switch (outform) { /* make sure (*putreal)() calls someone! */
+ case 'a': putreal = puta; break;
+ case 'f': putreal = putf; break;
+ case 'd': putreal = putd; break;
+ case 'c':
+ if (outvals[1] || !strchr("vrx", outvals[0]))
+ error(USER, "color format only with -ov, -or, -ox");
+ if (nco < 3)
+ error(USER, "color format incompatible with -pY, -pS, -pM");
+ break;
+ default:
+ error(CONSISTENCY, "botched output format");
+ }
+ castonly = 1; /* sets castonly as side-effect */
+ do
+ switch (*vs) {
+ case 'T': /* trace sources */
+ Tflag++;
+ /* fall through */
case 't': /* trace */
+ if (!vs[1]) break;
*table = NULL;
table = every_out;
- trace = ourtrace;
castonly = 0;
break;
case 'o': /* origin */
*table++ = oputo;
+ ncomp += 3;
break;
case 'd': /* direction */
*table++ = oputd;
+ ncomp += 3;
break;
+ case 'r': /* reflected contrib. */
+ *table++ = oputr;
+ ncomp += nco;
+ castonly = 0;
+ break;
+ case 'R': /* reflected distance */
+ *table++ = oputR;
+ ncomp++;
+ castonly = 0;
+ break;
+ case 'x': /* xmit contrib. */
+ *table++ = oputx;
+ ncomp += nco;
+ castonly = 0;
+ break;
+ case 'X': /* xmit distance */
+ *table++ = oputX;
+ ncomp++;
+ castonly = 0;
+ break;
case 'v': /* value */
*table++ = oputv;
+ ncomp += nco;
castonly = 0;
break;
+ case 'V': /* contribution */
+ *table++ = oputV;
+ ncomp += nco;
+ castonly = 0;
+ if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
+ error(WARNING,
+ "-otV accuracy depends on -aa 0 -as 0");
+ break;
case 'l': /* effective distance */
*table++ = oputl;
+ ncomp++;
castonly = 0;
break;
+ case 'c': /* local coordinates */
+ *table++ = oputc;
+ ncomp += 2;
+ break;
case 'L': /* single ray length */
*table++ = oputL;
+ ncomp++;
break;
case 'p': /* point */
*table++ = oputp;
+ ncomp += 3;
break;
case 'n': /* perturbed normal */
*table++ = oputn;
+ ncomp += 3;
castonly = 0;
break;
case 'N': /* unperturbed normal */
*table++ = oputN;
+ ncomp += 3;
break;
case 's': /* surface */
*table++ = oputs;
+ ncomp++;
break;
case 'w': /* weight */
*table++ = oputw;
+ ncomp++;
break;
+ case 'W': /* coefficient */
+ *table++ = oputW;
+ ncomp += nco;
+ castonly = 0;
+ if (ambounce > 0 && (ambacc > FTINY) | (ambssamp > 0))
+ error(WARNING,
+ "-otW accuracy depends on -aa 0 -as 0");
+ break;
case 'm': /* modifier */
*table++ = oputm;
+ ncomp++;
break;
+ case 'M': /* material */
+ *table++ = oputM;
+ ncomp++;
+ break;
+ case '~': /* tilde */
+ *table++ = oputtilde;
+ break;
+ default:
+ sprintf(errmsg, "unrecognized output option '%c'", *vs);
+ error(USER, errmsg);
}
+ while (*++vs);
+
*table = NULL;
+ if (*every_out != NULL)
+ ncomp = 0;
+ /* compatibility */
+ if ((do_irrad | imm_irrad) && castonly)
+ error(USER, "-I+ and -i+ options require some value output");
+ for (table = ray_out; *table != NULL; table++) {
+ if ((*table == oputV) | (*table == oputW))
+ error(WARNING, "-oVW options require trace mode");
+ if ((do_irrad | imm_irrad) &&
+ (*table == oputr) | (*table == oputR) |
+ (*table == oputx) | (*table == oputX))
+ error(WARNING, "-orRxX options incompatible with -I+ and -i+");
+ }
+ return(ncomp);
}
-void
-bogusray() /* print out empty record */
+static void
+bogusray(void) /* print out empty record */
{
- thisray.rorg[0] = thisray.rorg[1] = thisray.rorg[2] =
- thisray.rdir[0] = thisray.rdir[1] = thisray.rdir[2] = 0.0;
- rayorigin(&thisray, NULL, PRIMARY, 1.0);
+ rayorigin(&thisray, PRIMARY, NULL, NULL);
printvals(&thisray);
}
-void
-rad(org, dir, dmax) /* compute and print ray value(s) */
-FVECT org, dir;
-double dmax;
+static void
+raycast( /* compute first ray intersection only */
+ RAY *r
+)
{
- VCOPY(thisray.rorg, org);
- VCOPY(thisray.rdir, dir);
- thisray.rmax = dmax;
- rayorigin(&thisray, NULL, PRIMARY, 1.0);
- if (castonly) {
- if (!localhit(&thisray, &thescene))
- if (thisray.ro == &Aftplane) { /* clipped */
- thisray.ro = NULL;
- thisray.rot = FHUGE;
- } else
- sourcehit(&thisray);
- } else
- rayvalue(&thisray);
- printvals(&thisray);
+ if (!localhit(r, &thescene)) {
+ if (r->ro == &Aftplane) { /* clipped */
+ r->ro = NULL;
+ r->rot = FHUGE;
+ } else
+ sourcehit(r);
+ }
}
-void
-irrad(org, dir) /* compute immediate irradiance value */
-FVECT org, dir;
+static void
+rayirrad( /* compute irradiance rather than radiance */
+ RAY *r
+)
{
- register int i;
+ void (*old_revf)(RAY *) = r->revf;
+ /* pretend we hit surface */
+ r->rxt = r->rot = 1e-5;
+ VSUM(r->rop, r->rorg, r->rdir, r->rot);
+ r->ron[0] = -r->rdir[0];
+ r->ron[1] = -r->rdir[1];
+ r->ron[2] = -r->rdir[2];
+ r->rod = 1.0;
+ /* compute result */
+ r->revf = raytrace;
+ (*ofun[Lamb.otype].funp)(&Lamb, r);
+ r->revf = old_revf;
+}
- for (i = 0; i < 3; i++) {
- thisray.rorg[i] = org[i] + dir[i];
- thisray.rdir[i] = -dir[i];
+
+static void
+rtcompute( /* compute and print ray value(s) */
+ FVECT org,
+ FVECT dir,
+ double dmax
+)
+{
+ /* set up ray */
+ if (imm_irrad) {
+ VSUM(thisray.rorg, org, dir, 1.1e-4);
+ thisray.rdir[0] = -dir[0];
+ thisray.rdir[1] = -dir[1];
+ thisray.rdir[2] = -dir[2];
+ thisray.rmax = 0.0;
+ } else {
+ VCOPY(thisray.rorg, org);
+ VCOPY(thisray.rdir, dir);
+ thisray.rmax = dmax;
}
- rayorigin(&thisray, NULL, PRIMARY, 1.0);
- /* pretend we hit surface */
- thisray.rot = 1.0-1e-4;
- thisray.rod = 1.0;
- VCOPY(thisray.ron, dir);
- for (i = 0; i < 3; i++) /* fudge factor */
- thisray.rop[i] = org[i] + 1e-4*dir[i];
- /* compute and print */
- (*ofun[Lamb.otype].funp)(&Lamb, &thisray);
+ rayorigin(&thisray, PRIMARY, NULL, NULL);
+ if (imm_irrad)
+ thisray.revf = rayirrad;
+ else if (castonly)
+ thisray.revf = raycast;
+ if (ray_pnprocs > 1) { /* multiprocessing FIFO? */
+ if (ray_fifo_in(&thisray) < 0)
+ error(USER, "lost children");
+ return;
+ }
+ samplendx++; /* else do it ourselves */
+ rayvalue(&thisray);
printvals(&thisray);
}
-void
-printvals(r) /* print requested ray values */
-RAY *r;
+static int
+printvals( /* print requested ray values */
+ RAY *r
+)
{
- register void (**tp)();
+ oputf_t **tp;
if (ray_out[0] == NULL)
- return;
+ return(0);
for (tp = ray_out; *tp != NULL; tp++)
(**tp)(r);
if (outform == 'a')
putchar('\n');
+ return(1);
}
-int
-getvec(vec, fmt, fp) /* get a vector from fp */
-register FVECT vec;
-int fmt;
-FILE *fp;
+static int
+is_fifo( /* check if file pointer connected to pipe */
+ FILE *fp
+)
{
+#ifdef S_ISFIFO
+ struct stat sbuf;
+
+ if (fstat(fileno(fp), &sbuf) < 0)
+ error(SYSTEM, "fstat() failed on input stream");
+ return(S_ISFIFO(sbuf.st_mode));
+#else
+ return (fp == stdin); /* just a guess, really */
+#endif
+}
+
+
+static int
+getvec( /* get a vector from fp */
+ FVECT vec,
+ int fmt,
+ FILE *fp
+)
+{
static float vf[3];
static double vd[3];
char buf[32];
- register int i;
+ int i;
switch (fmt) {
case 'a': /* ascii */
@@ -407,14 +523,14 @@ FILE *fp;
}
break;
case 'f': /* binary float */
- if (fread((char *)vf, sizeof(float), 3, fp) != 3)
+ if (getbinary(vf, sizeof(float), 3, fp) != 3)
return(-1);
- vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
+ VCOPY(vec, vf);
break;
case 'd': /* binary double */
- if (fread((char *)vd, sizeof(double), 3, fp) != 3)
+ if (getbinary(vd, sizeof(double), 3, fp) != 3)
return(-1);
- vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
+ VCOPY(vec, vd);
break;
default:
error(CONSISTENCY, "botched input format");
@@ -423,13 +539,73 @@ FILE *fp;
}
+static int
+iszerovec(const FVECT vec)
+{
+ return (vec[0] == 0.0) & (vec[1] == 0.0) & (vec[2] == 0.0);
+}
+
+
+static double
+nextray( /* return next ray in work group (-1.0 if EOF) */
+ FVECT org,
+ FVECT dir
+)
+{
+ const size_t qlength = !vresolu * hresolu;
+
+ if ((org == NULL) | (dir == NULL)) {
+ if (inp_queue != NULL) /* asking to free queue */
+ free(inp_queue);
+ inp_queue = NULL;
+ inp_qpos = inp_qend = 0;
+ return(-1.);
+ }
+ if (!inp_qend) { /* initialize FIFO queue */
+ int rsiz = 6*20; /* conservative ascii ray size */
+ if (inform == 'f') rsiz = 6*sizeof(float);
+ else if (inform == 'd') rsiz = 6*sizeof(double);
+ /* check against pipe limit */
+ if (qlength*rsiz > 512 && is_fifo(inpfp))
+ inp_queue = (FVECT *)malloc(sizeof(FVECT)*2*qlength);
+ inp_qend = -(inp_queue == NULL); /* flag for no queue */
+ }
+ if (inp_qend < 0) { /* not queuing? */
+ if (getvec(org, inform, inpfp) < 0 ||
+ getvec(dir, inform, inpfp) < 0)
+ return(-1.);
+ return normalize(dir);
+ }
+ if (inp_qpos >= inp_qend) { /* need to refill input queue? */
+ for (inp_qend = 0; inp_qend < qlength; inp_qend++) {
+ if (getvec(inp_queue[2*inp_qend], inform, inpfp) < 0
+ || getvec(inp_queue[2*inp_qend+1],
+ inform, inpfp) < 0)
+ break; /* hit EOF */
+ if (iszerovec(inp_queue[2*inp_qend+1])) {
+ ++inp_qend; /* flush request */
+ break;
+ }
+ }
+ inp_qpos = 0;
+ }
+ if (inp_qpos >= inp_qend) /* unexpected EOF? */
+ return(-1.);
+ VCOPY(org, inp_queue[2*inp_qpos]);
+ VCOPY(dir, inp_queue[2*inp_qpos+1]);
+ ++inp_qpos;
+ return normalize(dir);
+}
+
+
void
-tranotify(obj) /* record new modifier */
-OBJECT obj;
+tranotify( /* record new modifier */
+ OBJECT obj
+)
{
static int hitlimit = 0;
- register OBJREC *o = objptr(obj);
- register char **tralp;
+ OBJREC *o = objptr(obj);
+ char **tralp;
if (obj == OVOID) { /* starting over */
traset[0] = 0;
@@ -452,10 +628,11 @@ OBJECT obj;
static void
-ourtrace(r) /* print ray values */
-RAY *r;
+ourtrace( /* print ray values */
+ RAY *r
+)
{
- register void (**tp)();
+ oputf_t **tp;
if (every_out[0] == NULL)
return;
@@ -467,15 +644,17 @@ RAY *r;
tabin(r);
for (tp = every_out; *tp != NULL; tp++)
(**tp)(r);
- putchar('\n');
+ if (outform == 'a')
+ putchar('\n');
}
static void
-tabin(r) /* tab in appropriate amount */
-RAY *r;
+tabin( /* tab in appropriate amount */
+ RAY *r
+)
{
- register RAY *rp;
+ const RAY *rp;
for (rp = r->parent; rp != NULL; rp = rp->parent)
putchar('\t');
@@ -483,114 +662,173 @@ RAY *r;
static void
-oputo(r) /* print origin */
-register RAY *r;
+oputo( /* print origin */
+ RAY *r
+)
{
- (*putreal)(r->rorg[0]);
- (*putreal)(r->rorg[1]);
- (*putreal)(r->rorg[2]);
+ (*putreal)(r->rorg, 3);
}
static void
-oputd(r) /* print direction */
-register RAY *r;
+oputd( /* print direction */
+ RAY *r
+)
{
- (*putreal)(r->rdir[0]);
- (*putreal)(r->rdir[1]);
- (*putreal)(r->rdir[2]);
+ (*putreal)(r->rdir, 3);
}
static void
-oputv(r) /* print value */
-register RAY *r;
+oputr( /* print mirrored contribution */
+ RAY *r
+)
{
- COLR cout;
-
- if (outform == 'c') {
- setcolr(cout, colval(r->rcol,RED),
- colval(r->rcol,GRN),
- colval(r->rcol,BLU));
- fwrite((char *)cout, sizeof(cout), 1, stdout);
- return;
- }
- (*putreal)(colval(r->rcol,RED));
- (*putreal)(colval(r->rcol,GRN));
- (*putreal)(colval(r->rcol,BLU));
+ RREAL cval[3];
+
+ cval[0] = colval(r->mcol,RED);
+ cval[1] = colval(r->mcol,GRN);
+ cval[2] = colval(r->mcol,BLU);
+ (*putreal)(cval, 3);
}
+
static void
-oputl(r) /* print effective distance */
-register RAY *r;
+oputR( /* print mirrored distance */
+ RAY *r
+)
{
- (*putreal)(r->rt);
+ (*putreal)(&r->rmt, 1);
}
static void
-oputL(r) /* print single ray length */
-register RAY *r;
+oputx( /* print unmirrored contribution */
+ RAY *r
+)
{
- (*putreal)(r->rot);
+ SCOLOR cdiff;
+
+ copyscolor(cdiff, r->rcol);
+ sopscolor(cdiff, -=, r->mcol);
+
+ putscolor(cdiff);
}
static void
-oputp(r) /* print point */
-register RAY *r;
+oputX( /* print unmirrored distance */
+ RAY *r
+)
{
- if (r->rot < FHUGE) {
- (*putreal)(r->rop[0]);
- (*putreal)(r->rop[1]);
- (*putreal)(r->rop[2]);
- } else {
- (*putreal)(0.0);
- (*putreal)(0.0);
- (*putreal)(0.0);
- }
+ (*putreal)(&r->rxt, 1);
}
static void
-oputN(r) /* print unperturbed normal */
-register RAY *r;
+oputv( /* print value */
+ RAY *r
+)
{
- if (r->rot < FHUGE) {
- (*putreal)(r->ron[0]);
- (*putreal)(r->ron[1]);
- (*putreal)(r->ron[2]);
- } else {
- (*putreal)(0.0);
- (*putreal)(0.0);
- (*putreal)(0.0);
+ putscolor(r->rcol);
+}
+
+
+static void
+oputV( /* print value contribution */
+ RAY *r
+)
+{
+ SCOLOR contr;
+
+ raycontrib(contr, r, PRIMARY);
+ smultscolor(contr, r->rcol);
+ putscolor(contr);
+}
+
+
+static void
+oputl( /* print effective distance */
+ RAY *r
+)
+{
+ RREAL d = raydistance(r);
+
+ (*putreal)(&d, 1);
+}
+
+
+static void
+oputL( /* print single ray length */
+ RAY *r
+)
+{
+ (*putreal)(&r->rot, 1);
+}
+
+
+static void
+oputc( /* print local coordinates */
+ RAY *r
+)
+{
+ (*putreal)(r->uv, 2);
+}
+
+
+static RREAL vdummy[3] = {0.0, 0.0, 0.0};
+
+
+static void
+oputp( /* print intersection point */
+ RAY *r
+)
+{
+ (*putreal)(r->rop, 3); /* set to ray origin if distant or no hit */
+}
+
+
+static void
+oputN( /* print unperturbed normal */
+ RAY *r
+)
+{
+ if (r->ro == NULL) { /* zero vector if clipped or no hit */
+ (*putreal)(vdummy, 3);
+ return;
}
+ if (r->rflips & 1) { /* undo any flippin' flips */
+ FVECT unrm;
+ unrm[0] = -r->ron[0];
+ unrm[1] = -r->ron[1];
+ unrm[2] = -r->ron[2];
+ (*putreal)(unrm, 3);
+ } else
+ (*putreal)(r->ron, 3);
}
static void
-oputn(r) /* print perturbed normal */
-RAY *r;
+oputn( /* print perturbed normal */
+ RAY *r
+)
{
FVECT pnorm;
- if (r->rot >= FHUGE) {
- (*putreal)(0.0);
- (*putreal)(0.0);
- (*putreal)(0.0);
+ if (r->ro == NULL) { /* clipped or no hit */
+ (*putreal)(vdummy, 3);
return;
}
raynormal(pnorm, r);
- (*putreal)(pnorm[0]);
- (*putreal)(pnorm[1]);
- (*putreal)(pnorm[2]);
+ (*putreal)(pnorm, 3);
}
static void
-oputs(r) /* print name */
-register RAY *r;
+oputs( /* print name */
+ RAY *r
+)
{
if (r->ro != NULL)
fputs(r->ro->oname, stdout);
@@ -601,17 +839,37 @@ register RAY *r;
static void
-oputw(r) /* print weight */
-register RAY *r;
+oputw( /* print weight */
+ RAY *r
+)
{
- (*putreal)(r->rweight);
+ RREAL rwt = r->rweight;
+
+ (*putreal)(&rwt, 1);
}
static void
-oputm(r) /* print modifier */
-register RAY *r;
+oputW( /* print coefficient */
+ RAY *r
+)
{
+ SCOLOR contr;
+ /* shadow ray not on source? */
+ if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
+ scolorblack(contr);
+ else
+ raycontrib(contr, r, PRIMARY);
+
+ putscolor(contr);
+}
+
+
+static void
+oputm( /* print modifier */
+ RAY *r
+)
+{
if (r->ro != NULL)
if (r->ro->omod != OVOID)
fputs(objptr(r->ro->omod)->oname, stdout);
@@ -624,26 +882,133 @@ register RAY *r;
static void
-puta(v) /* print ascii value */
-double v;
+oputM( /* print material */
+ RAY *r
+)
{
- printf("%e\t", v);
+ OBJREC *mat;
+
+ if (r->ro != NULL) {
+ if ((mat = findmaterial(r->ro)) != NULL)
+ fputs(mat->oname, stdout);
+ else
+ fputs(VOIDID, stdout);
+ } else
+ putchar('*');
+ putchar('\t');
}
static void
-putd(v) /* print binary double */
-double v;
+oputtilde( /* output tilde (spacer) */
+ RAY *r
+)
{
- fwrite((char *)&v, sizeof(v), 1, stdout);
+ fputs("~\t", stdout);
}
static void
-putf(v) /* print binary float */
-double v;
+puta( /* print ascii value(s) */
+ RREAL *v, int n
+)
{
- float f = v;
+ if (n == 3) {
+ printf("%e\t%e\t%e\t", v[0], v[1], v[2]);
+ return;
+ }
+ while (n--)
+ printf("%e\t", *v++);
+}
- fwrite((char *)&f, sizeof(f), 1, stdout);
+
+static void
+putd(RREAL *v, int n) /* output binary double(s) */
+{
+#ifdef SMLFLT
+ double da[3];
+ int i;
+
+ if (n > 3)
+ error(INTERNAL, "code error in putd()");
+ for (i = n; i--; )
+ da[i] = v[i];
+ putbinary(da, sizeof(double), n, stdout);
+#else
+ putbinary(v, sizeof(RREAL), n, stdout);
+#endif
+}
+
+
+static void
+putf(RREAL *v, int n) /* output binary float(s) */
+{
+#ifndef SMLFLT
+ float fa[3];
+ int i;
+
+ if (n > 3)
+ error(INTERNAL, "code error in putf()");
+ for (i = n; i--; )
+ fa[i] = v[i];
+ putbinary(fa, sizeof(float), n, stdout);
+#else
+ putbinary(v, sizeof(RREAL), n, stdout);
+#endif
+}
+
+
+static void
+putscolor(const COLORV *scol) /* output (spectral) color */
+{
+ static COLORMAT xyz2myrgbmat;
+ SCOLOR my_scol;
+ COLOR col;
+ /* apply scalefactor if any */
+ if (out_scalefactor != 1.) {
+ copyscolor(my_scol, scol);
+ scalescolor(my_scol, out_scalefactor);
+ scol = my_scol;
+ }
+ if (sens_curve != NULL) { /* single channel output */
+ RREAL v = (*sens_curve)(scol);
+ (*putreal)(&v, 1);
+ return;
+ }
+ if (out_prims == NULL) { /* full spectral reporting */
+ if (outform == 'c') {
+ SCOLR sclr;
+ scolor_scolr(sclr, scol);
+ putbinary(sclr, LSCOLR, 1, stdout);
+ } else if (sizeof(RREAL) != sizeof(COLORV)) {
+ RREAL sreal[MAXCSAMP];
+ int i = NCSAMP;
+ while (i--) sreal[i] = scol[i];
+ (*putreal)(sreal, NCSAMP);
+ } else
+ (*putreal)((RREAL *)scol, NCSAMP);
+ return;
+ }
+ if (out_prims == xyzprims) {
+ scolor_cie(col, scol);
+ } else if (out_prims == stdprims) {
+ scolor_rgb(col, scol);
+ } else {
+ COLOR xyz;
+ if (xyz2myrgbmat[0][0] == 0)
+ compxyz2rgbWBmat(xyz2myrgbmat, out_prims);
+ scolor_cie(xyz, scol);
+ colortrans(col, xyz2myrgbmat, xyz);
+ clipgamut(col, xyz[CIEY], CGAMUT_LOWER, cblack, cwhite);
+ }
+ if (outform == 'c') {
+ COLR clr;
+ setcolr(clr, colval(col,RED), colval(col,GRN), colval(col,BLU));
+ putbinary(clr, sizeof(COLR), 1, stdout);
+ } else if (sizeof(RREAL) != sizeof(COLORV)) {
+ RREAL creal[3];
+ copycolor(creal, col);
+ (*putreal)(creal, 3);
+ } else
+ (*putreal)((RREAL *)col, 3);
}