ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/xf.c
Revision: 1.14
Committed: Fri Feb 28 20:11:30 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P1, rad4R0, rad3R5, rad3R6, rad3R6P1, rad3R8, rad3R9, rad3R7P2
Changes since 1.13: +2 -5 lines
Log Message:
Updates for 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Routines for 4x4 homogeneous, rigid-body transformations
6 */
7
8 #include <stdio.h>
9 #include <math.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "parser.h"
13
14 #define d2r(a) ((PI/180.)*(a))
15
16 #define checkarg(a,l) if (av[i][a] || badarg(ac-i-1,av+i+1,l)) goto done
17
18 MAT4 m4ident = MAT4IDENT;
19
20 static MAT4 m4tmp; /* for efficiency */
21
22 XF_SPEC *xf_context = NULL; /* current context */
23 char **xf_argend; /* end of transform argument list */
24 static char **xf_argbeg; /* beginning of transform argument list */
25
26
27 int
28 xf_handler(ac, av) /* handle xf entity */
29 int ac;
30 char **av;
31 {
32 register XF_SPEC *spec;
33 register int n;
34 int rv;
35
36 if (ac == 1) { /* something with existing transform */
37 if ((spec = xf_context) == NULL)
38 return(MG_ECNTXT);
39 n = -1;
40 if (spec->xarr != NULL) { /* check for iteration */
41 register struct xf_array *ap = spec->xarr;
42
43 (void)xf_aname((struct xf_array *)NULL);
44 n = ap->ndim;
45 while (n--) {
46 if (++ap->aarg[n].i < ap->aarg[n].n)
47 break;
48 (void)strcpy(ap->aarg[n].arg, "0");
49 ap->aarg[n].i = 0;
50 }
51 if (n >= 0) {
52 if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
53 return(rv);
54 sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
55 (void)xf_aname(ap);
56 }
57 }
58 if (n < 0) { /* pop transform */
59 xf_context = spec->prev;
60 free_xf(spec);
61 return(MG_OK);
62 }
63 } else { /* else allocate transform */
64 if ((spec = new_xf(ac-1, av+1)) == NULL)
65 return(MG_EMEM);
66 if (spec->xarr != NULL)
67 (void)xf_aname(spec->xarr);
68 spec->prev = xf_context; /* push onto stack */
69 xf_context = spec;
70 }
71 /* translate new specification */
72 n = xf_ac(spec);
73 n -= xf_ac(spec->prev); /* incremental comp. is more eff. */
74 if (xf(&spec->xf, n, xf_av(spec)) != n)
75 return(MG_ETYPE);
76 /* check for vertex reversal */
77 if ((spec->rev = (spec->xf.sca < 0.)))
78 spec->xf.sca = -spec->xf.sca;
79 /* compute total transformation */
80 if (spec->prev != NULL) {
81 multmat4(spec->xf.xfm, spec->xf.xfm, spec->prev->xf.xfm);
82 spec->xf.sca *= spec->prev->xf.sca;
83 spec->rev ^= spec->prev->rev;
84 }
85 spec->xid = comp_xfid(spec->xf.xfm); /* compute unique ID */
86 return(MG_OK);
87 }
88
89
90 XF_SPEC *
91 new_xf(ac, av) /* allocate new transform structure */
92 int ac;
93 char **av;
94 {
95 register XF_SPEC *spec;
96 register int i;
97 char *cp;
98 int n, ndim;
99
100 ndim = 0;
101 n = 0; /* compute space req'd by arguments */
102 for (i = 0; i < ac; i++)
103 if (!strcmp(av[i], "-a")) {
104 ndim++;
105 i++;
106 } else
107 n += strlen(av[i]) + 1;
108 if (ndim > XF_MAXDIM)
109 return(NULL);
110 spec = (XF_SPEC *)malloc(sizeof(XF_SPEC) + n);
111 if (spec == NULL)
112 return(NULL);
113 if (ndim) {
114 spec->xarr = (struct xf_array *)malloc(sizeof(struct xf_array));
115 if (spec->xarr == NULL)
116 return(NULL);
117 mg_fgetpos(&spec->xarr->spos);
118 spec->xarr->ndim = 0; /* incremented below */
119 } else
120 spec->xarr = NULL;
121 spec->xac = ac + xf_argc;
122 /* and store new xf arguments */
123 if (xf_argbeg == NULL || xf_av(spec) < xf_argbeg) {
124 register char **newav =
125 (char **)malloc((spec->xac+1)*sizeof(char *));
126 if (newav == NULL)
127 return(NULL);
128 for (i = xf_argc; i-- > 0; )
129 newav[ac+i] = xf_argend[i-xf_context->xac];
130 *(xf_argend = newav + spec->xac) = NULL;
131 if (xf_argbeg != NULL)
132 free((MEM_PTR)xf_argbeg);
133 xf_argbeg = newav;
134 }
135 cp = (char *)(spec + 1); /* use memory allocated above */
136 for (i = 0; i < ac; i++)
137 if (!strcmp(av[i], "-a")) {
138 xf_av(spec)[i++] = "-i";
139 xf_av(spec)[i] = strcpy(
140 spec->xarr->aarg[spec->xarr->ndim].arg,
141 "0");
142 spec->xarr->aarg[spec->xarr->ndim].i = 0;
143 spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[i]);
144 } else {
145 xf_av(spec)[i] = strcpy(cp, av[i]);
146 cp += strlen(av[i]) + 1;
147 }
148 return(spec);
149 }
150
151
152 void
153 free_xf(spec) /* free a transform */
154 register XF_SPEC *spec;
155 {
156 if (spec->xarr != NULL)
157 free((MEM_PTR)spec->xarr);
158 free((MEM_PTR)spec);
159 }
160
161
162 int
163 xf_aname(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 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_argbeg != NULL) {
212 free((MEM_PTR)xf_argbeg);
213 xf_argbeg = xf_argend = NULL;
214 }
215 while ((spec = xf_context) != NULL) {
216 xf_context = spec->prev;
217 free_xf(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 }