home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / RT / FUNC.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  8KB  |  321 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)func.c 2.7 9/26/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  func.c - interface to calcomp functions.
  9.  *
  10.  *     4/7/86
  11.  */
  12.  
  13. #include  "ray.h"
  14.  
  15. #include  "otypes.h"
  16.  
  17. #include  "func.h"
  18.  
  19.  
  20. #define  INITFILE    "rayinit.cal"
  21. #define  REFVNAME    "`FILE_REFCNT"
  22. #define  CALSUF        ".cal"
  23. #define  LCALSUF    4
  24.  
  25. XF  unitxf = {            /* identity transform */
  26.     1.0, 0.0, 0.0, 0.0,
  27.     0.0, 1.0, 0.0, 0.0,
  28.     0.0, 0.0, 1.0, 0.0,
  29.     0.0, 0.0, 0.0, 1.0,
  30.     1.0
  31. };
  32.  
  33. XF  funcxf;            /* current transformation */
  34. static OBJREC  *fobj = NULL;    /* current function object */
  35. static RAY  *fray = NULL;    /* current function ray */
  36.  
  37. static double  l_erf(), l_erfc(), l_arg();
  38.  
  39.  
  40. MFUNC *
  41. getfunc(m, ff, ef, dofwd)    /* get function for this modifier */
  42. OBJREC  *m;
  43. int  ff;
  44. unsigned  ef;
  45. int  dofwd;
  46. {
  47.     extern EPNODE  *curfunc;
  48.     static char  initfile[] = INITFILE;
  49.     char  sbuf[MAXSTR];
  50.     register char  **arg;
  51.     register MFUNC  *f;
  52.     int  ne, na;
  53.     register int  i;
  54.                     /* check to see if done already */
  55.     if ((f = (MFUNC *)m->os) != NULL)
  56.         return(f);
  57.     fobj = NULL; fray = NULL;
  58.     if (initfile[0]) {        /* initialize on first call */
  59.         setcontext("");
  60.         scompile("Dx=$1;Dy=$2;Dz=$3;", NULL, 0);
  61.         scompile("Nx=$4;Ny=$5;Nz=$6;", NULL, 0);
  62.         scompile("Px=$7;Py=$8;Pz=$9;", NULL, 0);
  63.         scompile("T=$10;Ts=$25;Rdot=$11;", NULL, 0);
  64.         scompile("S=$12;Tx=$13;Ty=$14;Tz=$15;", NULL, 0);
  65.         scompile("Ix=$16;Iy=$17;Iz=$18;", NULL, 0);
  66.         scompile("Jx=$19;Jy=$20;Jz=$21;", NULL, 0);
  67.         scompile("Kx=$22;Ky=$23;Kz=$24;", NULL, 0);
  68.         funset("arg", 1, '=', l_arg);
  69.         funset("erf", 1, ':', l_erf);
  70.         funset("erfc", 1, ':', l_erfc);
  71.         setnoisefuncs();
  72.         loadfunc(initfile);
  73.         initfile[0] = '\0';
  74.     }
  75.     if ((na = m->oargs.nsargs) <= ff)
  76.         goto toofew;
  77.     arg = m->oargs.sarg;
  78.     if ((f = (MFUNC *)calloc(1, sizeof(MFUNC))) == NULL)
  79.         goto memerr;
  80.     i = strlen(arg[ff]);            /* set up context */
  81.     if (i == 1 && arg[ff][0] == '.')
  82.         setcontext(f->ctx = "");    /* "." means no file */
  83.     else {
  84.         strcpy(sbuf,arg[ff]);    /* file name is context */
  85.         if (i > LCALSUF && !strcmp(sbuf+i-LCALSUF, CALSUF))
  86.             sbuf[i-LCALSUF] = '\0';    /* remove suffix */
  87.         setcontext(f->ctx = savestr(sbuf));
  88.         if (!vardefined(REFVNAME)) {    /* file loaded? */
  89.             loadfunc(arg[ff]);
  90.             varset(REFVNAME, '=', 1.0);
  91.         } else                /* reference_count++ */
  92.             varset(REFVNAME, '=', varvalue(REFVNAME)+1.0);
  93.     }
  94.     curfunc = NULL;            /* parse expressions */
  95.     sprintf(sbuf, "%s \"%s\"", ofun[m->otype].funame, m->oname);
  96.     for (i=0, ne=0; ef && i < na; i++, ef>>=1)
  97.         if (ef & 1) {            /* flagged as an expression? */
  98.             if (ne >= MAXEXPR)
  99.                 objerror(m, INTERNAL, "too many expressions");
  100.             initstr(arg[i], sbuf, 0);
  101.             f->ep[ne++] = getE1();
  102.             if (nextc != EOF)
  103.                 syntax("unexpected character");
  104.         }
  105.     if (ef)
  106.         goto toofew;
  107.     if (i <= ff)            /* find transform args */
  108.         i = ff+1;
  109.     while (i < na && arg[i][0] != '-')
  110.         i++;
  111.     if (i == na)            /* no transform */
  112.         f->f = f->b = &unitxf;
  113.     else {                /* get transform */
  114.         if ((f->b = (XF *)malloc(sizeof(XF))) == NULL)
  115.             goto memerr;
  116.         if (invxf(f->b, na-i, arg+i) != na-i)
  117.             objerror(m, USER, "bad transform");
  118.         if (f->b->sca < 0.0)
  119.             f->b->sca = -f->b->sca;
  120.         if (dofwd) {            /* do both transforms */
  121.             if ((f->f = (XF *)malloc(sizeof(XF))) == NULL)
  122.                 goto memerr;
  123.             xf(f->f, na-i, arg+i);
  124.             if (f->f->sca < 0.0)
  125.                 f->f->sca = -f->f->sca;
  126.         }
  127.     }
  128.     m->os = (char *)f;
  129.     return(f);
  130. toofew:
  131.     objerror(m, USER, "too few string arguments");
  132. memerr:
  133.     error(SYSTEM, "out of memory in getfunc");
  134. }
  135.  
  136.  
  137. freefunc(m)            /* free memory associated with modifier */
  138. OBJREC  *m;
  139. {
  140.     register MFUNC  *f;
  141.     register int  i;
  142.  
  143.     if ((f = (MFUNC *)m->os) == NULL)
  144.         return;
  145.     for (i = 0; f->ep[i] != NULL; i++)
  146.         epfree(f->ep[i]);
  147.     if (f->ctx[0]) {            /* done with definitions */
  148.         setcontext(f->ctx);
  149.         i = varvalue(REFVNAME)-.5;    /* reference_count-- */
  150.         if (i > 0)
  151.             varset(REFVNAME, '=', (double)i);
  152.         else
  153.             dcleanup(2);        /* remove definitions */
  154.         freestr(f->ctx);
  155.     }
  156.     if (f->b != &unitxf)
  157.         free((char *)f->b);
  158.     if (f->f != NULL && f->f != &unitxf)
  159.         free((char *)f->f);
  160.     free((char *)f);
  161.     m->os = NULL;
  162. }
  163.  
  164.  
  165. setfunc(m, r)            /* set channels for function call */
  166. OBJREC  *m;
  167. register RAY  *r;
  168. {
  169.     static long  lastrno = -1;
  170.     register MFUNC  *f;
  171.                     /* get function */
  172.     if ((f = (MFUNC *)m->os) == NULL)
  173.         error(m, CONSISTENCY, "setfunc called before getfunc");
  174.                     /* set evaluator context */
  175.     setcontext(f->ctx);
  176.                     /* check to see if matrix set */
  177.     if (m == fobj && r->rno == lastrno)
  178.         return(0);
  179.     fobj = m;
  180.     fray = r;
  181.     if (r->rox != NULL)
  182.         if (f->b != &unitxf) {
  183.             funcxf.sca = r->rox->b.sca * f->b->sca;
  184.             multmat4(funcxf.xfm, r->rox->b.xfm, f->b->xfm);
  185.         } else
  186.             copystruct(&funcxf, &r->rox->b);
  187.     else
  188.         copystruct(&funcxf, f->b);
  189.     lastrno = r->rno;
  190.     eclock++;        /* notify expression evaluator */
  191.     return(1);
  192. }
  193.  
  194.  
  195. loadfunc(fname)            /* load definition file */
  196. char  *fname;
  197. {
  198.     extern char  *libpath;        /* library search path */
  199.     char  *ffname;
  200.  
  201.     if ((ffname = getpath(fname, libpath, R_OK)) == NULL) {
  202.         sprintf(errmsg, "cannot find function file \"%s\"", fname);
  203.         error(USER, errmsg);
  204.     }
  205.     fcompile(ffname);
  206. }
  207.  
  208.  
  209. static double
  210. l_arg()                /* return nth real argument */
  211. {
  212.     extern double  argument();
  213.     register int  n;
  214.  
  215.     if (fobj == NULL)
  216.         syntax("arg(n) used in constant expression");
  217.  
  218.     n = argument(1) + .5;        /* round to integer */
  219.  
  220.     if (n < 1)
  221.         return(fobj->oargs.nfargs);
  222.  
  223.     if (n > fobj->oargs.nfargs) {
  224.         sprintf(errmsg, "missing real argument %d", n);
  225.         objerror(fobj, USER, errmsg);
  226.     }
  227.     return(fobj->oargs.farg[n-1]);
  228. }
  229.  
  230.  
  231. static double
  232. l_erf()                /* error function */
  233. {
  234.     extern double  erf();
  235.  
  236.     return(erf(argument(1)));
  237. }
  238.  
  239.  
  240. static double
  241. l_erfc()            /* cumulative error function */
  242. {
  243.     extern double  erfc();
  244.  
  245.     return(erfc(argument(1)));
  246. }
  247.  
  248.  
  249. double
  250. chanvalue(n)            /* return channel n to calcomp */
  251. register int  n;
  252. {
  253.     double  sum;
  254.     register RAY  *r;
  255.  
  256.     if (fray == NULL)
  257.         syntax("ray parameter used in constant expression");
  258.  
  259.     if (--n < 0)
  260.         goto badchan;
  261.  
  262.     if (n < 3)            /* ray direction */
  263.  
  264.         return( (    fray->rdir[0]*funcxf.xfm[0][n] +
  265.                 fray->rdir[1]*funcxf.xfm[1][n] +
  266.                 fray->rdir[2]*funcxf.xfm[2][n]    )
  267.              / funcxf.sca );
  268.  
  269.     if (n < 6)            /* surface normal */
  270.  
  271.         return( (    fray->ron[0]*funcxf.xfm[0][n-3] +
  272.                 fray->ron[1]*funcxf.xfm[1][n-3] +
  273.                 fray->ron[2]*funcxf.xfm[2][n-3]    )
  274.              / funcxf.sca );
  275.  
  276.     if (n < 9)            /* intersection */
  277.  
  278.         return( fray->rop[0]*funcxf.xfm[0][n-6] +
  279.                 fray->rop[1]*funcxf.xfm[1][n-6] +
  280.                 fray->rop[2]*funcxf.xfm[2][n-6] +
  281.                          funcxf.xfm[3][n-6] );
  282.  
  283.     if (n == 9) {            /* total distance */
  284.         sum = fray->rot;
  285.         for (r = fray->parent; r != NULL; r = r->parent)
  286.             sum += r->rot;
  287.         return(sum * funcxf.sca);
  288.  
  289.     }
  290.  
  291.     if (n == 10)            /* dot product (range [-1,1]) */
  292.         return(    fray->rod <= -1.0 ? -1.0 :
  293.             fray->rod >= 1.0 ? 1.0 :
  294.             fray->rod );
  295.  
  296.     if (n == 11)            /* scale */
  297.         return(funcxf.sca);
  298.  
  299.     if (n < 15)            /* origin */
  300.         return(funcxf.xfm[3][n-12]);
  301.  
  302.     if (n < 18)            /* i unit vector */
  303.         return(funcxf.xfm[0][n-15] / funcxf.sca);
  304.  
  305.     if (n < 21)            /* j unit vector */
  306.         return(funcxf.xfm[1][n-15] / funcxf.sca);
  307.  
  308.     if (n < 24)            /* k unit vector */
  309.         return(funcxf.xfm[2][n-21] / funcxf.sca);
  310.  
  311.     if (n == 24) {            /* single ray (shadow) distance */
  312.         sum = fray->rot;
  313.         for (r = fray->parent; r != NULL && r->crtype&SHADOW;
  314.                 r = r->parent)
  315.             sum += r->rot;
  316.         return(sum * funcxf.sca);
  317.     }
  318. badchan:
  319.     error(USER, "illegal channel number");
  320. }
  321.