ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/replmarks.c
Revision: 2.19
Committed: Tue Apr 22 04:45:25 2025 UTC (5 weeks, 2 days ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.18: +7 -2 lines
Log Message:
fix: Added check to return value of pclose() in several tools

File Contents

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