ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.9
Committed: Wed May 10 22:20:57 1995 UTC (28 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.8: +25 -27 lines
Log Message:
fixed bug in order of global transform arguments

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 greg 1.9 XF_SPEC *xf_context; /* current context */
25     char **xf_argend; /* end of transform argument list */
26     static char **xf_argbeg; /* beginning of transform argument list */
27 greg 1.1
28 greg 1.5 static XF_SPEC *new_xf();
29     static long comp_xfid();
30     static int put_oname();
31 greg 1.1
32 greg 1.5
33 greg 1.1 int
34     xf_handler(ac, av) /* handle xf entity */
35     int ac;
36     char **av;
37     {
38     register XF_SPEC *spec;
39 greg 1.5 register int n;
40     int rv;
41 greg 1.1
42 greg 1.5 if (ac == 1) { /* something with existing transform */
43 greg 1.1 if ((spec = xf_context) == NULL)
44     return(MG_OK); /* should be error? */
45 greg 1.5 n = -1;
46     if (spec->xarr != NULL) { /* check for iteration */
47     register struct xf_array *ap = spec->xarr;
48    
49     (void)put_oname((struct xf_array *)NULL);
50     n = ap->ndim;
51     while (n--) {
52     if (++ap->aarg[n].i < ap->aarg[n].n)
53     break;
54     (void)strcpy(ap->aarg[n].arg, "0");
55     ap->aarg[n].i = 0;
56     }
57     if (n >= 0) {
58     if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
59     return(rv);
60     sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
61     (void)put_oname(ap);
62     } else
63     free((MEM_PTR)ap);
64     }
65     if (n < 0) { /* pop transform */
66     xf_context = spec->prev;
67     free((MEM_PTR)spec);
68     return(MG_OK);
69     }
70     } else { /* else allocate transform */
71     if ((spec = new_xf(ac-1, av+1)) == NULL)
72     return(MG_EMEM);
73     spec->prev = xf_context; /* push onto stack */
74     xf_context = spec;
75 greg 1.1 }
76     /* translate new specification */
77 greg 1.9 n = xf_ac(spec);
78     if (spec->prev != NULL) /* incremental comp. is more eff. */
79     n -= xf_ac(spec->prev);
80     if (xf(&spec->xf, n, xf_av(spec)) != n)
81 greg 1.1 return(MG_ETYPE);
82 greg 1.7 /* check for vertex reversal */
83 greg 1.8 if ((spec->rev = (spec->xf.sca < 0.)))
84     spec->xf.sca = -spec->xf.sca;
85 greg 1.5 /* compute total transformation */
86     if (spec->prev != NULL) {
87 greg 1.8 multmat4(spec->xf.xfm, spec->xf.xfm, spec->prev->xf.xfm);
88     spec->xf.sca *= spec->prev->xf.sca;
89 greg 1.7 spec->rev ^= spec->prev->rev;
90 greg 1.8 }
91 greg 1.5 spec->xid = comp_xfid(spec->xf.xfm); /* compute unique ID */
92     return(MG_OK);
93     }
94    
95    
96     static XF_SPEC *
97     new_xf(ac, av) /* allocate new transform structure */
98     int ac;
99     char **av;
100     {
101     register XF_SPEC *spec;
102     register int i;
103     char *cp;
104     int n, ndim;
105    
106     ndim = 0;
107     n = 0; /* compute space req'd by arguments */
108     for (i = 0; i < ac; i++)
109     if (!strcmp(av[i], "-a")) {
110     ndim++;
111     i++;
112     } else
113     n += strlen(av[i]) + 1;
114     if (ndim > XF_MAXDIM)
115     return(NULL);
116     spec = (XF_SPEC *)malloc(sizeof(XF_SPEC) + n);
117 greg 1.1 if (spec == NULL)
118 greg 1.5 return(NULL);
119     if (ndim) {
120     spec->xarr = (struct xf_array *)malloc(sizeof(struct xf_array));
121     if (spec->xarr == NULL)
122     return(NULL);
123     mg_fgetpos(&spec->xarr->spos);
124     spec->xarr->ndim = 0; /* incremented below */
125     } else
126     spec->xarr = NULL;
127 greg 1.9 spec->xac = ac + xf_argc;
128 greg 1.1 /* and store new xf arguments */
129 greg 1.9 if (xf_argbeg == NULL || xf_av(spec) < xf_argbeg) {
130     register char **newav =
131     (char **)malloc((spec->xac+1)*sizeof(char *));
132     if (newav == NULL)
133 greg 1.5 return(NULL);
134 greg 1.9 for (i = xf_argc; i-- > 0; )
135     newav[ac+i] = xf_argend[i-xf_context->xac];
136     *(xf_argend = newav + spec->xac) = NULL;
137     if (xf_argbeg != NULL)
138     free((MEM_PTR)xf_argbeg);
139     xf_argbeg = newav;
140 greg 1.1 }
141 greg 1.5 cp = (char *)(spec + 1); /* use memory allocated above */
142     for (i = 0; i < ac; i++)
143     if (!strcmp(av[i], "-a")) {
144 greg 1.9 xf_av(spec)[i++] = "-i";
145     xf_av(spec)[i] = strcpy(
146 greg 1.5 spec->xarr->aarg[spec->xarr->ndim].arg,
147     "0");
148     spec->xarr->aarg[spec->xarr->ndim].i = 0;
149 greg 1.9 spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[i]);
150 greg 1.5 } else {
151 greg 1.9 xf_av(spec)[i] = strcpy(cp, av[i]);
152 greg 1.5 cp += strlen(av[i]) + 1;
153     }
154     if (spec->xarr != NULL)
155     (void)put_oname(spec->xarr);
156     return(spec);
157     }
158 greg 1.4
159 greg 1.5
160     static int
161     put_oname(ap) /* put out name for this instance */
162     register struct xf_array *ap;
163     {
164     static char oname[10*XF_MAXDIM];
165     static char *oav[3] = {mg_ename[MG_E_OBJECT], oname};
166     register int i;
167     register char *cp1, *cp2;
168    
169     if (ap == NULL)
170     return(mg_handle(MG_E_OBJECT, 1, oav));
171     cp1 = oname;
172     *cp1 = 'a';
173     for (i = 0; i < ap->ndim; i++) {
174     for (cp2 = ap->aarg[i].arg; *cp2; )
175     *++cp1 = *cp2++;
176     *++cp1 = '.';
177     }
178     *cp1 = '\0';
179     return(mg_handle(MG_E_OBJECT, 2, oav));
180 greg 1.1 }
181    
182    
183 greg 1.5 static long
184     comp_xfid(xfm) /* compute unique ID from matrix */
185     register MAT4 xfm;
186     {
187     static char shifttab[64] = { 15, 5, 11, 5, 6, 3,
188     9, 15, 13, 2, 13, 5, 2, 12, 14, 11,
189     11, 12, 12, 3, 2, 11, 8, 12, 1, 12,
190     5, 4, 15, 9, 14, 5, 13, 14, 2, 10,
191     10, 14, 12, 3, 5, 5, 14, 6, 12, 11,
192     13, 9, 12, 8, 1, 6, 5, 12, 7, 13,
193     15, 8, 9, 2, 6, 11, 9, 11 };
194     register int i;
195     register long xid;
196    
197     xid = 0; /* compute unique transform id */
198     for (i = 0; i < sizeof(MAT4)/sizeof(unsigned short); i++)
199     xid ^= (long)(((unsigned short *)xfm)[i]) << shifttab[i&63];
200     return(xid);
201     }
202    
203    
204 greg 1.1 void
205 greg 1.2 xf_clear() /* clear transform stack */
206     {
207     register XF_SPEC *spec;
208    
209 greg 1.9 if (xf_argbeg != NULL) {
210     free((MEM_PTR)xf_argbeg);
211     xf_argbeg = xf_argend = NULL;
212 greg 1.2 }
213     while ((spec = xf_context) != NULL) {
214     xf_context = spec->prev;
215 greg 1.5 if (spec->xarr != NULL)
216     free((MEM_PTR)spec->xarr);
217 greg 1.2 free((MEM_PTR)spec);
218     }
219     }
220    
221    
222     void
223 greg 1.1 xf_xfmpoint(v1, v2) /* transform a point by the current matrix */
224     FVECT v1, v2;
225     {
226     if (xf_context == NULL) {
227     v1[0] = v2[0];
228     v1[1] = v2[1];
229     v1[2] = v2[2];
230     return;
231     }
232     multp3(v1, v2, xf_context->xf.xfm);
233     }
234    
235    
236     void
237     xf_xfmvect(v1, v2) /* transform a vector using current matrix */
238     FVECT v1, v2;
239     {
240     if (xf_context == NULL) {
241     v1[0] = v2[0];
242     v1[1] = v2[1];
243     v1[2] = v2[2];
244     return;
245     }
246     multv3(v1, v2, xf_context->xf.xfm);
247     }
248    
249    
250     void
251     xf_rotvect(v1, v2) /* rotate a vector using current matrix */
252     FVECT v1, v2;
253     {
254     xf_xfmvect(v1, v2);
255     if (xf_context == NULL)
256     return;
257     v1[0] /= xf_context->xf.sca;
258     v1[1] /= xf_context->xf.sca;
259     v1[2] /= xf_context->xf.sca;
260     }
261    
262    
263     double
264     xf_scale(d) /* scale a number by the current transform */
265     double d;
266     {
267     if (xf_context == NULL)
268     return(d);
269     return(d*xf_context->xf.sca);
270     }
271    
272    
273     void
274     multmat4(m4a, m4b, m4c) /* multiply m4b X m4c and put into m4a */
275     MAT4 m4a;
276     register MAT4 m4b, m4c;
277     {
278     register int i, j;
279    
280     for (i = 4; i--; )
281     for (j = 4; j--; )
282     m4tmp[i][j] = m4b[i][0]*m4c[0][j] +
283     m4b[i][1]*m4c[1][j] +
284     m4b[i][2]*m4c[2][j] +
285     m4b[i][3]*m4c[3][j];
286    
287     copymat4(m4a, m4tmp);
288     }
289    
290    
291     void
292     multv3(v3a, v3b, m4) /* transform vector v3b by m4 and put into v3a */
293     FVECT v3a;
294     register FVECT v3b;
295     register MAT4 m4;
296     {
297     m4tmp[0][0] = v3b[0]*m4[0][0] + v3b[1]*m4[1][0] + v3b[2]*m4[2][0];
298     m4tmp[0][1] = v3b[0]*m4[0][1] + v3b[1]*m4[1][1] + v3b[2]*m4[2][1];
299     m4tmp[0][2] = v3b[0]*m4[0][2] + v3b[1]*m4[1][2] + v3b[2]*m4[2][2];
300    
301     v3a[0] = m4tmp[0][0];
302     v3a[1] = m4tmp[0][1];
303     v3a[2] = m4tmp[0][2];
304     }
305    
306    
307     void
308     multp3(p3a, p3b, m4) /* transform p3b by m4 and put into p3a */
309     register FVECT p3a;
310     FVECT p3b;
311     register MAT4 m4;
312     {
313     multv3(p3a, p3b, m4); /* transform as vector */
314     p3a[0] += m4[3][0]; /* translate */
315     p3a[1] += m4[3][1];
316     p3a[2] += m4[3][2];
317     }
318    
319    
320     int
321     xf(ret, ac, av) /* get transform specification */
322     register XF *ret;
323     int ac;
324 greg 1.3 char **av;
325 greg 1.1 {
326     MAT4 xfmat, m4;
327     double xfsca, dtmp;
328     int i, icnt;
329    
330     setident4(ret->xfm);
331     ret->sca = 1.0;
332    
333     icnt = 1;
334     setident4(xfmat);
335     xfsca = 1.0;
336    
337     for (i = 0; i < ac && av[i][0] == '-'; i++) {
338    
339     setident4(m4);
340    
341     switch (av[i][1]) {
342    
343     case 't': /* translate */
344     checkarg(2,"fff");
345     m4[3][0] = atof(av[++i]);
346     m4[3][1] = atof(av[++i]);
347     m4[3][2] = atof(av[++i]);
348     break;
349    
350     case 'r': /* rotate */
351     switch (av[i][2]) {
352     case 'x':
353     checkarg(3,"f");
354     dtmp = d2r(atof(av[++i]));
355     m4[1][1] = m4[2][2] = cos(dtmp);
356     m4[2][1] = -(m4[1][2] = sin(dtmp));
357     break;
358     case 'y':
359     checkarg(3,"f");
360     dtmp = d2r(atof(av[++i]));
361     m4[0][0] = m4[2][2] = cos(dtmp);
362     m4[0][2] = -(m4[2][0] = sin(dtmp));
363     break;
364     case 'z':
365     checkarg(3,"f");
366     dtmp = d2r(atof(av[++i]));
367     m4[0][0] = m4[1][1] = cos(dtmp);
368     m4[1][0] = -(m4[0][1] = sin(dtmp));
369     break;
370     default:
371     goto done;
372     }
373     break;
374    
375     case 's': /* scale */
376     checkarg(2,"f");
377     dtmp = atof(av[i+1]);
378     if (dtmp == 0.0) goto done;
379     i++;
380     xfsca *=
381     m4[0][0] =
382     m4[1][1] =
383     m4[2][2] = dtmp;
384     break;
385    
386     case 'm': /* mirror */
387     switch (av[i][2]) {
388     case 'x':
389     checkarg(3,"");
390     xfsca *=
391     m4[0][0] = -1.0;
392     break;
393     case 'y':
394     checkarg(3,"");
395     xfsca *=
396     m4[1][1] = -1.0;
397     break;
398     case 'z':
399     checkarg(3,"");
400     xfsca *=
401     m4[2][2] = -1.0;
402     break;
403     default:
404     goto done;
405     }
406     break;
407    
408     case 'i': /* iterate */
409     checkarg(2,"i");
410     while (icnt-- > 0) {
411     multmat4(ret->xfm, ret->xfm, xfmat);
412     ret->sca *= xfsca;
413     }
414     icnt = atoi(av[++i]);
415     setident4(xfmat);
416     xfsca = 1.0;
417     continue;
418    
419     default:
420     goto done;
421    
422     }
423     multmat4(xfmat, xfmat, m4);
424     }
425     done:
426     while (icnt-- > 0) {
427     multmat4(ret->xfm, ret->xfm, xfmat);
428     ret->sca *= xfsca;
429     }
430     return(i);
431     }