ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/func.c
(Generate patch)

Comparing ray/src/rt/func.c (file contents):
Revision 1.1 by greg, Thu Feb 2 10:41:23 1989 UTC vs.
Revision 2.14 by greg, Sat Feb 22 02:07:28 2003 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1986 Regents of the University of California */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ LBL";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5   *  func.c - interface to calcomp functions.
6 + */
7 +
8 + /* ====================================================================
9 + * The Radiance Software License, Version 1.0
10   *
11 < *     4/7/86
11 > * Copyright (c) 1990 - 2002 The Regents of the University of California,
12 > * through Lawrence Berkeley National Laboratory.   All rights reserved.
13 > *
14 > * Redistribution and use in source and binary forms, with or without
15 > * modification, are permitted provided that the following conditions
16 > * are met:
17 > *
18 > * 1. Redistributions of source code must retain the above copyright
19 > *         notice, this list of conditions and the following disclaimer.
20 > *
21 > * 2. Redistributions in binary form must reproduce the above copyright
22 > *       notice, this list of conditions and the following disclaimer in
23 > *       the documentation and/or other materials provided with the
24 > *       distribution.
25 > *
26 > * 3. The end-user documentation included with the redistribution,
27 > *           if any, must include the following acknowledgment:
28 > *             "This product includes Radiance software
29 > *                 (http://radsite.lbl.gov/)
30 > *                 developed by the Lawrence Berkeley National Laboratory
31 > *               (http://www.lbl.gov/)."
32 > *       Alternately, this acknowledgment may appear in the software itself,
33 > *       if and wherever such third-party acknowledgments normally appear.
34 > *
35 > * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36 > *       and "The Regents of the University of California" must
37 > *       not be used to endorse or promote products derived from this
38 > *       software without prior written permission. For written
39 > *       permission, please contact [email protected].
40 > *
41 > * 5. Products derived from this software may not be called "Radiance",
42 > *       nor may "Radiance" appear in their name, without prior written
43 > *       permission of Lawrence Berkeley National Laboratory.
44 > *
45 > * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46 > * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47 > * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48 > * DISCLAIMED.   IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49 > * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 > * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51 > * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52 > * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53 > * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54 > * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55 > * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 > * SUCH DAMAGE.
57 > * ====================================================================
58 > *
59 > * This software consists of voluntary contributions made by many
60 > * individuals on behalf of Lawrence Berkeley National Laboratory.   For more
61 > * information on Lawrence Berkeley National Laboratory, please see
62 > * <http://www.lbl.gov/>.
63   */
64  
65   #include  "ray.h"
66  
67   #include  "otypes.h"
68  
69 + #include  "func.h"
70  
18 typedef struct {
19        double  sca;                    /* scalefactor */
20        double  xfm[4][4];              /* transform matrix */
21 }  XF;
71  
72 < static OBJREC  *fobj;           /* current function object */
73 < static RAY  *fray;              /* current function ray */
74 < static XF  fxf;                 /* current transformation */
72 > #define  INITFILE       "rayinit.cal"
73 > #define  CALSUF         ".cal"
74 > #define  LCALSUF        4
75 > char  REFVNAME[] = "`FILE_REFCNT";
76  
77 + XF  unitxf = {                  /* identity transform */
78 +        {{1.0, 0.0, 0.0, 0.0},
79 +        {0.0, 1.0, 0.0, 0.0},
80 +        {0.0, 0.0, 1.0, 0.0},
81 +        {0.0, 0.0, 0.0, 1.0}},
82 +        1.0
83 + };
84  
85 < setmap(m, r, sca, xfm)          /* set channels for function call */
85 > XF  funcxf;                     /* current transformation */
86 > static OBJREC  *fobj = NULL;    /* current function object */
87 > static RAY  *fray = NULL;       /* current function ray */
88 >
89 > static double  l_erf(), l_erfc(), l_arg();
90 >
91 >
92 > MFUNC *
93 > getfunc(m, ff, ef, dofwd)       /* get function for this modifier */
94   OBJREC  *m;
95 < register RAY  *r;
96 < double  sca;
97 < double  xfm[4][4];
95 > int  ff;
96 > unsigned int  ef;
97 > int  dofwd;
98   {
99 <        extern double  l_noise3(), l_noise3a(), l_noise3b(), l_noise3c();
100 <        extern double  l_hermite(), l_fnoise3(), l_arg();
101 <        extern long  eclock;
102 <        static char  *initfile = "rayinit.cal";
103 <
104 <        if (initfile != NULL) {
99 >        static char  initfile[] = INITFILE;
100 >        char  sbuf[MAXSTR];
101 >        register char  **arg;
102 >        register MFUNC  *f;
103 >        int  ne, na;
104 >        register int  i;
105 >                                        /* check to see if done already */
106 >        if ((f = (MFUNC *)m->os) != NULL)
107 >                return(f);
108 >        fobj = NULL; fray = NULL;
109 >        if (initfile[0]) {              /* initialize on first call */
110 >                esupport |= E_VARIABLE|E_FUNCTION|E_INCHAN|E_RCONST|E_REDEFW;
111 >                esupport &= ~(E_OUTCHAN);
112 >                setcontext("");
113 >                scompile("Dx=$1;Dy=$2;Dz=$3;", NULL, 0);
114 >                scompile("Nx=$4;Ny=$5;Nz=$6;", NULL, 0);
115 >                scompile("Px=$7;Py=$8;Pz=$9;", NULL, 0);
116 >                scompile("T=$10;Ts=$25;Rdot=$11;", NULL, 0);
117 >                scompile("S=$12;Tx=$13;Ty=$14;Tz=$15;", NULL, 0);
118 >                scompile("Ix=$16;Iy=$17;Iz=$18;", NULL, 0);
119 >                scompile("Jx=$19;Jy=$20;Jz=$21;", NULL, 0);
120 >                scompile("Kx=$22;Ky=$23;Kz=$24;", NULL, 0);
121 >                funset("arg", 1, '=', l_arg);
122 >                funset("erf", 1, ':', l_erf);
123 >                funset("erfc", 1, ':', l_erfc);
124 >                setnoisefuncs();
125 >                setprismfuncs();
126                  loadfunc(initfile);
127 <                scompile(NULL, "Dx=$1;Dy=$2;Dz=$3;");
42 <                scompile(NULL, "Nx=$4;Ny=$5;Nz=$6;");
43 <                scompile(NULL, "Px=$7;Py=$8;Pz=$9;");
44 <                scompile(NULL, "T=$10;Rdot=$11;");
45 <                funset("arg", 1, l_arg);
46 <                funset("noise3", 3, l_noise3);
47 <                funset("noise3a", 3, l_noise3a);
48 <                funset("noise3b", 3, l_noise3b);
49 <                funset("noise3c", 3, l_noise3c);
50 <                funset("hermite", 5, l_hermite);
51 <                funset("fnoise3", 3, l_fnoise3);
52 <                initfile = NULL;
127 >                initfile[0] = '\0';
128          }
129 <        fobj = m;
130 <        fray = r;
131 <        fxf.sca = r->ros * sca;
132 <        multmat4(fxf.xfm, r->rox, xfm);
133 <        eclock++;               /* notify expression evaluator */
129 >        if ((na = m->oargs.nsargs) <= ff)
130 >                goto toofew;
131 >        arg = m->oargs.sarg;
132 >        if ((f = (MFUNC *)calloc(1, sizeof(MFUNC))) == NULL)
133 >                goto memerr;
134 >        i = strlen(arg[ff]);                    /* set up context */
135 >        if (i == 1 && arg[ff][0] == '.')
136 >                setcontext(f->ctx = "");        /* "." means no file */
137 >        else {
138 >                strcpy(sbuf,arg[ff]);           /* file name is context */
139 >                if (i > LCALSUF && !strcmp(sbuf+i-LCALSUF, CALSUF))
140 >                        sbuf[i-LCALSUF] = '\0'; /* remove suffix */
141 >                setcontext(f->ctx = savestr(sbuf));
142 >                if (!vardefined(REFVNAME)) {    /* file loaded? */
143 >                        loadfunc(arg[ff]);
144 >                        varset(REFVNAME, '=', 1.0);
145 >                } else                          /* reference_count++ */
146 >                        varset(REFVNAME, '=', varvalue(REFVNAME)+1.0);
147 >        }
148 >        curfunc = NULL;                 /* parse expressions */
149 >        sprintf(sbuf, "%s \"%s\"", ofun[m->otype].funame, m->oname);
150 >        for (i=0, ne=0; ef && i < na; i++, ef>>=1)
151 >                if (ef & 1) {                   /* flagged as an expression? */
152 >                        if (ne >= MAXEXPR)
153 >                                objerror(m, INTERNAL, "too many expressions");
154 >                        initstr(arg[i], sbuf, 0);
155 >                        f->ep[ne++] = getE1();
156 >                        if (nextc != EOF)
157 >                                syntax("unexpected character");
158 >                }
159 >        if (ef)
160 >                goto toofew;
161 >        if (i <= ff)                    /* find transform args */
162 >                i = ff+1;
163 >        while (i < na && arg[i][0] != '-')
164 >                i++;
165 >        if (i == na)                    /* no transform */
166 >                f->f = f->b = &unitxf;
167 >        else {                          /* get transform */
168 >                if ((f->b = (XF *)malloc(sizeof(XF))) == NULL)
169 >                        goto memerr;
170 >                if (invxf(f->b, na-i, arg+i) != na-i)
171 >                        objerror(m, USER, "bad transform");
172 >                if (f->b->sca < 0.0)
173 >                        f->b->sca = -f->b->sca;
174 >                if (dofwd) {                    /* do both transforms */
175 >                        if ((f->f = (XF *)malloc(sizeof(XF))) == NULL)
176 >                                goto memerr;
177 >                        xf(f->f, na-i, arg+i);
178 >                        if (f->f->sca < 0.0)
179 >                                f->f->sca = -f->f->sca;
180 >                }
181 >        }
182 >        m->os = (char *)f;
183 >        return(f);
184 > toofew:
185 >        objerror(m, USER, "too few string arguments");
186 > memerr:
187 >        error(SYSTEM, "out of memory in getfunc");
188   }
189  
190  
191 < setfunc(m, r)                           /* simplified interface to setmap */
192 < register OBJREC  *m;
193 < RAY  *r;
191 > void
192 > freefunc(m)                     /* free memory associated with modifier */
193 > OBJREC  *m;
194   {
195 < #define  mxf    ((XF *)m->os)
195 >        register MFUNC  *f;
196 >        register int  i;
197  
198 <        if (mxf == NULL) {
199 <                register int  n = m->oargs.nsargs;
200 <                register char  **sa = m->oargs.sarg;
201 <
202 <                while (n > 0 && **sa != '-') {
203 <                        n--;
204 <                        sa++;
205 <                }
206 <                mxf = (XF *)malloc(sizeof(XF));
207 <                if (mxf == NULL)
208 <                        goto memerr;
209 <                mxf->sca = 1.0;
80 <                setident4(mxf->xfm);
81 <                if (invxf(mxf->xfm, &mxf->sca, n, sa) != n)
82 <                        objerror(m, USER, "bad transform");
83 <                if (mxf->sca < 0.0)
84 <                        mxf->sca = -mxf->sca;
198 >        if ((f = (MFUNC *)m->os) == NULL)
199 >                return;
200 >        for (i = 0; f->ep[i] != NULL; i++)
201 >                epfree(f->ep[i]);
202 >        if (f->ctx[0]) {                        /* done with definitions */
203 >                setcontext(f->ctx);
204 >                i = varvalue(REFVNAME)-.5;      /* reference_count-- */
205 >                if (i > 0)
206 >                        varset(REFVNAME, '=', (double)i);
207 >                else
208 >                        dcleanup(2);            /* remove definitions */
209 >                freestr(f->ctx);
210          }
211 <        setmap(m, r, mxf->sca, mxf->xfm);
212 <        return;
213 < memerr:
214 <        error(SYSTEM, "out of memory in setfunc");
215 < #undef  mxf
211 >        if (f->b != &unitxf)
212 >                free((void *)f->b);
213 >        if (f->f != NULL && f->f != &unitxf)
214 >                free((void *)f->f);
215 >        free((void *)f);
216 >        m->os = NULL;
217   }
218  
219  
220 + int
221 + setfunc(m, r)                   /* set channels for function call */
222 + OBJREC  *m;
223 + register RAY  *r;
224 + {
225 +        static unsigned long  lastrno = ~0;
226 +        register MFUNC  *f;
227 +                                        /* get function */
228 +        if ((f = (MFUNC *)m->os) == NULL)
229 +                objerror(m, CONSISTENCY, "setfunc called before getfunc");
230 +                                        /* set evaluator context */
231 +        setcontext(f->ctx);
232 +                                        /* check to see if matrix set */
233 +        if (m == fobj && r->rno == lastrno)
234 +                return(0);
235 +        fobj = m;
236 +        fray = r;
237 +        if (r->rox != NULL)
238 +                if (f->b != &unitxf) {
239 +                        funcxf.sca = r->rox->b.sca * f->b->sca;
240 +                        multmat4(funcxf.xfm, r->rox->b.xfm, f->b->xfm);
241 +                } else
242 +                        copystruct(&funcxf, &r->rox->b);
243 +        else
244 +                copystruct(&funcxf, f->b);
245 +        lastrno = r->rno;
246 +        eclock++;               /* notify expression evaluator */
247 +        return(1);
248 + }
249 +
250 +
251 + void
252   loadfunc(fname)                 /* load definition file */
253   char  *fname;
254   {
97        extern char  *libpath;          /* library search path */
255          char  *ffname;
256  
257 <        if ((ffname = getpath(fname, libpath)) == NULL) {
257 >        if ((ffname = getpath(fname, getlibpath(), R_OK)) == NULL) {
258                  sprintf(errmsg, "cannot find function file \"%s\"", fname);
259                  error(USER, errmsg);
260          }
# Line 105 | Line 262 | char  *fname;
262   }
263  
264  
265 < double
265 > static double
266   l_arg()                         /* return nth real argument */
267   {
111        extern double  argument();
268          register int  n;
269  
270 +        if (fobj == NULL)
271 +                syntax("arg(n) used in constant expression");
272 +
273          n = argument(1) + .5;           /* round to integer */
274  
275          if (n < 1)
# Line 124 | Line 283 | l_arg()                                /* return nth real argument */
283   }
284  
285  
286 + static double
287 + l_erf()                         /* error function */
288 + {
289 +        extern double  erf();
290 +
291 +        return(erf(argument(1)));
292 + }
293 +
294 +
295 + static double
296 + l_erfc()                        /* cumulative error function */
297 + {
298 +        extern double  erfc();
299 +
300 +        return(erfc(argument(1)));
301 + }
302 +
303 +
304   double
305   chanvalue(n)                    /* return channel n to calcomp */
306   register int  n;
307   {
308 <        double  res;
309 <        register RAY  *r;
308 >        if (fray == NULL)
309 >                syntax("ray parameter used in constant expression");
310  
311 <        n--;                                    /* for convenience */
311 >        if (--n < 0)
312 >                goto badchan;
313  
314 <        if (n < 0 || n > 10)
137 <                error(USER, "illegal channel number");
314 >        if (n < 3)                      /* ray direction */
315  
316 <        if (n == 9) {                           /* distance */
316 >                return( (       fray->rdir[0]*funcxf.xfm[0][n] +
317 >                                fray->rdir[1]*funcxf.xfm[1][n] +
318 >                                fray->rdir[2]*funcxf.xfm[2][n]  )
319 >                         / funcxf.sca );
320  
321 <                res = fray->rot;
142 <                for (r = fray->parent; r != NULL; r = r->parent)
143 <                        res += r->rot;
144 <                res *= fxf.sca;
321 >        if (n < 6)                      /* surface normal */
322  
323 <        } else if (n == 10) {                   /* dot product */
323 >                return( (       fray->ron[0]*funcxf.xfm[0][n-3] +
324 >                                fray->ron[1]*funcxf.xfm[1][n-3] +
325 >                                fray->ron[2]*funcxf.xfm[2][n-3] )
326 >                         / funcxf.sca );
327  
328 <                res = fray->rod;
328 >        if (n < 9)                      /* intersection */
329  
330 <        } else if (n < 3) {                     /* ray direction */
331 <                        res = ( fray->rdir[0]*fxf.xfm[0][n] +
332 <                                        fray->rdir[1]*fxf.xfm[1][n] +
333 <                                        fray->rdir[2]*fxf.xfm[2][n]     )
154 <                                 / fxf.sca ;
155 <        } else if (n < 6) {                     /* surface normal */
156 <                        res = ( fray->ron[0]*fxf.xfm[0][n-3] +
157 <                                        fray->ron[1]*fxf.xfm[1][n-3] +
158 <                                        fray->ron[2]*fxf.xfm[2][n-3]    )
159 <                                 / fxf.sca ;
160 <        } else {                                /* intersection */
161 <                        res =   fray->rop[0]*fxf.xfm[0][n-6] +
162 <                                        fray->rop[1]*fxf.xfm[1][n-6] +
163 <                                        fray->rop[2]*fxf.xfm[2][n-6] +
164 <                                                     fxf.xfm[3][n-6] ;
165 <        }
330 >                return( fray->rop[0]*funcxf.xfm[0][n-6] +
331 >                                fray->rop[1]*funcxf.xfm[1][n-6] +
332 >                                fray->rop[2]*funcxf.xfm[2][n-6] +
333 >                                             funcxf.xfm[3][n-6] );
334  
335 <        return(res);
335 >        if (n == 9)                     /* total distance */
336 >                return(raydist(fray,PRIMARY) * funcxf.sca);
337 >
338 >        if (n == 10)                    /* dot product (range [-1,1]) */
339 >                return( fray->rod <= -1.0 ? -1.0 :
340 >                        fray->rod >= 1.0 ? 1.0 :
341 >                        fray->rod );
342 >
343 >        if (n == 11)                    /* scale */
344 >                return(funcxf.sca);
345 >
346 >        if (n < 15)                     /* origin */
347 >                return(funcxf.xfm[3][n-12]);
348 >
349 >        if (n < 18)                     /* i unit vector */
350 >                return(funcxf.xfm[0][n-15] / funcxf.sca);
351 >
352 >        if (n < 21)                     /* j unit vector */
353 >                return(funcxf.xfm[1][n-15] / funcxf.sca);
354 >
355 >        if (n < 24)                     /* k unit vector */
356 >                return(funcxf.xfm[2][n-21] / funcxf.sca);
357 >
358 >        if (n == 24)                    /* single ray (shadow) distance */
359 >                return((fray->rot+raydist(fray->parent,SHADOW)) * funcxf.sca);
360 > badchan:
361 >        error(USER, "illegal channel number");
362   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines