ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.8
Committed: Tue Apr 18 16:52:28 1995 UTC (29 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +6 -8 lines
Log Message:
minor optimization

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
44 if (ac == 1) { /* something with existing transform */
45 if ((spec = xf_context) == NULL)
46 return(MG_OK); /* should be error? */
47 n = -1;
48 if (spec->xarr != NULL) { /* check for iteration */
49 register struct xf_array *ap = spec->xarr;
50
51 (void)put_oname((struct xf_array *)NULL);
52 n = ap->ndim;
53 while (n--) {
54 if (++ap->aarg[n].i < ap->aarg[n].n)
55 break;
56 (void)strcpy(ap->aarg[n].arg, "0");
57 ap->aarg[n].i = 0;
58 }
59 if (n >= 0) {
60 if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
61 return(rv);
62 sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
63 (void)put_oname(ap);
64 } else
65 free((MEM_PTR)ap);
66 }
67 if (n < 0) { /* pop transform */
68 xf_argv[xf_argc=spec->xav0] = NULL;
69 xf_context = spec->prev;
70 free((MEM_PTR)spec);
71 return(MG_OK);
72 }
73 } else { /* else allocate transform */
74 if ((spec = new_xf(ac-1, av+1)) == NULL)
75 return(MG_EMEM);
76 spec->prev = xf_context; /* push onto stack */
77 xf_context = spec;
78 }
79 /* translate new specification */
80 if (xf(&spec->xf, spec->xac, &xf_argv[spec->xav0]) != spec->xac)
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->xav0 = xf_argc;
128 spec->xac = ac;
129 /* and store new xf arguments */
130 if (xf_argc+ac+1 > xf_maxarg) {
131 if (!xf_maxarg)
132 xf_argv = (char **)malloc(
133 (xf_maxarg=ac+1)*sizeof(char *));
134 else
135 xf_argv = (char **)realloc((MEM_PTR)xf_argv,
136 (xf_maxarg=xf_argc+ac+1)*sizeof(char *));
137 if (xf_argv == NULL)
138 return(NULL);
139 }
140 cp = (char *)(spec + 1); /* use memory allocated above */
141 for (i = 0; i < ac; i++)
142 if (!strcmp(av[i], "-a")) {
143 xf_argv[xf_argc++] = "-i";
144 xf_argv[xf_argc++] = strcpy(
145 spec->xarr->aarg[spec->xarr->ndim].arg,
146 "0");
147 spec->xarr->aarg[spec->xarr->ndim].i = 0;
148 spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[++i]);
149 } else {
150 xf_argv[xf_argc++] = strcpy(cp, av[i]);
151 cp += strlen(av[i]) + 1;
152 }
153 xf_argv[xf_argc] = NULL;
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_maxarg) {
210 free((MEM_PTR)xf_argv);
211 xf_argv = NULL;
212 xf_maxarg = 0;
213 }
214 xf_argc = 0;
215 while ((spec = xf_context) != NULL) {
216 xf_context = spec->prev;
217 if (spec->xarr != NULL)
218 free((MEM_PTR)spec->xarr);
219 free((MEM_PTR)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 v1[0] = v2[0];
230 v1[1] = v2[1];
231 v1[2] = v2[2];
232 return;
233 }
234 multp3(v1, v2, xf_context->xf.xfm);
235 }
236
237
238 void
239 xf_xfmvect(v1, v2) /* transform a vector using current matrix */
240 FVECT v1, v2;
241 {
242 if (xf_context == NULL) {
243 v1[0] = v2[0];
244 v1[1] = v2[1];
245 v1[2] = v2[2];
246 return;
247 }
248 multv3(v1, v2, xf_context->xf.xfm);
249 }
250
251
252 void
253 xf_rotvect(v1, v2) /* rotate a vector using current matrix */
254 FVECT v1, v2;
255 {
256 xf_xfmvect(v1, v2);
257 if (xf_context == NULL)
258 return;
259 v1[0] /= xf_context->xf.sca;
260 v1[1] /= xf_context->xf.sca;
261 v1[2] /= xf_context->xf.sca;
262 }
263
264
265 double
266 xf_scale(d) /* scale a number by the current transform */
267 double d;
268 {
269 if (xf_context == NULL)
270 return(d);
271 return(d*xf_context->xf.sca);
272 }
273
274
275 void
276 multmat4(m4a, m4b, m4c) /* multiply m4b X m4c and put into m4a */
277 MAT4 m4a;
278 register MAT4 m4b, m4c;
279 {
280 register int i, j;
281
282 for (i = 4; i--; )
283 for (j = 4; j--; )
284 m4tmp[i][j] = m4b[i][0]*m4c[0][j] +
285 m4b[i][1]*m4c[1][j] +
286 m4b[i][2]*m4c[2][j] +
287 m4b[i][3]*m4c[3][j];
288
289 copymat4(m4a, m4tmp);
290 }
291
292
293 void
294 multv3(v3a, v3b, m4) /* transform vector v3b by m4 and put into v3a */
295 FVECT v3a;
296 register FVECT v3b;
297 register MAT4 m4;
298 {
299 m4tmp[0][0] = v3b[0]*m4[0][0] + v3b[1]*m4[1][0] + v3b[2]*m4[2][0];
300 m4tmp[0][1] = v3b[0]*m4[0][1] + v3b[1]*m4[1][1] + v3b[2]*m4[2][1];
301 m4tmp[0][2] = v3b[0]*m4[0][2] + v3b[1]*m4[1][2] + v3b[2]*m4[2][2];
302
303 v3a[0] = m4tmp[0][0];
304 v3a[1] = m4tmp[0][1];
305 v3a[2] = m4tmp[0][2];
306 }
307
308
309 void
310 multp3(p3a, p3b, m4) /* transform p3b by m4 and put into p3a */
311 register FVECT p3a;
312 FVECT p3b;
313 register MAT4 m4;
314 {
315 multv3(p3a, p3b, m4); /* transform as vector */
316 p3a[0] += m4[3][0]; /* translate */
317 p3a[1] += m4[3][1];
318 p3a[2] += m4[3][2];
319 }
320
321
322 int
323 xf(ret, ac, av) /* get transform specification */
324 register XF *ret;
325 int ac;
326 char **av;
327 {
328 MAT4 xfmat, m4;
329 double xfsca, dtmp;
330 int i, icnt;
331
332 setident4(ret->xfm);
333 ret->sca = 1.0;
334
335 icnt = 1;
336 setident4(xfmat);
337 xfsca = 1.0;
338
339 for (i = 0; i < ac && av[i][0] == '-'; i++) {
340
341 setident4(m4);
342
343 switch (av[i][1]) {
344
345 case 't': /* translate */
346 checkarg(2,"fff");
347 m4[3][0] = atof(av[++i]);
348 m4[3][1] = atof(av[++i]);
349 m4[3][2] = atof(av[++i]);
350 break;
351
352 case 'r': /* rotate */
353 switch (av[i][2]) {
354 case 'x':
355 checkarg(3,"f");
356 dtmp = d2r(atof(av[++i]));
357 m4[1][1] = m4[2][2] = cos(dtmp);
358 m4[2][1] = -(m4[1][2] = sin(dtmp));
359 break;
360 case 'y':
361 checkarg(3,"f");
362 dtmp = d2r(atof(av[++i]));
363 m4[0][0] = m4[2][2] = cos(dtmp);
364 m4[0][2] = -(m4[2][0] = sin(dtmp));
365 break;
366 case 'z':
367 checkarg(3,"f");
368 dtmp = d2r(atof(av[++i]));
369 m4[0][0] = m4[1][1] = cos(dtmp);
370 m4[1][0] = -(m4[0][1] = sin(dtmp));
371 break;
372 default:
373 goto done;
374 }
375 break;
376
377 case 's': /* scale */
378 checkarg(2,"f");
379 dtmp = atof(av[i+1]);
380 if (dtmp == 0.0) goto done;
381 i++;
382 xfsca *=
383 m4[0][0] =
384 m4[1][1] =
385 m4[2][2] = dtmp;
386 break;
387
388 case 'm': /* mirror */
389 switch (av[i][2]) {
390 case 'x':
391 checkarg(3,"");
392 xfsca *=
393 m4[0][0] = -1.0;
394 break;
395 case 'y':
396 checkarg(3,"");
397 xfsca *=
398 m4[1][1] = -1.0;
399 break;
400 case 'z':
401 checkarg(3,"");
402 xfsca *=
403 m4[2][2] = -1.0;
404 break;
405 default:
406 goto done;
407 }
408 break;
409
410 case 'i': /* iterate */
411 checkarg(2,"i");
412 while (icnt-- > 0) {
413 multmat4(ret->xfm, ret->xfm, xfmat);
414 ret->sca *= xfsca;
415 }
416 icnt = atoi(av[++i]);
417 setident4(xfmat);
418 xfsca = 1.0;
419 continue;
420
421 default:
422 goto done;
423
424 }
425 multmat4(xfmat, xfmat, m4);
426 }
427 done:
428 while (icnt-- > 0) {
429 multmat4(ret->xfm, ret->xfm, xfmat);
430 ret->sca *= xfsca;
431 }
432 return(i);
433 }