ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.7
Committed: Thu Jul 21 14:56:39 1994 UTC (29 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +4 -0 lines
Log Message:
added rev field to XF_SPEC structure to indicate vertex reversal

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