ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.9
Committed: Wed May 10 22:20:57 1995 UTC (28 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.8: +25 -27 lines
Log Message:
fixed bug in order of global transform arguments

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 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
28 static XF_SPEC *new_xf();
29 static long comp_xfid();
30 static int put_oname();
31
32
33 int
34 xf_handler(ac, av) /* handle xf entity */
35 int ac;
36 char **av;
37 {
38 register XF_SPEC *spec;
39 register int n;
40 int rv;
41
42 if (ac == 1) { /* something with existing transform */
43 if ((spec = xf_context) == NULL)
44 return(MG_OK); /* should be error? */
45 n = -1;
46 if (spec->xarr != NULL) { /* check for iteration */
47 register struct xf_array *ap = spec->xarr;
48
49 (void)put_oname((struct xf_array *)NULL);
50 n = ap->ndim;
51 while (n--) {
52 if (++ap->aarg[n].i < ap->aarg[n].n)
53 break;
54 (void)strcpy(ap->aarg[n].arg, "0");
55 ap->aarg[n].i = 0;
56 }
57 if (n >= 0) {
58 if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
59 return(rv);
60 sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
61 (void)put_oname(ap);
62 } else
63 free((MEM_PTR)ap);
64 }
65 if (n < 0) { /* pop transform */
66 xf_context = spec->prev;
67 free((MEM_PTR)spec);
68 return(MG_OK);
69 }
70 } else { /* else allocate transform */
71 if ((spec = new_xf(ac-1, av+1)) == NULL)
72 return(MG_EMEM);
73 spec->prev = xf_context; /* push onto stack */
74 xf_context = spec;
75 }
76 /* translate new specification */
77 n = xf_ac(spec);
78 if (spec->prev != NULL) /* incremental comp. is more eff. */
79 n -= xf_ac(spec->prev);
80 if (xf(&spec->xf, n, xf_av(spec)) != n)
81 return(MG_ETYPE);
82 /* check for vertex reversal */
83 if ((spec->rev = (spec->xf.sca < 0.)))
84 spec->xf.sca = -spec->xf.sca;
85 /* compute total transformation */
86 if (spec->prev != NULL) {
87 multmat4(spec->xf.xfm, spec->xf.xfm, spec->prev->xf.xfm);
88 spec->xf.sca *= spec->prev->xf.sca;
89 spec->rev ^= spec->prev->rev;
90 }
91 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 if (spec == NULL)
118 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 spec->xac = ac + xf_argc;
128 /* and store new xf arguments */
129 if (xf_argbeg == NULL || xf_av(spec) < xf_argbeg) {
130 register char **newav =
131 (char **)malloc((spec->xac+1)*sizeof(char *));
132 if (newav == NULL)
133 return(NULL);
134 for (i = xf_argc; i-- > 0; )
135 newav[ac+i] = xf_argend[i-xf_context->xac];
136 *(xf_argend = newav + spec->xac) = NULL;
137 if (xf_argbeg != NULL)
138 free((MEM_PTR)xf_argbeg);
139 xf_argbeg = newav;
140 }
141 cp = (char *)(spec + 1); /* use memory allocated above */
142 for (i = 0; i < ac; i++)
143 if (!strcmp(av[i], "-a")) {
144 xf_av(spec)[i++] = "-i";
145 xf_av(spec)[i] = strcpy(
146 spec->xarr->aarg[spec->xarr->ndim].arg,
147 "0");
148 spec->xarr->aarg[spec->xarr->ndim].i = 0;
149 spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[i]);
150 } else {
151 xf_av(spec)[i] = strcpy(cp, av[i]);
152 cp += strlen(av[i]) + 1;
153 }
154 if (spec->xarr != NULL)
155 (void)put_oname(spec->xarr);
156 return(spec);
157 }
158
159
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 }
181
182
183 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 void
205 xf_clear() /* clear transform stack */
206 {
207 register XF_SPEC *spec;
208
209 if (xf_argbeg != NULL) {
210 free((MEM_PTR)xf_argbeg);
211 xf_argbeg = xf_argend = NULL;
212 }
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 }