ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.6
Committed: Mon Jul 11 14:47:12 1994 UTC (29 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.5: +2 -2 lines
Log Message:
fixed order of transformation accumulation (serious bug!)

File Contents

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