home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1992 Regents of the University of California */
-
- #ifndef lint
- static char SCCSid[] = "@(#)rtrace.c 2.9 11/6/92 LBL";
- #endif
-
- /*
- * rtrace.c - program and variables for individual ray tracing.
- *
- * 6/11/86
- */
-
- /*
- * Input is in the form:
- *
- * xorg yorg zorg xdir ydir zdir
- *
- * The direction need not be normalized. Output is flexible.
- * If the direction vector is (0,0,0), then the output is flushed.
- * All values default to ascii representation of real
- * numbers. Binary representations can be selected
- * with '-ff' for float or '-fd' for double. By default,
- * radiance is computed. The '-i' or '-I' options indicate that
- * irradiance values are desired.
- */
-
- #include "ray.h"
-
- #include "octree.h"
-
- #include "otypes.h"
-
- #include "resolu.h"
-
- int dimlist[MAXDIM]; /* sampling dimensions */
- int ndims = 0; /* number of sampling dimensions */
- int samplendx = 0; /* index for this sample */
-
- int imm_irrad = 0; /* compute immediate irradiance? */
-
- int inform = 'a'; /* input format */
- int outform = 'a'; /* output format */
- char *outvals = "v"; /* output specification */
-
- int hresolu = 0; /* horizontal (scan) size */
- int vresolu = 0; /* vertical resolution */
-
- double dstrsrc = 0.0; /* square source distribution */
- double shadthresh = .05; /* shadow threshold */
- double shadcert = .5; /* shadow certainty */
- int directrelay = 1; /* number of source relays */
- int vspretest = 512; /* virtual source pretest density */
- int directinvis = 0; /* sources invisible? */
- double srcsizerat = .25; /* maximum ratio source size/dist. */
-
- double specthresh = .15; /* specular sampling threshold */
- double specjitter = 1.; /* specular sampling jitter */
-
- int maxdepth = 6; /* maximum recursion depth */
- double minweight = 4e-3; /* minimum ray weight */
-
- COLOR ambval = BLKCOLOR; /* ambient value */
- double ambacc = 0.2; /* ambient accuracy */
- int ambres = 32; /* ambient resolution */
- int ambdiv = 128; /* 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 OBJREC Lamb; /* a Lambertian surface */
-
- static RAY thisray; /* for our convenience */
-
- static int oputo(), oputd(), oputv(), oputl(), oputL(),
- oputp(), oputn(), oputN(), oputs(), oputw(), oputm();
-
- static int (*ray_out[10])(), (*every_out[10])();
- static int castonly;
-
- static int puta(), putf(), putd();
-
- static int (*putreal)();
-
-
- quit(code) /* quit program */
- int code;
- {
- exit(code);
- }
-
-
- char *
- formstr(f) /* return format identifier */
- int f;
- {
- switch (f) {
- case 'a': return("ascii");
- case 'f': return("float");
- case 'd': return("double");
- case 'c': return(COLRFMT);
- }
- return("unknown");
- }
-
-
- rtrace(fname) /* trace rays from file */
- char *fname;
- {
- long vcount = hresolu>1 ? hresolu*vresolu : vresolu;
- long nextflush = hresolu;
- FILE *fp;
- FVECT orig, direc;
- /* set up input */
- if (fname == NULL)
- fp = stdin;
- else if ((fp = 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);
- #endif
- /* 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 (hresolu > 0 && vresolu > 0)
- fprtresolu(hresolu, vresolu, stdout);
- /* process file */
- while (getvec(orig, inform, fp) == 0 &&
- getvec(direc, inform, fp) == 0) {
-
- if (normalize(direc) == 0.0) { /* zero ==> flush */
- fflush(stdout);
- continue;
- }
- samplendx++;
- /* compute and print */
- if (imm_irrad)
- irrad(orig, direc);
- else
- traceray(orig, direc);
- /* flush if time */
- if (--nextflush == 0) {
- fflush(stdout);
- nextflush = hresolu;
- }
- if (ferror(stdout))
- error(SYSTEM, "write error");
- if (--vcount == 0) /* check for end */
- break;
- }
- if (vcount > 0)
- error(USER, "read error");
- fclose(fp);
- }
-
-
- setoutput(vs) /* set up output tables */
- register char *vs;
- {
- extern int ourtrace(), (*trace)();
- register int (**table)() = ray_out;
-
- castonly = 1;
- while (*vs)
- switch (*vs++) {
- case 't': /* trace */
- *table = NULL;
- table = every_out;
- trace = ourtrace;
- castonly = 0;
- break;
- case 'o': /* origin */
- *table++ = oputo;
- break;
- case 'd': /* direction */
- *table++ = oputd;
- break;
- case 'v': /* value */
- *table++ = oputv;
- castonly = 0;
- break;
- case 'l': /* effective distance */
- *table++ = oputl;
- castonly = 0;
- break;
- case 'L': /* single ray length */
- *table++ = oputL;
- break;
- case 'p': /* point */
- *table++ = oputp;
- break;
- case 'n': /* perturbed normal */
- *table++ = oputn;
- castonly = 0;
- break;
- case 'N': /* unperturbed normal */
- *table++ = oputN;
- break;
- case 's': /* surface */
- *table++ = oputs;
- break;
- case 'w': /* weight */
- *table++ = oputw;
- break;
- case 'm': /* modifier */
- *table++ = oputm;
- break;
- }
- *table = NULL;
- }
-
-
- traceray(org, dir) /* compute and print ray value(s) */
- FVECT org, dir;
- {
- register int (**tp)();
-
- VCOPY(thisray.rorg, org);
- VCOPY(thisray.rdir, dir);
- rayorigin(&thisray, NULL, PRIMARY, 1.0);
- if (castonly)
- localhit(&thisray, &thescene) || sourcehit(&thisray);
- else
- rayvalue(&thisray);
-
- if (ray_out[0] == NULL)
- return;
- for (tp = ray_out; *tp != NULL; tp++)
- (**tp)(&thisray);
- if (outform == 'a')
- putchar('\n');
- }
-
-
- irrad(org, dir) /* compute immediate irradiance value */
- FVECT org, dir;
- {
- register int i;
-
- for (i = 0; i < 3; i++) {
- thisray.rorg[i] = org[i] + dir[i];
- thisray.rdir[i] = -dir[i];
- }
- rayorigin(&thisray, NULL, PRIMARY, 1.0);
- /* pretend we hit surface */
- thisray.rot = 1.0;
- 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);
- oputv(&thisray);
- if (outform == 'a')
- putchar('\n');
- }
-
-
- getvec(vec, fmt, fp) /* get a vector from fp */
- register FVECT vec;
- int fmt;
- FILE *fp;
- {
- extern char *fgetword();
- static float vf[3];
- static double vd[3];
- char buf[32];
- register int i;
-
- switch (fmt) {
- case 'a': /* ascii */
- for (i = 0; i < 3; i++) {
- if (fgetword(buf, sizeof(buf), fp) == NULL ||
- !isflt(buf))
- return(-1);
- vec[i] = atof(buf);
- }
- break;
- case 'f': /* binary float */
- if (fread((char *)vf, sizeof(float), 3, fp) != 3)
- return(-1);
- vec[0] = vf[0]; vec[1] = vf[1]; vec[2] = vf[2];
- break;
- case 'd': /* binary double */
- if (fread((char *)vd, sizeof(double), 3, fp) != 3)
- return(-1);
- vec[0] = vd[0]; vec[1] = vd[1]; vec[2] = vd[2];
- break;
- default:
- error(CONSISTENCY, "botched input format");
- }
- return(0);
- }
-
-
- static
- ourtrace(r) /* print ray values */
- RAY *r;
- {
- register int (**tp)();
-
- if (every_out[0] == NULL)
- return;
- tabin(r);
- for (tp = every_out; *tp != NULL; tp++)
- (**tp)(r);
- putchar('\n');
- }
-
-
- static
- tabin(r) /* tab in appropriate amount */
- RAY *r;
- {
- register RAY *rp;
-
- for (rp = r->parent; rp != NULL; rp = rp->parent)
- putchar('\t');
- }
-
-
- static
- oputo(r) /* print origin */
- register RAY *r;
- {
- (*putreal)(r->rorg[0]);
- (*putreal)(r->rorg[1]);
- (*putreal)(r->rorg[2]);
- }
-
-
- static
- oputd(r) /* print direction */
- register RAY *r;
- {
- (*putreal)(r->rdir[0]);
- (*putreal)(r->rdir[1]);
- (*putreal)(r->rdir[2]);
- }
-
-
- static
- oputv(r) /* print value */
- register 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));
- }
-
-
- static
- oputl(r) /* print effective distance */
- register RAY *r;
- {
- (*putreal)(r->rt);
- }
-
-
- static
- oputL(r) /* print single ray length */
- register RAY *r;
- {
- (*putreal)(r->rot);
- }
-
-
- static
- oputp(r) /* print point */
- register 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);
- }
- }
-
-
- static
- oputN(r) /* print unperturbed normal */
- register 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);
- }
- }
-
-
- static
- oputn(r) /* print perturbed normal */
- RAY *r;
- {
- FVECT pnorm;
-
- if (r->rot >= FHUGE) {
- (*putreal)(0.0);
- (*putreal)(0.0);
- (*putreal)(0.0);
- return;
- }
- raynormal(pnorm, r);
- (*putreal)(pnorm[0]);
- (*putreal)(pnorm[1]);
- (*putreal)(pnorm[2]);
- }
-
-
- static
- oputs(r) /* print name */
- register RAY *r;
- {
- if (r->ro != NULL)
- fputs(r->ro->oname, stdout);
- else
- putchar('*');
- putchar('\t');
- }
-
-
- static
- oputw(r) /* print weight */
- register RAY *r;
- {
- (*putreal)(r->rweight);
- }
-
-
- static
- oputm(r) /* print modifier */
- register RAY *r;
- {
- if (r->ro != NULL)
- fputs(objptr(r->ro->omod)->oname, stdout);
- else
- putchar('*');
- putchar('\t');
- }
-
-
- static
- puta(v) /* print ascii value */
- double v;
- {
- printf("%e\t", v);
- }
-
-
- static
- putd(v) /* print binary double */
- double v;
- {
- fwrite((char *)&v, sizeof(v), 1, stdout);
- }
-
-
- static
- putf(v) /* print binary float */
- double v;
- {
- float f = v;
-
- fwrite((char *)&f, sizeof(f), 1, stdout);
- }
-