ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/gen/replmarks.c
Revision: 2.16
Committed: Thu Mar 6 00:47:37 2014 UTC (10 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad4R2, rad4R2P1
Changes since 2.15: +2 -2 lines
Log Message:
Changed to calling asin() for safety

File Contents

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