ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.13
Committed: Mon Dec 15 09:41:37 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 1.12: +1 -0 lines
Log Message:
added stdlib.h for better reliability on some systems

File Contents

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