ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.8
Committed: Tue Apr 18 16:52:28 1995 UTC (29 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +6 -8 lines
Log Message:
minor optimization

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
44 greg 1.5 if (ac == 1) { /* something with existing transform */
45 greg 1.1 if ((spec = xf_context) == NULL)
46     return(MG_OK); /* should be error? */
47 greg 1.5 n = -1;
48     if (spec->xarr != NULL) { /* check for iteration */
49     register struct xf_array *ap = spec->xarr;
50    
51     (void)put_oname((struct xf_array *)NULL);
52     n = ap->ndim;
53     while (n--) {
54     if (++ap->aarg[n].i < ap->aarg[n].n)
55     break;
56     (void)strcpy(ap->aarg[n].arg, "0");
57     ap->aarg[n].i = 0;
58     }
59     if (n >= 0) {
60     if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
61     return(rv);
62     sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
63     (void)put_oname(ap);
64     } else
65     free((MEM_PTR)ap);
66     }
67     if (n < 0) { /* pop transform */
68     xf_argv[xf_argc=spec->xav0] = NULL;
69     xf_context = spec->prev;
70     free((MEM_PTR)spec);
71     return(MG_OK);
72     }
73     } else { /* else allocate transform */
74     if ((spec = new_xf(ac-1, av+1)) == NULL)
75     return(MG_EMEM);
76     spec->prev = xf_context; /* push onto stack */
77     xf_context = spec;
78 greg 1.1 }
79     /* translate new specification */
80 greg 1.8 if (xf(&spec->xf, spec->xac, &xf_argv[spec->xav0]) != spec->xac)
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.1 spec->xav0 = xf_argc;
128 greg 1.5 spec->xac = ac;
129 greg 1.1 /* and store new xf arguments */
130 greg 1.5 if (xf_argc+ac+1 > xf_maxarg) {
131 greg 1.1 if (!xf_maxarg)
132     xf_argv = (char **)malloc(
133 greg 1.5 (xf_maxarg=ac+1)*sizeof(char *));
134 greg 1.1 else
135     xf_argv = (char **)realloc((MEM_PTR)xf_argv,
136 greg 1.5 (xf_maxarg=xf_argc+ac+1)*sizeof(char *));
137 greg 1.1 if (xf_argv == NULL)
138 greg 1.5 return(NULL);
139 greg 1.1 }
140 greg 1.5 cp = (char *)(spec + 1); /* use memory allocated above */
141     for (i = 0; i < ac; i++)
142     if (!strcmp(av[i], "-a")) {
143     xf_argv[xf_argc++] = "-i";
144     xf_argv[xf_argc++] = strcpy(
145     spec->xarr->aarg[spec->xarr->ndim].arg,
146     "0");
147     spec->xarr->aarg[spec->xarr->ndim].i = 0;
148     spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[++i]);
149     } else {
150     xf_argv[xf_argc++] = strcpy(cp, av[i]);
151     cp += strlen(av[i]) + 1;
152     }
153 greg 1.1 xf_argv[xf_argc] = NULL;
154 greg 1.5 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     if (xf_maxarg) {
210     free((MEM_PTR)xf_argv);
211     xf_argv = NULL;
212     xf_maxarg = 0;
213     }
214 greg 1.5 xf_argc = 0;
215 greg 1.2 while ((spec = xf_context) != NULL) {
216     xf_context = spec->prev;
217 greg 1.5 if (spec->xarr != NULL)
218     free((MEM_PTR)spec->xarr);
219 greg 1.2 free((MEM_PTR)spec);
220     }
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     v1[0] = v2[0];
230     v1[1] = v2[1];
231     v1[2] = v2[2];
232     return;
233     }
234     multp3(v1, v2, xf_context->xf.xfm);
235     }
236    
237    
238     void
239     xf_xfmvect(v1, v2) /* transform a vector using current matrix */
240     FVECT v1, v2;
241     {
242     if (xf_context == NULL) {
243     v1[0] = v2[0];
244     v1[1] = v2[1];
245     v1[2] = v2[2];
246     return;
247     }
248     multv3(v1, v2, xf_context->xf.xfm);
249     }
250    
251    
252     void
253     xf_rotvect(v1, v2) /* rotate a vector using current matrix */
254     FVECT v1, v2;
255     {
256     xf_xfmvect(v1, v2);
257     if (xf_context == NULL)
258     return;
259     v1[0] /= xf_context->xf.sca;
260     v1[1] /= xf_context->xf.sca;
261     v1[2] /= xf_context->xf.sca;
262     }
263    
264    
265     double
266     xf_scale(d) /* scale a number by the current transform */
267     double d;
268     {
269     if (xf_context == NULL)
270     return(d);
271     return(d*xf_context->xf.sca);
272     }
273    
274    
275     void
276     multmat4(m4a, m4b, m4c) /* multiply m4b X m4c and put into m4a */
277     MAT4 m4a;
278     register MAT4 m4b, m4c;
279     {
280     register int i, j;
281    
282     for (i = 4; i--; )
283     for (j = 4; j--; )
284     m4tmp[i][j] = m4b[i][0]*m4c[0][j] +
285     m4b[i][1]*m4c[1][j] +
286     m4b[i][2]*m4c[2][j] +
287     m4b[i][3]*m4c[3][j];
288    
289     copymat4(m4a, m4tmp);
290     }
291    
292    
293     void
294     multv3(v3a, v3b, m4) /* transform vector v3b by m4 and put into v3a */
295     FVECT v3a;
296     register FVECT v3b;
297     register MAT4 m4;
298     {
299     m4tmp[0][0] = v3b[0]*m4[0][0] + v3b[1]*m4[1][0] + v3b[2]*m4[2][0];
300     m4tmp[0][1] = v3b[0]*m4[0][1] + v3b[1]*m4[1][1] + v3b[2]*m4[2][1];
301     m4tmp[0][2] = v3b[0]*m4[0][2] + v3b[1]*m4[1][2] + v3b[2]*m4[2][2];
302    
303     v3a[0] = m4tmp[0][0];
304     v3a[1] = m4tmp[0][1];
305     v3a[2] = m4tmp[0][2];
306     }
307    
308    
309     void
310     multp3(p3a, p3b, m4) /* transform p3b by m4 and put into p3a */
311     register FVECT p3a;
312     FVECT p3b;
313     register MAT4 m4;
314     {
315     multv3(p3a, p3b, m4); /* transform as vector */
316     p3a[0] += m4[3][0]; /* translate */
317     p3a[1] += m4[3][1];
318     p3a[2] += m4[3][2];
319     }
320    
321    
322     int
323     xf(ret, ac, av) /* get transform specification */
324     register XF *ret;
325     int ac;
326 greg 1.3 char **av;
327 greg 1.1 {
328     MAT4 xfmat, m4;
329     double xfsca, dtmp;
330     int i, icnt;
331    
332     setident4(ret->xfm);
333     ret->sca = 1.0;
334    
335     icnt = 1;
336     setident4(xfmat);
337     xfsca = 1.0;
338    
339     for (i = 0; i < ac && av[i][0] == '-'; i++) {
340    
341     setident4(m4);
342    
343     switch (av[i][1]) {
344    
345     case 't': /* translate */
346     checkarg(2,"fff");
347     m4[3][0] = atof(av[++i]);
348     m4[3][1] = atof(av[++i]);
349     m4[3][2] = atof(av[++i]);
350     break;
351    
352     case 'r': /* rotate */
353     switch (av[i][2]) {
354     case 'x':
355     checkarg(3,"f");
356     dtmp = d2r(atof(av[++i]));
357     m4[1][1] = m4[2][2] = cos(dtmp);
358     m4[2][1] = -(m4[1][2] = sin(dtmp));
359     break;
360     case 'y':
361     checkarg(3,"f");
362     dtmp = d2r(atof(av[++i]));
363     m4[0][0] = m4[2][2] = cos(dtmp);
364     m4[0][2] = -(m4[2][0] = sin(dtmp));
365     break;
366     case 'z':
367     checkarg(3,"f");
368     dtmp = d2r(atof(av[++i]));
369     m4[0][0] = m4[1][1] = cos(dtmp);
370     m4[1][0] = -(m4[0][1] = sin(dtmp));
371     break;
372     default:
373     goto done;
374     }
375     break;
376    
377     case 's': /* scale */
378     checkarg(2,"f");
379     dtmp = atof(av[i+1]);
380     if (dtmp == 0.0) goto done;
381     i++;
382     xfsca *=
383     m4[0][0] =
384     m4[1][1] =
385     m4[2][2] = dtmp;
386     break;
387    
388     case 'm': /* mirror */
389     switch (av[i][2]) {
390     case 'x':
391     checkarg(3,"");
392     xfsca *=
393     m4[0][0] = -1.0;
394     break;
395     case 'y':
396     checkarg(3,"");
397     xfsca *=
398     m4[1][1] = -1.0;
399     break;
400     case 'z':
401     checkarg(3,"");
402     xfsca *=
403     m4[2][2] = -1.0;
404     break;
405     default:
406     goto done;
407     }
408     break;
409    
410     case 'i': /* iterate */
411     checkarg(2,"i");
412     while (icnt-- > 0) {
413     multmat4(ret->xfm, ret->xfm, xfmat);
414     ret->sca *= xfsca;
415     }
416     icnt = atoi(av[++i]);
417     setident4(xfmat);
418     xfsca = 1.0;
419     continue;
420    
421     default:
422     goto done;
423    
424     }
425     multmat4(xfmat, xfmat, m4);
426     }
427     done:
428     while (icnt-- > 0) {
429     multmat4(ret->xfm, ret->xfm, xfmat);
430     ret->sca *= xfsca;
431     }
432     return(i);
433     }