ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.2
Committed: Wed Jun 22 15:33:50 1994 UTC (29 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +19 -0 lines
Log Message:
various enhancements and fixes

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1994 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Routines for 4x4 homogeneous, rigid-body transformations
9     */
10    
11     #include <stdio.h>
12     #include <math.h>
13     #include <string.h>
14     #include "parser.h"
15    
16     #define d2r(a) ((PI/180.)*(a))
17    
18     #define checkarg(a,l) if (av[i][a] || badarg(ac-i-1,av+i+1,l)) goto done
19    
20     MAT4 m4ident = MAT4IDENT;
21    
22     static MAT4 m4tmp; /* for efficiency */
23    
24     int xf_argc; /* total # transform args. */
25     char **xf_argv; /* transform arguments */
26     XF_SPEC *xf_context; /* current context */
27    
28     static int xf_maxarg; /* # allocated arguments */
29    
30    
31     int
32     xf_handler(ac, av) /* handle xf entity */
33     int ac;
34     char **av;
35     {
36     register int i;
37     register XF_SPEC *spec;
38     XF thisxf;
39    
40     if (ac == 1) { /* pop top transform */
41     if ((spec = xf_context) == NULL)
42     return(MG_OK); /* should be error? */
43     while (xf_argc > spec->xav0)
44     free((MEM_PTR)xf_argv[--xf_argc]);
45     xf_argv[xf_argc] = NULL;
46     xf_context = spec->prev;
47     free((MEM_PTR)spec);
48     return(MG_OK);
49     }
50     /* translate new specification */
51     if (xf(&thisxf, ac-1, av+1) != ac-1)
52     return(MG_ETYPE);
53     /* allocate space for new transform */
54     spec = (XF_SPEC *)malloc(sizeof(XF_SPEC));
55     if (spec == NULL)
56     return(MG_EMEM);
57     spec->xav0 = xf_argc;
58     spec->xac = ac-1;
59     /* and store new xf arguments */
60     if (xf_argc+ac > xf_maxarg) {
61     if (!xf_maxarg)
62     xf_argv = (char **)malloc(
63     (xf_maxarg=ac)*sizeof(char *));
64     else
65     xf_argv = (char **)realloc((MEM_PTR)xf_argv,
66     (xf_maxarg+=ac)*sizeof(char *));
67     if (xf_argv == NULL)
68     return(MG_EMEM);
69     }
70     for (i = 0; i < ac-1; i++) {
71     xf_argv[xf_argc] = (char *)malloc(strlen(av[i+1])+1);
72     if (xf_argv[xf_argc] == NULL)
73     return(MG_EMEM);
74     strcpy(xf_argv[xf_argc++], av[i+1]);
75     }
76     xf_argv[xf_argc] = NULL;
77     /* compute total transformation */
78     if (xf_context != NULL) {
79     multmat4(spec->xf.xfm, xf_context->xf.xfm, thisxf.xfm);
80     spec->xf.sca = xf_context->xf.sca * thisxf.sca;
81     } else
82     spec->xf = thisxf;
83     spec->prev = xf_context; /* push new transform onto stack */
84     xf_context = spec;
85     return(MG_OK);
86     }
87    
88    
89     void
90 greg 1.2 xf_clear() /* clear transform stack */
91     {
92     register XF_SPEC *spec;
93    
94     while (xf_argc)
95     free((MEM_PTR)xf_argv[--xf_argc]);
96     if (xf_maxarg) {
97     free((MEM_PTR)xf_argv);
98     xf_argv = NULL;
99     xf_maxarg = 0;
100     }
101     while ((spec = xf_context) != NULL) {
102     xf_context = spec->prev;
103     free((MEM_PTR)spec);
104     }
105     }
106    
107    
108     void
109 greg 1.1 xf_xfmpoint(v1, v2) /* transform a point by the current matrix */
110     FVECT v1, v2;
111     {
112     if (xf_context == NULL) {
113     v1[0] = v2[0];
114     v1[1] = v2[1];
115     v1[2] = v2[2];
116     return;
117     }
118     multp3(v1, v2, xf_context->xf.xfm);
119     }
120    
121    
122     void
123     xf_xfmvect(v1, v2) /* transform a vector using current matrix */
124     FVECT v1, v2;
125     {
126     if (xf_context == NULL) {
127     v1[0] = v2[0];
128     v1[1] = v2[1];
129     v1[2] = v2[2];
130     return;
131     }
132     multv3(v1, v2, xf_context->xf.xfm);
133     }
134    
135    
136     void
137     xf_rotvect(v1, v2) /* rotate a vector using current matrix */
138     FVECT v1, v2;
139     {
140     xf_xfmvect(v1, v2);
141     if (xf_context == NULL)
142     return;
143     v1[0] /= xf_context->xf.sca;
144     v1[1] /= xf_context->xf.sca;
145     v1[2] /= xf_context->xf.sca;
146     }
147    
148    
149     double
150     xf_scale(d) /* scale a number by the current transform */
151     double d;
152     {
153     if (xf_context == NULL)
154     return(d);
155     return(d*xf_context->xf.sca);
156     }
157    
158    
159     void
160     multmat4(m4a, m4b, m4c) /* multiply m4b X m4c and put into m4a */
161     MAT4 m4a;
162     register MAT4 m4b, m4c;
163     {
164     register int i, j;
165    
166     for (i = 4; i--; )
167     for (j = 4; j--; )
168     m4tmp[i][j] = m4b[i][0]*m4c[0][j] +
169     m4b[i][1]*m4c[1][j] +
170     m4b[i][2]*m4c[2][j] +
171     m4b[i][3]*m4c[3][j];
172    
173     copymat4(m4a, m4tmp);
174     }
175    
176    
177     void
178     multv3(v3a, v3b, m4) /* transform vector v3b by m4 and put into v3a */
179     FVECT v3a;
180     register FVECT v3b;
181     register MAT4 m4;
182     {
183     m4tmp[0][0] = v3b[0]*m4[0][0] + v3b[1]*m4[1][0] + v3b[2]*m4[2][0];
184     m4tmp[0][1] = v3b[0]*m4[0][1] + v3b[1]*m4[1][1] + v3b[2]*m4[2][1];
185     m4tmp[0][2] = v3b[0]*m4[0][2] + v3b[1]*m4[1][2] + v3b[2]*m4[2][2];
186    
187     v3a[0] = m4tmp[0][0];
188     v3a[1] = m4tmp[0][1];
189     v3a[2] = m4tmp[0][2];
190     }
191    
192    
193     void
194     multp3(p3a, p3b, m4) /* transform p3b by m4 and put into p3a */
195     register FVECT p3a;
196     FVECT p3b;
197     register MAT4 m4;
198     {
199     multv3(p3a, p3b, m4); /* transform as vector */
200     p3a[0] += m4[3][0]; /* translate */
201     p3a[1] += m4[3][1];
202     p3a[2] += m4[3][2];
203     }
204    
205    
206     int
207     xf(ret, ac, av) /* get transform specification */
208     register XF *ret;
209     int ac;
210     char *av[];
211     {
212     MAT4 xfmat, m4;
213     double xfsca, dtmp;
214     int i, icnt;
215    
216     setident4(ret->xfm);
217     ret->sca = 1.0;
218    
219     icnt = 1;
220     setident4(xfmat);
221     xfsca = 1.0;
222    
223     for (i = 0; i < ac && av[i][0] == '-'; i++) {
224    
225     setident4(m4);
226    
227     switch (av[i][1]) {
228    
229     case 't': /* translate */
230     checkarg(2,"fff");
231     m4[3][0] = atof(av[++i]);
232     m4[3][1] = atof(av[++i]);
233     m4[3][2] = atof(av[++i]);
234     break;
235    
236     case 'r': /* rotate */
237     switch (av[i][2]) {
238     case 'x':
239     checkarg(3,"f");
240     dtmp = d2r(atof(av[++i]));
241     m4[1][1] = m4[2][2] = cos(dtmp);
242     m4[2][1] = -(m4[1][2] = sin(dtmp));
243     break;
244     case 'y':
245     checkarg(3,"f");
246     dtmp = d2r(atof(av[++i]));
247     m4[0][0] = m4[2][2] = cos(dtmp);
248     m4[0][2] = -(m4[2][0] = sin(dtmp));
249     break;
250     case 'z':
251     checkarg(3,"f");
252     dtmp = d2r(atof(av[++i]));
253     m4[0][0] = m4[1][1] = cos(dtmp);
254     m4[1][0] = -(m4[0][1] = sin(dtmp));
255     break;
256     default:
257     goto done;
258     }
259     break;
260    
261     case 's': /* scale */
262     checkarg(2,"f");
263     dtmp = atof(av[i+1]);
264     if (dtmp == 0.0) goto done;
265     i++;
266     xfsca *=
267     m4[0][0] =
268     m4[1][1] =
269     m4[2][2] = dtmp;
270     break;
271    
272     case 'm': /* mirror */
273     switch (av[i][2]) {
274     case 'x':
275     checkarg(3,"");
276     xfsca *=
277     m4[0][0] = -1.0;
278     break;
279     case 'y':
280     checkarg(3,"");
281     xfsca *=
282     m4[1][1] = -1.0;
283     break;
284     case 'z':
285     checkarg(3,"");
286     xfsca *=
287     m4[2][2] = -1.0;
288     break;
289     default:
290     goto done;
291     }
292     break;
293    
294     case 'i': /* iterate */
295     checkarg(2,"i");
296     while (icnt-- > 0) {
297     multmat4(ret->xfm, ret->xfm, xfmat);
298     ret->sca *= xfsca;
299     }
300     icnt = atoi(av[++i]);
301     setident4(xfmat);
302     xfsca = 1.0;
303     continue;
304    
305     default:
306     goto done;
307    
308     }
309     multmat4(xfmat, xfmat, m4);
310     }
311     done:
312     while (icnt-- > 0) {
313     multmat4(ret->xfm, ret->xfm, xfmat);
314     ret->sca *= xfsca;
315     }
316     return(i);
317     }