ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.14
Committed: Fri Feb 28 20:11:30 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P1, rad4R0, rad3R5, rad3R6, rad3R6P1, rad3R8, rad3R9, rad3R7P2
Changes since 1.13: +2 -5 lines
Log Message:
Updates for 3.5 release

File Contents

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