ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.6
Committed: Mon Jul 11 14:47:12 1994 UTC (29 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.5: +2 -2 lines
Log Message:
fixed order of transformation accumulation (serious bug!)

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 greg 1.5 static XF_SPEC *new_xf();
31     static long comp_xfid();
32     static int put_oname();
33 greg 1.1
34 greg 1.5
35 greg 1.1 int
36     xf_handler(ac, av) /* handle xf entity */
37     int ac;
38     char **av;
39     {
40     register XF_SPEC *spec;
41 greg 1.5 register int n;
42     int rv;
43 greg 1.1 XF thisxf;
44    
45 greg 1.5 if (ac == 1) { /* something with existing transform */
46 greg 1.1 if ((spec = xf_context) == NULL)
47     return(MG_OK); /* should be error? */
48 greg 1.5 n = -1;
49     if (spec->xarr != NULL) { /* check for iteration */
50     register struct xf_array *ap = spec->xarr;
51    
52     (void)put_oname((struct xf_array *)NULL);
53     n = ap->ndim;
54     while (n--) {
55     if (++ap->aarg[n].i < ap->aarg[n].n)
56     break;
57     (void)strcpy(ap->aarg[n].arg, "0");
58     ap->aarg[n].i = 0;
59     }
60     if (n >= 0) {
61     if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
62     return(rv);
63     sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
64     (void)put_oname(ap);
65     } else
66     free((MEM_PTR)ap);
67     }
68     if (n < 0) { /* pop transform */
69     xf_argv[xf_argc=spec->xav0] = NULL;
70     xf_context = spec->prev;
71     free((MEM_PTR)spec);
72     return(MG_OK);
73     }
74     } else { /* else allocate transform */
75     if ((spec = new_xf(ac-1, av+1)) == NULL)
76     return(MG_EMEM);
77     spec->prev = xf_context; /* push onto stack */
78     xf_context = spec;
79 greg 1.1 }
80     /* translate new specification */
81 greg 1.5 if (xf(&thisxf, spec->xac, &xf_argv[spec->xav0]) != spec->xac)
82 greg 1.1 return(MG_ETYPE);
83 greg 1.5 /* compute total transformation */
84     if (spec->prev != NULL) {
85 greg 1.6 multmat4(spec->xf.xfm, thisxf.xfm, spec->prev->xf.xfm);
86     spec->xf.sca = thisxf.sca * spec->prev->xf.sca;
87 greg 1.5 } else
88     spec->xf = thisxf;
89     spec->xid = comp_xfid(spec->xf.xfm); /* compute unique ID */
90     return(MG_OK);
91     }
92    
93    
94     static XF_SPEC *
95     new_xf(ac, av) /* allocate new transform structure */
96     int ac;
97     char **av;
98     {
99     register XF_SPEC *spec;
100     register int i;
101     char *cp;
102     int n, ndim;
103    
104     ndim = 0;
105     n = 0; /* compute space req'd by arguments */
106     for (i = 0; i < ac; i++)
107     if (!strcmp(av[i], "-a")) {
108     ndim++;
109     i++;
110     } else
111     n += strlen(av[i]) + 1;
112     if (ndim > XF_MAXDIM)
113     return(NULL);
114     spec = (XF_SPEC *)malloc(sizeof(XF_SPEC) + n);
115 greg 1.1 if (spec == NULL)
116 greg 1.5 return(NULL);
117     if (ndim) {
118     spec->xarr = (struct xf_array *)malloc(sizeof(struct xf_array));
119     if (spec->xarr == NULL)
120     return(NULL);
121     mg_fgetpos(&spec->xarr->spos);
122     spec->xarr->ndim = 0; /* incremented below */
123     } else
124     spec->xarr = NULL;
125 greg 1.1 spec->xav0 = xf_argc;
126 greg 1.5 spec->xac = ac;
127 greg 1.1 /* and store new xf arguments */
128 greg 1.5 if (xf_argc+ac+1 > xf_maxarg) {
129 greg 1.1 if (!xf_maxarg)
130     xf_argv = (char **)malloc(
131 greg 1.5 (xf_maxarg=ac+1)*sizeof(char *));
132 greg 1.1 else
133     xf_argv = (char **)realloc((MEM_PTR)xf_argv,
134 greg 1.5 (xf_maxarg=xf_argc+ac+1)*sizeof(char *));
135 greg 1.1 if (xf_argv == NULL)
136 greg 1.5 return(NULL);
137 greg 1.1 }
138 greg 1.5 cp = (char *)(spec + 1); /* use memory allocated above */
139     for (i = 0; i < ac; i++)
140     if (!strcmp(av[i], "-a")) {
141     xf_argv[xf_argc++] = "-i";
142     xf_argv[xf_argc++] = strcpy(
143     spec->xarr->aarg[spec->xarr->ndim].arg,
144     "0");
145     spec->xarr->aarg[spec->xarr->ndim].i = 0;
146     spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[++i]);
147     } else {
148     xf_argv[xf_argc++] = strcpy(cp, av[i]);
149     cp += strlen(av[i]) + 1;
150     }
151 greg 1.1 xf_argv[xf_argc] = NULL;
152 greg 1.5 if (spec->xarr != NULL)
153     (void)put_oname(spec->xarr);
154     return(spec);
155     }
156 greg 1.4
157 greg 1.5
158     static int
159     put_oname(ap) /* put out name for this instance */
160     register struct xf_array *ap;
161     {
162     static char oname[10*XF_MAXDIM];
163     static char *oav[3] = {mg_ename[MG_E_OBJECT], oname};
164     register int i;
165     register char *cp1, *cp2;
166    
167     if (ap == NULL)
168     return(mg_handle(MG_E_OBJECT, 1, oav));
169     cp1 = oname;
170     *cp1 = 'a';
171     for (i = 0; i < ap->ndim; i++) {
172     for (cp2 = ap->aarg[i].arg; *cp2; )
173     *++cp1 = *cp2++;
174     *++cp1 = '.';
175     }
176     *cp1 = '\0';
177     return(mg_handle(MG_E_OBJECT, 2, oav));
178 greg 1.1 }
179    
180    
181 greg 1.5 static long
182     comp_xfid(xfm) /* compute unique ID from matrix */
183     register MAT4 xfm;
184     {
185     static char shifttab[64] = { 15, 5, 11, 5, 6, 3,
186     9, 15, 13, 2, 13, 5, 2, 12, 14, 11,
187     11, 12, 12, 3, 2, 11, 8, 12, 1, 12,
188     5, 4, 15, 9, 14, 5, 13, 14, 2, 10,
189     10, 14, 12, 3, 5, 5, 14, 6, 12, 11,
190     13, 9, 12, 8, 1, 6, 5, 12, 7, 13,
191     15, 8, 9, 2, 6, 11, 9, 11 };
192     register int i;
193     register long xid;
194    
195     xid = 0; /* compute unique transform id */
196     for (i = 0; i < sizeof(MAT4)/sizeof(unsigned short); i++)
197     xid ^= (long)(((unsigned short *)xfm)[i]) << shifttab[i&63];
198     return(xid);
199     }
200    
201    
202 greg 1.1 void
203 greg 1.2 xf_clear() /* clear transform stack */
204     {
205     register XF_SPEC *spec;
206    
207     if (xf_maxarg) {
208     free((MEM_PTR)xf_argv);
209     xf_argv = NULL;
210     xf_maxarg = 0;
211     }
212 greg 1.5 xf_argc = 0;
213 greg 1.2 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     }