ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/replmarks.c
Revision: 2.9
Committed: Sun Nov 16 10:29:38 2003 UTC (20 years, 4 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.8: +57 -30 lines
Log Message:
Continued ANSIfication and reduced other compile warnings.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id";
3 #endif
4 /*
5 * Replace markers in Radiance scene description with objects or instances.
6 *
7 * Created: 17 Feb 1991 Greg Ward
8 */
9
10 #include <stdlib.h>
11 #include <ctype.h>
12 #include <math.h>
13 #include <stdio.h>
14
15 #include "platform.h"
16 #include "rtio.h"
17 #include "rtprocess.h"
18 #include "fvect.h"
19
20 #ifdef M_PI
21 #define PI ((double)M_PI)
22 #else
23 #define PI 3.14159265358979323846
24 #endif
25
26 #define FEQ(a,b) ((a)-(b) <= 1e-7 && (b)-(a) <= 1e-7)
27
28 #define MAXVERT 6 /* maximum number of vertices for markers */
29 #define MAXMARK 32 /* maximum number of markers */
30
31 typedef struct {
32 short beg, end; /* beginning and ending vertex */
33 float len2; /* length squared */
34 } EDGE; /* a marker edge */
35
36 struct mrkr {
37 char *modout; /* output modifier */
38 double mscale; /* scale by this to get unit */
39 char *modin; /* input modifier indicating marker */
40 char *objname; /* output object file or octree */
41 int doxform; /* true if xform, false if instance */
42 } marker[MAXMARK]; /* array of markers */
43 int nmarkers = 0; /* number of markers */
44
45 int expand; /* expand commands? */
46
47 char *progname;
48
49 static void convert(char *name, FILE *fin);
50 static void cvcomm(char *fname, FILE *fin);
51 static void cvobject(char *fname, FILE *fin);
52 static void replace(char *fname, struct mrkr *m, char *mark, FILE *fin);
53 static int edgecmp(const void *e1, const void *e2);
54 static int buildxf(char *xf, double markscale, FILE *fin);
55 static int addrot(char *xf, FVECT xp, FVECT yp, FVECT zp);
56
57
58 int
59 main(
60 int argc,
61 char *argv[]
62 )
63 {
64 FILE *fp;
65 int i, j;
66
67 progname = argv[0];
68 i = 1;
69 while (i < argc && argv[i][0] == '-') {
70 do {
71 switch (argv[i][1]) {
72 case 'i':
73 marker[nmarkers].doxform = 0;
74 marker[nmarkers].objname = argv[++i];
75 break;
76 case 'x':
77 marker[nmarkers].doxform = 1;
78 marker[nmarkers].objname = argv[++i];
79 break;
80 case 'e':
81 expand = 1;
82 break;
83 case 'm':
84 marker[nmarkers].modout = argv[++i];
85 break;
86 case 's':
87 marker[nmarkers].mscale = atof(argv[++i]);
88 break;
89 default:
90 goto userr;
91 }
92 if (++i >= argc)
93 goto userr;
94 } while (argv[i][0] == '-');
95 if (marker[nmarkers].objname == NULL)
96 goto userr;
97 marker[nmarkers++].modin = argv[i++];
98 if (nmarkers >= MAXMARK)
99 break;
100 marker[nmarkers].mscale = marker[nmarkers-1].mscale;
101 }
102 if (nmarkers == 0)
103 goto userr;
104 /* simple header */
105 putchar('#');
106 for (j = 0; j < i; j++) {
107 putchar(' ');
108 fputs(argv[j], stdout);
109 }
110 putchar('\n');
111 if (i == argc)
112 convert("<stdin>", stdin);
113 else
114 for ( ; i < argc; i++) {
115 if ((fp = fopen(argv[i], "r")) == NULL) {
116 perror(argv[i]);
117 exit(1);
118 }
119 convert(argv[i], fp);
120 fclose(fp);
121 }
122 return 0;
123 userr:
124 fprintf(stderr,
125 "Usage: %s [-e][-s size][-m modout] {-x objfile|-i octree} modname .. [file ..]\n",
126 progname);
127 return 1;
128 }
129
130
131 void
132 convert( /* replace marks in a stream */
133 char *name,
134 register FILE *fin
135 )
136 {
137 register int c;
138
139 while ((c = getc(fin)) != EOF) {
140 if (isspace(c)) /* blank */
141 continue;
142 if (c == '#') { /* comment */
143 putchar(c);
144 do {
145 if ((c = getc(fin)) == EOF)
146 return;
147 putchar(c);
148 } while (c != '\n');
149 } else if (c == '!') { /* command */
150 ungetc(c, fin);
151 cvcomm(name, fin);
152 } else { /* object */
153 ungetc(c, fin);
154 cvobject(name, fin);
155 }
156 }
157 }
158
159
160 void
161 cvcomm( /* convert a command */
162 char *fname,
163 FILE *fin
164 )
165 {
166 FILE *pin;
167 char buf[512], *fgetline();
168
169 fgetline(buf, sizeof(buf), fin);
170 if (expand) {
171 if ((pin = popen(buf+1, "r")) == NULL) {
172 fprintf(stderr,
173 "%s: (%s): cannot execute \"%s\"\n",
174 progname, fname, buf);
175 exit(1);
176 }
177 convert(buf, pin);
178 pclose(pin);
179 } else
180 printf("\n%s\n", buf);
181 }
182
183
184 void
185 cvobject( /* convert an object */
186 char *fname,
187 FILE *fin
188 )
189 {
190 extern char *fgetword();
191 char buf[128], typ[16], nam[128];
192 int i, n;
193 register int j;
194
195 if (fscanf(fin, "%s %s %s", buf, typ, nam) != 3)
196 goto readerr;
197 if (!strcmp(typ, "polygon"))
198 for (j = 0; j < nmarkers; j++)
199 if (!strcmp(buf, marker[j].modin)) {
200 replace(fname, &marker[j], nam, fin);
201 return;
202 }
203 printf("\n%s %s %s\n", buf, typ, nam);
204 if (!strcmp(typ, "alias")) { /* alias special case */
205 if (fscanf(fin, "%s", buf) != 1)
206 goto readerr;
207 printf("\t%s\n", buf);
208 return;
209 }
210 for (i = 0; i < 3; i++) { /* pass along arguments */
211 if (fscanf(fin, "%d", &n) != 1)
212 goto readerr;
213 printf("%d", n);
214 for (j = 0; j < n; j++) {
215 if (fgetword(buf, sizeof(buf), fin) == NULL)
216 goto readerr;
217 if (j%3 == 0)
218 putchar('\n');
219 putchar('\t');
220 fputword(buf, stdout);
221 }
222 putchar('\n');
223 }
224 return;
225 readerr:
226 fprintf(stderr, "%s: (%s): read error for %s \"%s\"\n",
227 progname, fname, typ, nam);
228 }
229
230
231 void
232 replace( /* replace marker */
233 char *fname,
234 register struct mrkr *m,
235 char *mark,
236 FILE *fin
237 )
238 {
239 int n;
240 char buf[256];
241
242 buf[0] = '\0'; /* bug fix thanks to schorsch */
243 if (m->doxform) {
244 sprintf(buf, "xform -e -n %s", mark);
245 if (m->modout != NULL)
246 sprintf(buf+strlen(buf), " -m %s", m->modout);
247 if (buildxf(buf+strlen(buf), m->mscale, fin) < 0)
248 goto badxf;
249 sprintf(buf+strlen(buf), " %s", m->objname);
250 if (expand) {
251 fflush(stdout);
252 system(buf);
253 } else
254 printf("\n!%s\n", buf);
255 } else {
256 if ((n = buildxf(buf, m->mscale, fin)) < 0)
257 goto badxf;
258 printf("\n%s instance %s\n",
259 m->modout==NULL?"void":m->modout, mark);
260 printf("%d %s%s\n0\n0\n", n+1, m->objname, buf);
261 }
262 return;
263 badxf:
264 fprintf(stderr, "%s: (%s): bad arguments for marker \"%s\"\n",
265 progname, fname, mark);
266 exit(1);
267 }
268
269
270 int
271 edgecmp( /* compare two edges, descending order */
272 const void *e1,
273 const void *e2
274 )
275 {
276 if (((EDGE*)e1)->len2 > ((EDGE*)e2)->len2)
277 return(-1);
278 if (((EDGE*)e1)->len2 < ((EDGE*)e2)->len2)
279 return(1);
280 return(0);
281 }
282
283
284 int
285 buildxf( /* build transform for marker */
286 register char *xf,
287 double markscale,
288 FILE *fin
289 )
290 {
291 static FVECT vlist[MAXVERT];
292 static EDGE elist[MAXVERT];
293 FVECT xvec, yvec, zvec;
294 double xlen;
295 int n;
296 register int i;
297 /*
298 * Read and sort vectors: longest is hypotenuse,
299 * second longest is x' axis,
300 * third longest is y' axis (approximate),
301 * other vectors are ignored.
302 * It is an error if the x' and y' axes do
303 * not share a common vertex (their origin).
304 */
305 if (fscanf(fin, "%*d %*d %d", &n) != 1)
306 return(-1);
307 if (n%3 != 0)
308 return(-1);
309 n /= 3;
310 if (n < 3 || n > MAXVERT)
311 return(-1);
312 /* sort edges in descending order */
313 for (i = 0; i < n; i++) {
314 if (fscanf(fin, "%lf %lf %lf", &vlist[i][0],
315 &vlist[i][1], &vlist[i][2]) != 3)
316 return(-1);
317 if (i) {
318 elist[i].beg = i-1;
319 elist[i].end = i;
320 elist[i].len2 = dist2(vlist[i-1],vlist[i]);
321 }
322 }
323 elist[0].beg = n-1;
324 elist[0].end = 0;
325 elist[0].len2 = dist2(vlist[n-1],vlist[0]);
326 qsort(elist, n, sizeof(EDGE), edgecmp);
327 /* find x' and y' */
328 if (elist[1].end == elist[2].beg || elist[1].end == elist[2].end) {
329 i = elist[1].beg;
330 elist[1].beg = elist[1].end;
331 elist[1].end = i;
332 }
333 if (elist[2].end == elist[1].beg) {
334 i = elist[2].beg;
335 elist[2].beg = elist[2].end;
336 elist[2].end = i;
337 }
338 if (elist[1].beg != elist[2].beg)
339 return(-1); /* x' and y' not connected! */
340 for (i = 0; i < 3; i++) {
341 xvec[i] = vlist[elist[1].end][i] - vlist[elist[1].beg][i];
342 yvec[i] = vlist[elist[2].end][i] - vlist[elist[2].beg][i];
343 }
344 if ((xlen = normalize(xvec)) == 0.0)
345 return(-1);
346 fcross(zvec, xvec, yvec);
347 if (normalize(zvec) == 0.0)
348 return(-1);
349 fcross(yvec, zvec, xvec);
350 n = 0; /* start transformation... */
351 if (markscale > 0.0) { /* add scale factor */
352 sprintf(xf, " -s %f", xlen*markscale);
353 n += 2;
354 while (*xf) ++xf;
355 }
356 /* add rotation */
357 n += addrot(xf, xvec, yvec, zvec);
358 while (*xf) ++xf;
359 /* add translation */
360 n += 4;
361 sprintf(xf, " -t %f %f %f", vlist[elist[1].beg][0],
362 vlist[elist[1].beg][1], vlist[elist[1].beg][2]);
363 return(n); /* all done */
364 }
365
366
367 int
368 addrot( /* compute rotation (x,y,z) => (xp,yp,zp) */
369 register char *xf,
370 FVECT xp,
371 FVECT yp,
372 FVECT zp
373 )
374 {
375 int n;
376 double theta;
377
378 n = 0;
379 theta = atan2(yp[2], zp[2]);
380 if (!FEQ(theta,0.0)) {
381 sprintf(xf, " -rx %f", theta*(180./PI));
382 while (*xf) ++xf;
383 n += 2;
384 }
385 theta = asin(-xp[2]);
386 if (!FEQ(theta,0.0)) {
387 sprintf(xf, " -ry %f", theta*(180./PI));
388 while (*xf) ++xf;
389 n += 2;
390 }
391 theta = atan2(xp[1], xp[0]);
392 if (!FEQ(theta,0.0)) {
393 sprintf(xf, " -rz %f", theta*(180./PI));
394 /* while (*xf) ++xf; */
395 n += 2;
396 }
397 return(n);
398 }