ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/mgf_xf.c
Revision: 3.1
Committed: Fri Feb 18 00:40:25 2011 UTC (13 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R1, rad4R2P1, rad5R3, HEAD
Log Message:
Major code reorg, moving mgflib to common and introducing BSDF material

File Contents

# User Rev Content
1 greg 3.1 #ifndef lint
2     static const char RCSid[] = "$Id: xf.c,v 1.15 2011/01/14 05:46:12 greg Exp $";
3     #endif
4     /*
5     * Routines for 4x4 homogeneous, rigid-body transformations
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include "mgf_parser.h"
11    
12     #define d2r(a) ((PI/180.)*(a))
13    
14     #define checkarg(a,l) if (av[i][a] || badarg(ac-i-1,av+i+1,l)) goto done
15    
16     XF_SPEC *xf_context = NULL; /* current context */
17     char **xf_argend; /* end of transform argument list */
18     static char **xf_argbeg; /* beginning of transform argument list */
19    
20    
21     int
22     xf_handler(int ac, char **av) /* handle xf entity */
23     {
24     register XF_SPEC *spec;
25     register int n;
26     int rv;
27    
28     if (ac == 1) { /* something with existing transform */
29     if ((spec = xf_context) == NULL)
30     return(MG_ECNTXT);
31     n = -1;
32     if (spec->xarr != NULL) { /* check for iteration */
33     register struct xf_array *ap = spec->xarr;
34    
35     (void)xf_aname((struct xf_array *)NULL);
36     n = ap->ndim;
37     while (n--) {
38     if (++ap->aarg[n].i < ap->aarg[n].n)
39     break;
40     (void)strcpy(ap->aarg[n].arg, "0");
41     ap->aarg[n].i = 0;
42     }
43     if (n >= 0) {
44     if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
45     return(rv);
46     sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
47     (void)xf_aname(ap);
48     }
49     }
50     if (n < 0) { /* pop transform */
51     xf_context = spec->prev;
52     free_xf(spec);
53     return(MG_OK);
54     }
55     } else { /* else allocate transform */
56     if ((spec = new_xf(ac-1, av+1)) == NULL)
57     return(MG_EMEM);
58     if (spec->xarr != NULL)
59     (void)xf_aname(spec->xarr);
60     spec->prev = xf_context; /* push onto stack */
61     xf_context = spec;
62     }
63     /* translate new specification */
64     n = xf_ac(spec);
65     n -= xf_ac(spec->prev); /* incremental comp. is more eff. */
66     if (xf(&spec->xf, n, xf_av(spec)) != n)
67     return(MG_ETYPE);
68     /* check for vertex reversal */
69     if ((spec->rev = (spec->xf.sca < 0.)))
70     spec->xf.sca = -spec->xf.sca;
71     /* compute total transformation */
72     if (spec->prev != NULL) {
73     multmat4(spec->xf.xfm, spec->xf.xfm, spec->prev->xf.xfm);
74     spec->xf.sca *= spec->prev->xf.sca;
75     spec->rev ^= spec->prev->rev;
76     }
77     spec->xid = comp_xfid(spec->xf.xfm); /* compute unique ID */
78     return(MG_OK);
79     }
80    
81    
82     XF_SPEC *
83     new_xf(int ac, char **av) /* allocate new transform structure */
84     {
85     register XF_SPEC *spec;
86     register int i;
87     char *cp;
88     int n, ndim;
89    
90     ndim = 0;
91     n = 0; /* compute space req'd by arguments */
92     for (i = 0; i < ac; i++)
93     if (!strcmp(av[i], "-a")) {
94     ndim++;
95     i++;
96     } else
97     n += strlen(av[i]) + 1;
98     if (ndim > XF_MAXDIM)
99     return(NULL);
100     spec = (XF_SPEC *)malloc(sizeof(XF_SPEC) + n);
101     if (spec == NULL)
102     return(NULL);
103     if (ndim) {
104     spec->xarr = (struct xf_array *)malloc(sizeof(struct xf_array));
105     if (spec->xarr == NULL)
106     return(NULL);
107     mg_fgetpos(&spec->xarr->spos);
108     spec->xarr->ndim = 0; /* incremented below */
109     } else
110     spec->xarr = NULL;
111     spec->xac = ac + xf_argc;
112     /* and store new xf arguments */
113     if (xf_argbeg == NULL || xf_av(spec) < xf_argbeg) {
114     register char **newav =
115     (char **)malloc((spec->xac+1)*sizeof(char *));
116     if (newav == NULL)
117     return(NULL);
118     for (i = xf_argc; i-- > 0; )
119     newav[ac+i] = xf_argend[i-xf_context->xac];
120     *(xf_argend = newav + spec->xac) = NULL;
121     if (xf_argbeg != NULL)
122     free(xf_argbeg);
123     xf_argbeg = newav;
124     }
125     cp = (char *)(spec + 1); /* use memory allocated above */
126     for (i = 0; i < ac; i++)
127     if (!strcmp(av[i], "-a")) {
128     xf_av(spec)[i++] = "-i";
129     xf_av(spec)[i] = strcpy(
130     spec->xarr->aarg[spec->xarr->ndim].arg,
131     "0");
132     spec->xarr->aarg[spec->xarr->ndim].i = 0;
133     spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[i]);
134     } else {
135     xf_av(spec)[i] = strcpy(cp, av[i]);
136     cp += strlen(av[i]) + 1;
137     }
138     return(spec);
139     }
140    
141    
142     void
143     free_xf(XF_SPEC *spec) /* free a transform */
144     {
145     if (spec->xarr != NULL)
146     free(spec->xarr);
147     free(spec);
148     }
149    
150    
151     int
152     xf_aname(struct xf_array *ap) /* put out name for this instance */
153     {
154     static char oname[10*XF_MAXDIM];
155     static char *oav[3] = {mg_ename[MG_E_OBJECT], oname};
156     register int i;
157     register char *cp1, *cp2;
158    
159     if (ap == NULL)
160     return(mg_handle(MG_E_OBJECT, 1, oav));
161     cp1 = oname;
162     *cp1 = 'a';
163     for (i = 0; i < ap->ndim; i++) {
164     for (cp2 = ap->aarg[i].arg; *cp2; )
165     *++cp1 = *cp2++;
166     *++cp1 = '.';
167     }
168     *cp1 = '\0';
169     return(mg_handle(MG_E_OBJECT, 2, oav));
170     }
171    
172    
173     long
174     comp_xfid(MAT4 xfm) /* compute unique ID from matrix */
175     {
176     static char shifttab[64] = { 15, 5, 11, 5, 6, 3,
177     9, 15, 13, 2, 13, 5, 2, 12, 14, 11,
178     11, 12, 12, 3, 2, 11, 8, 12, 1, 12,
179     5, 4, 15, 9, 14, 5, 13, 14, 2, 10,
180     10, 14, 12, 3, 5, 5, 14, 6, 12, 11,
181     13, 9, 12, 8, 1, 6, 5, 12, 7, 13,
182     15, 8, 9, 2, 6, 11, 9, 11 };
183     register int i;
184     register long xid;
185    
186     xid = 0; /* compute unique transform id */
187     for (i = 0; i < sizeof(MAT4)/sizeof(unsigned short); i++)
188     xid ^= (long)(((unsigned short *)xfm)[i]) << shifttab[i&63];
189     return(xid);
190     }
191    
192    
193     void
194     xf_clear(void) /* clear transform stack */
195     {
196     register XF_SPEC *spec;
197    
198     if (xf_argbeg != NULL) {
199     free(xf_argbeg);
200     xf_argbeg = xf_argend = NULL;
201     }
202     while ((spec = xf_context) != NULL) {
203     xf_context = spec->prev;
204     free_xf(spec);
205     }
206     }
207    
208    
209     void
210     xf_xfmpoint(FVECT v1, FVECT v2) /* transform a point by the current matrix */
211     {
212     if (xf_context == NULL) {
213     VCOPY(v1, v2);
214     return;
215     }
216     multp3(v1, v2, xf_context->xf.xfm);
217     }
218    
219    
220     void
221     xf_xfmvect(FVECT v1, FVECT v2) /* transform a vector using current matrix */
222     {
223     if (xf_context == NULL) {
224     VCOPY(v1, v2);
225     return;
226     }
227     multv3(v1, v2, xf_context->xf.xfm);
228     }
229    
230    
231     void
232     xf_rotvect(FVECT v1, FVECT v2) /* rotate a vector using current matrix */
233     {
234     xf_xfmvect(v1, v2);
235     if (xf_context == NULL)
236     return;
237     v1[0] /= xf_context->xf.sca;
238     v1[1] /= xf_context->xf.sca;
239     v1[2] /= xf_context->xf.sca;
240     }
241    
242    
243     double
244     xf_scale(double d) /* scale a number by the current transform */
245     {
246     if (xf_context == NULL)
247     return(d);
248     return(d*xf_context->xf.sca);
249     }