home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 8
/
CDASC08.ISO
/
NEWS
/
RADIANCE
/
SRC
/
RT
/
RTRACE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-07
|
10KB
|
497 lines
/* 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);
}