ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.12
Committed: Wed Nov 29 19:55:45 1995 UTC (28 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.11: +23 -21 lines
Log Message:
made some of xf.c's internal (static) routines global

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