Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F70478281
func.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Jul 7, 01:50
Size
8 KB
Mime Type
text/x-c
Expires
Tue, Jul 9, 01:50 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
18763232
Attached To
R10977 RADIANCE Photon Map
func.c
View Options
#ifndef lint
static const char RCSid[] = "$Id: func.c,v 2.38 2020/04/02 18:00:34 greg Exp $";
#endif
/*
* func.c - interface to calcomp functions.
*/
#include "copyright.h"
#include "ray.h"
#include "paths.h"
#include "otypes.h"
#include "func.h"
#include <ctype.h>
#define INITFILE "rayinit.cal"
#define CALSUF ".cal"
#define LCALSUF 4
char REFVNAME[] = "`FILE_REFCNT";
XF unitxf = { /* identity transform */
{{1.0, 0.0, 0.0, 0.0},
{0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0},
{0.0, 0.0, 0.0, 1.0}},
1.0
};
XF funcxf; /* current transformation */
static OBJREC *fobj = NULL; /* current function object */
static RAY *fray = NULL; /* current function ray */
static char rayinitcal[] = INITFILE;
static double l_erf(char *), l_erfc(char *), l_arg(char *);
void
initfunc(void) /* initialize function evaluation */
{
if (!rayinitcal[0]) /* already done? */
return;
esupport |= E_VARIABLE|E_FUNCTION|E_INCHAN|E_RCONST|E_REDEFW;
esupport &= ~(E_OUTCHAN);
setcontext("");
scompile("Dx=$1;Dy=$2;Dz=$3;", NULL, 0);
scompile("Nx=$4;Ny=$5;Nz=$6;", NULL, 0);
scompile("Px=$7;Py=$8;Pz=$9;", NULL, 0);
scompile("T=$10;Ts=$25;Rdot=$11;", NULL, 0);
scompile("S=$12;Tx=$13;Ty=$14;Tz=$15;", NULL, 0);
scompile("Ix=$16;Iy=$17;Iz=$18;", NULL, 0);
scompile("Jx=$19;Jy=$20;Jz=$21;", NULL, 0);
scompile("Kx=$22;Ky=$23;Kz=$24;", NULL, 0);
scompile("Lu=$26;Lv=$27;", NULL, 0);
funset("arg", 1, '=', l_arg);
funset("erf", 1, ':', l_erf);
funset("erfc", 1, ':', l_erfc);
setnoisefuncs();
setprismfuncs();
loadfunc(rayinitcal);
rayinitcal[0] = '\0';
}
/* Set parameters for current evaluation */
void
set_eparams(char *prms)
{
static char *last_params = NULL;
char vname[RMAXWORD];
double value;
char *cpd;
/* check if already set */
if (prms == NULL || !*prms)
return;
if (prms == last_params || (last_params != NULL &&
!strcmp(prms, last_params)))
return;
last_params = prms; /* XXX assumes static string */
/* assign each variable */
while (*prms) {
if (isspace(*prms)) {
++prms; continue;
}
if (!isalpha(*prms))
goto bad_params;
cpd = vname;
while (*prms && (*prms != '=') & !isspace(*prms)) {
if (!isid(*prms) | (cpd-vname >= RMAXWORD-1))
goto bad_params;
*cpd++ = *prms++;
}
*cpd = '\0';
while (isspace(*prms)) prms++;
if (*prms++ != '=')
goto bad_params;
value = atof(prms);
if ((prms = fskip(prms)) == NULL)
goto bad_params;
while (isspace(*prms)) prms++;
prms += (*prms == ',') | (*prms == ';') | (*prms == ':');
varset(vname, '=', value);
}
eclock++; /* notify expression evaluator */
return;
bad_params:
sprintf(errmsg, "bad parameter list '%s'", last_params);
error(USER, errmsg);
}
MFUNC *
getfunc( /* get function for this modifier */
OBJREC *m,
int ff,
unsigned int ef,
int dofwd
)
{
char sbuf[MAXSTR];
char **arg;
MFUNC *f;
int ne, na;
int i;
/* check to see if done already */
if ((f = (MFUNC *)m->os) != NULL)
return(f);
fobj = NULL; fray = NULL;
if (rayinitcal[0]) /* initialize on first call */
initfunc();
if ((na = m->oargs.nsargs) <= ff)
goto toofew;
arg = m->oargs.sarg;
if ((f = (MFUNC *)calloc(1, sizeof(MFUNC))) == NULL)
goto memerr;
i = strlen(arg[ff]); /* set up context */
if (i == 1 && arg[ff][0] == '.') {
setcontext(f->ctx = ""); /* "." means no file */
} else {
strcpy(sbuf,arg[ff]); /* file name is context */
if (i > LCALSUF && !strcmp(sbuf+i-LCALSUF, CALSUF))
sbuf[i-LCALSUF] = '\0'; /* remove suffix */
setcontext(f->ctx = savestr(sbuf));
if (!vardefined(REFVNAME)) { /* file loaded? */
loadfunc(arg[ff]);
varset(REFVNAME, '=', 1.0);
} else /* reference_count++ */
varset(REFVNAME, '=', varvalue(REFVNAME)+1.0);
}
curfunc = NULL; /* parse expressions */
sprintf(sbuf, "%s \"%s\"", ofun[m->otype].funame, m->oname);
for (i=0, ne=0; ef && i < na; i++, ef>>=1)
if (ef & 1) { /* flagged as an expression? */
if (ne >= MAXEXPR)
objerror(m, INTERNAL, "too many expressions");
initstr(arg[i], sbuf, 0);
f->ep[ne++] = getE1();
if (nextc != EOF)
syntax("unexpected character");
}
if (ef)
goto toofew;
if (i <= ff) /* find transform args */
i = ff+1;
while (i < na && arg[i][0] != '-')
i++;
if (i == na) { /* no transform */
f->fxp = f->bxp = &unitxf;
} else { /* get transform */
if ((f->bxp = (XF *)malloc(sizeof(XF))) == NULL)
goto memerr;
if (invxf(f->bxp, na-i, arg+i) != na-i)
objerror(m, USER, "bad transform");
if (f->bxp->sca < 0.0)
f->bxp->sca = -f->bxp->sca;
if (dofwd) { /* do both transforms */
if ((f->fxp = (XF *)malloc(sizeof(XF))) == NULL)
goto memerr;
xf(f->fxp, na-i, arg+i);
if (f->fxp->sca < 0.0)
f->fxp->sca = -f->fxp->sca;
}
}
m->os = (char *)f;
return(f);
toofew:
objerror(m, USER, "too few string arguments");
memerr:
error(SYSTEM, "out of memory in getfunc");
return NULL; /* pro forma return */
}
void
freefunc( /* free memory associated with modifier */
OBJREC *m
)
{
MFUNC *f;
int i;
if ((f = (MFUNC *)m->os) == NULL)
return;
for (i = 0; f->ep[i] != NULL; i++)
epfree(f->ep[i]);
if (f->ctx[0]) { /* done with definitions */
setcontext(f->ctx);
i = varvalue(REFVNAME)-.5; /* reference_count-- */
if (i > 0)
varset(REFVNAME, '=', (double)i);
else
dcleanup(2); /* remove definitions */
freestr(f->ctx);
}
if (f->bxp != &unitxf)
free((void *)f->bxp);
if ((f->fxp != NULL) & (f->fxp != &unitxf))
free((void *)f->fxp);
free((void *)f);
m->os = NULL;
}
int
setfunc( /* set channels for function call */
OBJREC *m,
RAY *r
)
{
static RNUMBER lastrno = ~0;
MFUNC *f;
/* get function if any */
if ((f = (MFUNC *)m->os) == NULL)
objerror(m, CONSISTENCY, "setfunc called before getfunc");
setcontext(f->ctx); /* set evaluator context */
/* check to see if matrix set */
if ((m == fobj) & (r->rno == lastrno))
return(0);
fobj = m;
fray = r;
if (r->rox != NULL) {
if (f->bxp != &unitxf) {
funcxf.sca = r->rox->b.sca * f->bxp->sca;
multmat4(funcxf.xfm, r->rox->b.xfm, f->bxp->xfm);
} else
funcxf = r->rox->b;
} else
funcxf = *f->bxp;
lastrno = r->rno;
eclock++; /* notify expression evaluator */
return(1);
}
int
worldfunc( /* special function context sans object */
char *ctx,
RAY *r
)
{
static RNUMBER lastrno = ~0;
if (rayinitcal[0]) /* initialize on first call */
initfunc();
/* set evaluator context */
setcontext(ctx);
/* check if ray already set */
if ((fobj == NULL) & (r->rno == lastrno))
return(0);
fobj = NULL;
fray = r;
funcxf = unitxf;
lastrno = r->rno;
eclock++; /* notify expression evaluator */
return(1);
}
void
loadfunc( /* load definition file */
char *fname
)
{
char *ffname;
if ((ffname = getpath(fname, getrlibpath(), R_OK)) == NULL) {
sprintf(errmsg, "cannot find function file \"%s\"", fname);
error(SYSTEM, errmsg);
}
fcompile(ffname);
}
static double
l_arg(char *nm) /* return nth real argument */
{
int n;
if (fobj == NULL)
error(USER,
"bad call to arg(n) - illegal constant in .cal file?");
n = argument(1) + .5; /* round to integer */
if (n < 1)
return(fobj->oargs.nfargs);
if (n > fobj->oargs.nfargs) {
sprintf(errmsg, "missing real argument %d", n);
objerror(fobj, USER, errmsg);
}
return(fobj->oargs.farg[n-1]);
}
static double
l_erf(char *nm) /* error function */
{
return(erf(argument(1)));
}
static double
l_erfc(char *nm) /* cumulative error function */
{
return(erfc(argument(1)));
}
double
chanvalue( /* return channel n to calcomp */
int n
)
{
if (fray == NULL)
syntax("ray parameter used in constant expression");
if (--n < 0)
goto badchan;
if (n <= 2) /* ray direction */
return( ( fray->rdir[0]*funcxf.xfm[0][n] +
fray->rdir[1]*funcxf.xfm[1][n] +
fray->rdir[2]*funcxf.xfm[2][n] )
/ funcxf.sca );
if (n <= 5) /* surface normal */
return( ( fray->ron[0]*funcxf.xfm[0][n-3] +
fray->ron[1]*funcxf.xfm[1][n-3] +
fray->ron[2]*funcxf.xfm[2][n-3] )
/ funcxf.sca );
if (n <= 8) { /* intersection point */
if (fray->rot >= FHUGE*.99)
return(0.0); /* XXX should be runtime error? */
return( fray->rop[0]*funcxf.xfm[0][n-6] +
fray->rop[1]*funcxf.xfm[1][n-6] +
fray->rop[2]*funcxf.xfm[2][n-6] +
funcxf.xfm[3][n-6] );
}
if (n == 9) /* total distance */
return(raydist(fray,PRIMARY) * funcxf.sca);
if (n == 10) /* dot product (range [-1,1]) */
return( fray->rod <= -1.0 ? -1.0 :
fray->rod >= 1.0 ? 1.0 :
fray->rod );
if (n == 11) /* scale */
return(funcxf.sca);
if (n <= 14) /* origin */
return(funcxf.xfm[3][n-12]);
if (n <= 17) /* i unit vector */
return(funcxf.xfm[0][n-15] / funcxf.sca);
if (n <= 20) /* j unit vector */
return(funcxf.xfm[1][n-18] / funcxf.sca);
if (n <= 23) /* k unit vector */
return(funcxf.xfm[2][n-21] / funcxf.sca);
if (n == 24) /* single ray (shadow) distance */
return((fray->rot+raydist(fray->parent,SHADOW)) * funcxf.sca);
if (n <= 26) /* local (u,v) coordinates */
return(fray->uv[n-25]);
badchan:
error(USER, "illegal channel number");
return(0.0);
}
Event Timeline
Log In to Comment