ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.7
Committed: Thu Jul 21 14:56:39 1994 UTC (29 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +4 -0 lines
Log Message:
added rev field to XF_SPEC structure to indicate vertex reversal

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