ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.13
Committed: Mon Dec 15 09:41:37 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 1.12: +1 -0 lines
Log Message:
added stdlib.h for better reliability on some systems

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