ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.11
Committed: Wed Nov 29 16:45:10 1995 UTC (28 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +1 -1 lines
Log Message:
added error for unmatched xf or o context close

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_ECNTXT);
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 VCOPY(v1, v2);
228 return;
229 }
230 multp3(v1, v2, xf_context->xf.xfm);
231 }
232
233
234 void
235 xf_xfmvect(v1, v2) /* transform a vector using current matrix */
236 FVECT v1, v2;
237 {
238 if (xf_context == NULL) {
239 VCOPY(v1, v2);
240 return;
241 }
242 multv3(v1, v2, xf_context->xf.xfm);
243 }
244
245
246 void
247 xf_rotvect(v1, v2) /* rotate a vector using current matrix */
248 FVECT v1, v2;
249 {
250 xf_xfmvect(v1, v2);
251 if (xf_context == NULL)
252 return;
253 v1[0] /= xf_context->xf.sca;
254 v1[1] /= xf_context->xf.sca;
255 v1[2] /= xf_context->xf.sca;
256 }
257
258
259 double
260 xf_scale(d) /* scale a number by the current transform */
261 double d;
262 {
263 if (xf_context == NULL)
264 return(d);
265 return(d*xf_context->xf.sca);
266 }
267
268
269 void
270 multmat4(m4a, m4b, m4c) /* multiply m4b X m4c and put into m4a */
271 MAT4 m4a;
272 register MAT4 m4b, m4c;
273 {
274 register int i, j;
275
276 for (i = 4; i--; )
277 for (j = 4; j--; )
278 m4tmp[i][j] = m4b[i][0]*m4c[0][j] +
279 m4b[i][1]*m4c[1][j] +
280 m4b[i][2]*m4c[2][j] +
281 m4b[i][3]*m4c[3][j];
282
283 copymat4(m4a, m4tmp);
284 }
285
286
287 void
288 multv3(v3a, v3b, m4) /* transform vector v3b by m4 and put into v3a */
289 FVECT v3a;
290 register FVECT v3b;
291 register MAT4 m4;
292 {
293 m4tmp[0][0] = v3b[0]*m4[0][0] + v3b[1]*m4[1][0] + v3b[2]*m4[2][0];
294 m4tmp[0][1] = v3b[0]*m4[0][1] + v3b[1]*m4[1][1] + v3b[2]*m4[2][1];
295 m4tmp[0][2] = v3b[0]*m4[0][2] + v3b[1]*m4[1][2] + v3b[2]*m4[2][2];
296
297 v3a[0] = m4tmp[0][0];
298 v3a[1] = m4tmp[0][1];
299 v3a[2] = m4tmp[0][2];
300 }
301
302
303 void
304 multp3(p3a, p3b, m4) /* transform p3b by m4 and put into p3a */
305 register FVECT p3a;
306 FVECT p3b;
307 register MAT4 m4;
308 {
309 multv3(p3a, p3b, m4); /* transform as vector */
310 p3a[0] += m4[3][0]; /* translate */
311 p3a[1] += m4[3][1];
312 p3a[2] += m4[3][2];
313 }
314
315
316 int
317 xf(ret, ac, av) /* get transform specification */
318 register XF *ret;
319 int ac;
320 char **av;
321 {
322 MAT4 xfmat, m4;
323 double xfsca, dtmp;
324 int i, icnt;
325
326 setident4(ret->xfm);
327 ret->sca = 1.0;
328
329 icnt = 1;
330 setident4(xfmat);
331 xfsca = 1.0;
332
333 for (i = 0; i < ac && av[i][0] == '-'; i++) {
334
335 setident4(m4);
336
337 switch (av[i][1]) {
338
339 case 't': /* translate */
340 checkarg(2,"fff");
341 m4[3][0] = atof(av[++i]);
342 m4[3][1] = atof(av[++i]);
343 m4[3][2] = atof(av[++i]);
344 break;
345
346 case 'r': /* rotate */
347 switch (av[i][2]) {
348 case 'x':
349 checkarg(3,"f");
350 dtmp = d2r(atof(av[++i]));
351 m4[1][1] = m4[2][2] = cos(dtmp);
352 m4[2][1] = -(m4[1][2] = sin(dtmp));
353 break;
354 case 'y':
355 checkarg(3,"f");
356 dtmp = d2r(atof(av[++i]));
357 m4[0][0] = m4[2][2] = cos(dtmp);
358 m4[0][2] = -(m4[2][0] = sin(dtmp));
359 break;
360 case 'z':
361 checkarg(3,"f");
362 dtmp = d2r(atof(av[++i]));
363 m4[0][0] = m4[1][1] = cos(dtmp);
364 m4[1][0] = -(m4[0][1] = sin(dtmp));
365 break;
366 default:
367 goto done;
368 }
369 break;
370
371 case 's': /* scale */
372 checkarg(2,"f");
373 dtmp = atof(av[i+1]);
374 if (dtmp == 0.0) goto done;
375 i++;
376 xfsca *=
377 m4[0][0] =
378 m4[1][1] =
379 m4[2][2] = dtmp;
380 break;
381
382 case 'm': /* mirror */
383 switch (av[i][2]) {
384 case 'x':
385 checkarg(3,"");
386 xfsca *=
387 m4[0][0] = -1.0;
388 break;
389 case 'y':
390 checkarg(3,"");
391 xfsca *=
392 m4[1][1] = -1.0;
393 break;
394 case 'z':
395 checkarg(3,"");
396 xfsca *=
397 m4[2][2] = -1.0;
398 break;
399 default:
400 goto done;
401 }
402 break;
403
404 case 'i': /* iterate */
405 checkarg(2,"i");
406 while (icnt-- > 0) {
407 multmat4(ret->xfm, ret->xfm, xfmat);
408 ret->sca *= xfsca;
409 }
410 icnt = atoi(av[++i]);
411 setident4(xfmat);
412 xfsca = 1.0;
413 continue;
414
415 default:
416 goto done;
417
418 }
419 multmat4(xfmat, xfmat, m4);
420 }
421 done:
422 while (icnt-- > 0) {
423 multmat4(ret->xfm, ret->xfm, xfmat);
424 ret->sca *= xfsca;
425 }
426 return(i);
427 }