ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.10
Committed: Wed Nov 22 16:09:23 1995 UTC (28 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +2 -6 lines
Log Message:
applied VCOPY macro

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 greg 1.10 VCOPY(v1, v2);
228 greg 1.1 return;
229     }
230     multp3(v1, v2, xf_context->xf.xfm);
231     }
232    
233    
234     void
235     xf_xfmvect(v1, v2) /* transform a vector using current matrix */
236     FVECT v1, v2;
237     {
238     if (xf_context == NULL) {
239 greg 1.10 VCOPY(v1, v2);
240 greg 1.1 return;
241     }
242     multv3(v1, v2, xf_context->xf.xfm);
243     }
244    
245    
246     void
247     xf_rotvect(v1, v2) /* rotate a vector using current matrix */
248     FVECT v1, v2;
249     {
250     xf_xfmvect(v1, v2);
251     if (xf_context == NULL)
252     return;
253     v1[0] /= xf_context->xf.sca;
254     v1[1] /= xf_context->xf.sca;
255     v1[2] /= xf_context->xf.sca;
256     }
257    
258    
259     double
260     xf_scale(d) /* scale a number by the current transform */
261     double d;
262     {
263     if (xf_context == NULL)
264     return(d);
265     return(d*xf_context->xf.sca);
266     }
267    
268    
269     void
270     multmat4(m4a, m4b, m4c) /* multiply m4b X m4c and put into m4a */
271     MAT4 m4a;
272     register MAT4 m4b, m4c;
273     {
274     register int i, j;
275    
276     for (i = 4; i--; )
277     for (j = 4; j--; )
278     m4tmp[i][j] = m4b[i][0]*m4c[0][j] +
279     m4b[i][1]*m4c[1][j] +
280     m4b[i][2]*m4c[2][j] +
281     m4b[i][3]*m4c[3][j];
282    
283     copymat4(m4a, m4tmp);
284     }
285    
286    
287     void
288     multv3(v3a, v3b, m4) /* transform vector v3b by m4 and put into v3a */
289     FVECT v3a;
290     register FVECT v3b;
291     register MAT4 m4;
292     {
293     m4tmp[0][0] = v3b[0]*m4[0][0] + v3b[1]*m4[1][0] + v3b[2]*m4[2][0];
294     m4tmp[0][1] = v3b[0]*m4[0][1] + v3b[1]*m4[1][1] + v3b[2]*m4[2][1];
295     m4tmp[0][2] = v3b[0]*m4[0][2] + v3b[1]*m4[1][2] + v3b[2]*m4[2][2];
296    
297     v3a[0] = m4tmp[0][0];
298     v3a[1] = m4tmp[0][1];
299     v3a[2] = m4tmp[0][2];
300     }
301    
302    
303     void
304     multp3(p3a, p3b, m4) /* transform p3b by m4 and put into p3a */
305     register FVECT p3a;
306     FVECT p3b;
307     register MAT4 m4;
308     {
309     multv3(p3a, p3b, m4); /* transform as vector */
310     p3a[0] += m4[3][0]; /* translate */
311     p3a[1] += m4[3][1];
312     p3a[2] += m4[3][2];
313     }
314    
315    
316     int
317     xf(ret, ac, av) /* get transform specification */
318     register XF *ret;
319     int ac;
320 greg 1.3 char **av;
321 greg 1.1 {
322     MAT4 xfmat, m4;
323     double xfsca, dtmp;
324     int i, icnt;
325    
326     setident4(ret->xfm);
327     ret->sca = 1.0;
328    
329     icnt = 1;
330     setident4(xfmat);
331     xfsca = 1.0;
332    
333     for (i = 0; i < ac && av[i][0] == '-'; i++) {
334    
335     setident4(m4);
336    
337     switch (av[i][1]) {
338    
339     case 't': /* translate */
340     checkarg(2,"fff");
341     m4[3][0] = atof(av[++i]);
342     m4[3][1] = atof(av[++i]);
343     m4[3][2] = atof(av[++i]);
344     break;
345    
346     case 'r': /* rotate */
347     switch (av[i][2]) {
348     case 'x':
349     checkarg(3,"f");
350     dtmp = d2r(atof(av[++i]));
351     m4[1][1] = m4[2][2] = cos(dtmp);
352     m4[2][1] = -(m4[1][2] = sin(dtmp));
353     break;
354     case 'y':
355     checkarg(3,"f");
356     dtmp = d2r(atof(av[++i]));
357     m4[0][0] = m4[2][2] = cos(dtmp);
358     m4[0][2] = -(m4[2][0] = sin(dtmp));
359     break;
360     case 'z':
361     checkarg(3,"f");
362     dtmp = d2r(atof(av[++i]));
363     m4[0][0] = m4[1][1] = cos(dtmp);
364     m4[1][0] = -(m4[0][1] = sin(dtmp));
365     break;
366     default:
367     goto done;
368     }
369     break;
370    
371     case 's': /* scale */
372     checkarg(2,"f");
373     dtmp = atof(av[i+1]);
374     if (dtmp == 0.0) goto done;
375     i++;
376     xfsca *=
377     m4[0][0] =
378     m4[1][1] =
379     m4[2][2] = dtmp;
380     break;
381    
382     case 'm': /* mirror */
383     switch (av[i][2]) {
384     case 'x':
385     checkarg(3,"");
386     xfsca *=
387     m4[0][0] = -1.0;
388     break;
389     case 'y':
390     checkarg(3,"");
391     xfsca *=
392     m4[1][1] = -1.0;
393     break;
394     case 'z':
395     checkarg(3,"");
396     xfsca *=
397     m4[2][2] = -1.0;
398     break;
399     default:
400     goto done;
401     }
402     break;
403    
404     case 'i': /* iterate */
405     checkarg(2,"i");
406     while (icnt-- > 0) {
407     multmat4(ret->xfm, ret->xfm, xfmat);
408     ret->sca *= xfsca;
409     }
410     icnt = atoi(av[++i]);
411     setident4(xfmat);
412     xfsca = 1.0;
413     continue;
414    
415     default:
416     goto done;
417    
418     }
419     multmat4(xfmat, xfmat, m4);
420     }
421     done:
422     while (icnt-- > 0) {
423     multmat4(ret->xfm, ret->xfm, xfmat);
424     ret->sca *= xfsca;
425     }
426     return(i);
427     }