ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.12
Committed: Wed Nov 29 19:55:45 1995 UTC (28 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.11: +23 -21 lines
Log Message:
made some of xf.c's internal (static) routines global

File Contents

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