ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/mgf_xf.c
Revision: 3.1
Committed: Fri Feb 18 00:40:25 2011 UTC (13 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, rad5R2, rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R1, rad4R2P1, rad5R3, HEAD
Log Message:
Major code reorg, moving mgflib to common and introducing BSDF material

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: xf.c,v 1.15 2011/01/14 05:46:12 greg Exp $";
3 #endif
4 /*
5 * Routines for 4x4 homogeneous, rigid-body transformations
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "mgf_parser.h"
11
12 #define d2r(a) ((PI/180.)*(a))
13
14 #define checkarg(a,l) if (av[i][a] || badarg(ac-i-1,av+i+1,l)) goto done
15
16 XF_SPEC *xf_context = NULL; /* current context */
17 char **xf_argend; /* end of transform argument list */
18 static char **xf_argbeg; /* beginning of transform argument list */
19
20
21 int
22 xf_handler(int ac, char **av) /* handle xf entity */
23 {
24 register XF_SPEC *spec;
25 register int n;
26 int rv;
27
28 if (ac == 1) { /* something with existing transform */
29 if ((spec = xf_context) == NULL)
30 return(MG_ECNTXT);
31 n = -1;
32 if (spec->xarr != NULL) { /* check for iteration */
33 register struct xf_array *ap = spec->xarr;
34
35 (void)xf_aname((struct xf_array *)NULL);
36 n = ap->ndim;
37 while (n--) {
38 if (++ap->aarg[n].i < ap->aarg[n].n)
39 break;
40 (void)strcpy(ap->aarg[n].arg, "0");
41 ap->aarg[n].i = 0;
42 }
43 if (n >= 0) {
44 if ((rv = mg_fgoto(&ap->spos)) != MG_OK)
45 return(rv);
46 sprintf(ap->aarg[n].arg, "%d", ap->aarg[n].i);
47 (void)xf_aname(ap);
48 }
49 }
50 if (n < 0) { /* pop transform */
51 xf_context = spec->prev;
52 free_xf(spec);
53 return(MG_OK);
54 }
55 } else { /* else allocate transform */
56 if ((spec = new_xf(ac-1, av+1)) == NULL)
57 return(MG_EMEM);
58 if (spec->xarr != NULL)
59 (void)xf_aname(spec->xarr);
60 spec->prev = xf_context; /* push onto stack */
61 xf_context = spec;
62 }
63 /* translate new specification */
64 n = xf_ac(spec);
65 n -= xf_ac(spec->prev); /* incremental comp. is more eff. */
66 if (xf(&spec->xf, n, xf_av(spec)) != n)
67 return(MG_ETYPE);
68 /* check for vertex reversal */
69 if ((spec->rev = (spec->xf.sca < 0.)))
70 spec->xf.sca = -spec->xf.sca;
71 /* compute total transformation */
72 if (spec->prev != NULL) {
73 multmat4(spec->xf.xfm, spec->xf.xfm, spec->prev->xf.xfm);
74 spec->xf.sca *= spec->prev->xf.sca;
75 spec->rev ^= spec->prev->rev;
76 }
77 spec->xid = comp_xfid(spec->xf.xfm); /* compute unique ID */
78 return(MG_OK);
79 }
80
81
82 XF_SPEC *
83 new_xf(int ac, char **av) /* allocate new transform structure */
84 {
85 register XF_SPEC *spec;
86 register int i;
87 char *cp;
88 int n, ndim;
89
90 ndim = 0;
91 n = 0; /* compute space req'd by arguments */
92 for (i = 0; i < ac; i++)
93 if (!strcmp(av[i], "-a")) {
94 ndim++;
95 i++;
96 } else
97 n += strlen(av[i]) + 1;
98 if (ndim > XF_MAXDIM)
99 return(NULL);
100 spec = (XF_SPEC *)malloc(sizeof(XF_SPEC) + n);
101 if (spec == NULL)
102 return(NULL);
103 if (ndim) {
104 spec->xarr = (struct xf_array *)malloc(sizeof(struct xf_array));
105 if (spec->xarr == NULL)
106 return(NULL);
107 mg_fgetpos(&spec->xarr->spos);
108 spec->xarr->ndim = 0; /* incremented below */
109 } else
110 spec->xarr = NULL;
111 spec->xac = ac + xf_argc;
112 /* and store new xf arguments */
113 if (xf_argbeg == NULL || xf_av(spec) < xf_argbeg) {
114 register char **newav =
115 (char **)malloc((spec->xac+1)*sizeof(char *));
116 if (newav == NULL)
117 return(NULL);
118 for (i = xf_argc; i-- > 0; )
119 newav[ac+i] = xf_argend[i-xf_context->xac];
120 *(xf_argend = newav + spec->xac) = NULL;
121 if (xf_argbeg != NULL)
122 free(xf_argbeg);
123 xf_argbeg = newav;
124 }
125 cp = (char *)(spec + 1); /* use memory allocated above */
126 for (i = 0; i < ac; i++)
127 if (!strcmp(av[i], "-a")) {
128 xf_av(spec)[i++] = "-i";
129 xf_av(spec)[i] = strcpy(
130 spec->xarr->aarg[spec->xarr->ndim].arg,
131 "0");
132 spec->xarr->aarg[spec->xarr->ndim].i = 0;
133 spec->xarr->aarg[spec->xarr->ndim++].n = atoi(av[i]);
134 } else {
135 xf_av(spec)[i] = strcpy(cp, av[i]);
136 cp += strlen(av[i]) + 1;
137 }
138 return(spec);
139 }
140
141
142 void
143 free_xf(XF_SPEC *spec) /* free a transform */
144 {
145 if (spec->xarr != NULL)
146 free(spec->xarr);
147 free(spec);
148 }
149
150
151 int
152 xf_aname(struct xf_array *ap) /* put out name for this instance */
153 {
154 static char oname[10*XF_MAXDIM];
155 static char *oav[3] = {mg_ename[MG_E_OBJECT], oname};
156 register int i;
157 register char *cp1, *cp2;
158
159 if (ap == NULL)
160 return(mg_handle(MG_E_OBJECT, 1, oav));
161 cp1 = oname;
162 *cp1 = 'a';
163 for (i = 0; i < ap->ndim; i++) {
164 for (cp2 = ap->aarg[i].arg; *cp2; )
165 *++cp1 = *cp2++;
166 *++cp1 = '.';
167 }
168 *cp1 = '\0';
169 return(mg_handle(MG_E_OBJECT, 2, oav));
170 }
171
172
173 long
174 comp_xfid(MAT4 xfm) /* compute unique ID from matrix */
175 {
176 static char shifttab[64] = { 15, 5, 11, 5, 6, 3,
177 9, 15, 13, 2, 13, 5, 2, 12, 14, 11,
178 11, 12, 12, 3, 2, 11, 8, 12, 1, 12,
179 5, 4, 15, 9, 14, 5, 13, 14, 2, 10,
180 10, 14, 12, 3, 5, 5, 14, 6, 12, 11,
181 13, 9, 12, 8, 1, 6, 5, 12, 7, 13,
182 15, 8, 9, 2, 6, 11, 9, 11 };
183 register int i;
184 register long xid;
185
186 xid = 0; /* compute unique transform id */
187 for (i = 0; i < sizeof(MAT4)/sizeof(unsigned short); i++)
188 xid ^= (long)(((unsigned short *)xfm)[i]) << shifttab[i&63];
189 return(xid);
190 }
191
192
193 void
194 xf_clear(void) /* clear transform stack */
195 {
196 register XF_SPEC *spec;
197
198 if (xf_argbeg != NULL) {
199 free(xf_argbeg);
200 xf_argbeg = xf_argend = NULL;
201 }
202 while ((spec = xf_context) != NULL) {
203 xf_context = spec->prev;
204 free_xf(spec);
205 }
206 }
207
208
209 void
210 xf_xfmpoint(FVECT v1, FVECT v2) /* transform a point by the current matrix */
211 {
212 if (xf_context == NULL) {
213 VCOPY(v1, v2);
214 return;
215 }
216 multp3(v1, v2, xf_context->xf.xfm);
217 }
218
219
220 void
221 xf_xfmvect(FVECT v1, FVECT v2) /* transform a vector using current matrix */
222 {
223 if (xf_context == NULL) {
224 VCOPY(v1, v2);
225 return;
226 }
227 multv3(v1, v2, xf_context->xf.xfm);
228 }
229
230
231 void
232 xf_rotvect(FVECT v1, FVECT v2) /* rotate a vector using current matrix */
233 {
234 xf_xfmvect(v1, v2);
235 if (xf_context == NULL)
236 return;
237 v1[0] /= xf_context->xf.sca;
238 v1[1] /= xf_context->xf.sca;
239 v1[2] /= xf_context->xf.sca;
240 }
241
242
243 double
244 xf_scale(double d) /* scale a number by the current transform */
245 {
246 if (xf_context == NULL)
247 return(d);
248 return(d*xf_context->xf.sca);
249 }