ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/wfconv.c
Revision: 2.9
Committed: Fri Apr 23 16:20:56 2004 UTC (19 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 2.8: +9 -3 lines
Log Message:
Increased .OBJ face vertex limit to 512 (was 64)

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.9 static const char RCSid[] = "$Id: wfconv.c,v 2.8 2004/03/27 12:41:45 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * Load Wavefront .OBJ file and convert to triangles with mesh info.
6     * Code borrowed largely from obj2rad.c
7     */
8    
9     #include "copyright.h"
10     #include "standard.h"
11     #include "cvmesh.h"
12     #include <ctype.h>
13    
14     typedef int VNDX[3]; /* vertex index (point,map,normal) */
15    
16     #define CHUNKSIZ 1024 /* vertex allocation chunk size */
17    
18 greg 2.9 #define MAXARG 512 /* maximum # arguments in a statement */
19 greg 2.1
20 greg 2.3 static FVECT *vlist; /* our vertex list */
21     static int nvs; /* number of vertices in our list */
22     static FVECT *vnlist; /* vertex normal list */
23     static int nvns;
24 schorsch 2.5 static RREAL (*vtlist)[2]; /* map vertex list */
25 greg 2.3 static int nvts;
26    
27     static char *inpfile; /* input file name */
28     static int havemats; /* materials available? */
29     static char material[64]; /* current material name */
30     static char group[64]; /* current group name */
31     static int lineno; /* current line number */
32     static int faceno; /* current face number */
33    
34 schorsch 2.8 static int getstmt(char *av[MAXARG], FILE *fp);
35     static int cvtndx(VNDX vi, char *vs);
36     static int putface(int ac, char **av);
37     static OBJECT getmod(void);
38     static int puttri(char *v1, char *v2, char *v3);
39     static void freeverts(void);
40     static int newv(double x, double y, double z);
41     static int newvn(double x, double y, double z);
42     static int newvt(double x, double y);
43     static void syntax(char *er);
44 greg 2.1
45    
46 greg 2.3 void
47 schorsch 2.8 wfreadobj( /* read in .OBJ file and convert */
48     char *objfn
49     )
50 greg 2.1 {
51     FILE *fp;
52     char *argv[MAXARG];
53     int argc;
54     int nstats, nunknown;
55    
56     if (objfn == NULL) {
57     inpfile = "<stdin>";
58     fp = stdin;
59     } else if ((fp = fopen(inpfile=objfn, "r")) == NULL) {
60     sprintf(errmsg, "cannot open \"%s\"", inpfile);
61     error(USER, errmsg);
62     }
63 greg 2.3 havemats = (nobjects > 0);
64 greg 2.1 nstats = nunknown = 0;
65 greg 2.3 material[0] = '\0';
66     group[0] = '\0';
67 greg 2.1 lineno = 0; faceno = 0;
68     /* scan until EOF */
69 schorsch 2.6 while ( (argc = getstmt(argv, fp)) ) {
70 greg 2.1 switch (argv[0][0]) {
71     case 'v': /* vertex */
72     switch (argv[0][1]) {
73     case '\0': /* point */
74     if (badarg(argc-1,argv+1,"fff"))
75 greg 2.2 syntax("bad vertex");
76 greg 2.1 newv(atof(argv[1]), atof(argv[2]),
77     atof(argv[3]));
78     break;
79     case 'n': /* normal */
80     if (argv[0][2])
81     goto unknown;
82     if (badarg(argc-1,argv+1,"fff"))
83 greg 2.2 syntax("bad normal");
84 greg 2.1 if (!newvn(atof(argv[1]), atof(argv[2]),
85     atof(argv[3])))
86 greg 2.2 syntax("zero normal");
87 greg 2.1 break;
88 greg 2.2 case 't': /* coordinate */
89 greg 2.1 if (argv[0][2])
90     goto unknown;
91     if (badarg(argc-1,argv+1,"ff"))
92     goto unknown;
93     newvt(atof(argv[1]), atof(argv[2]));
94     break;
95     default:
96     goto unknown;
97     }
98     break;
99     case 'f': /* face */
100     if (argv[0][1])
101     goto unknown;
102     faceno++;
103     switch (argc-1) {
104     case 0: case 1: case 2:
105 greg 2.2 syntax("too few vertices");
106 greg 2.1 break;
107     case 3:
108     if (!puttri(argv[1], argv[2], argv[3]))
109 greg 2.2 syntax("bad triangle");
110 greg 2.1 break;
111     default:
112     if (!putface(argc-1, argv+1))
113 greg 2.2 syntax("bad face");
114 greg 2.1 break;
115     }
116     break;
117 greg 2.3 case 'u': /* usemtl/usemap */
118     if (!strcmp(argv[0], "usemap"))
119     break;
120     if (strcmp(argv[0], "usemtl"))
121 greg 2.1 goto unknown;
122 greg 2.3 if (argc > 1)
123     strcpy(material, argv[1]);
124     else
125     material[0] = '\0';
126 greg 2.1 break;
127     case 'o': /* object name */
128     if (argv[0][1])
129     goto unknown;
130     break;
131 greg 2.3 case 'g': /* group name */
132 greg 2.1 if (argv[0][1])
133     goto unknown;
134 greg 2.3 if (argc > 1)
135     strcpy(group, argv[1]);
136     else
137     group[0] = '\0';
138 greg 2.1 break;
139     case '#': /* comment */
140     break;
141     default:; /* something we don't deal with */
142     unknown:
143     nunknown++;
144     break;
145     }
146     nstats++;
147     }
148     /* clean up */
149     freeverts();
150     fclose(fp);
151     if (nunknown > 0) {
152     sprintf(errmsg, "%d of %d statements unrecognized",
153     nunknown, nstats);
154     error(WARNING, errmsg);
155     }
156     }
157    
158    
159 greg 2.3 static int
160 schorsch 2.8 getstmt( /* read the next statement from fp */
161     register char *av[MAXARG],
162     FILE *fp
163     )
164 greg 2.1 {
165 greg 2.3 static char sbuf[MAXARG*16];
166 greg 2.1 register char *cp;
167     register int i;
168    
169     do {
170     if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
171     return(0);
172     i = 0;
173     for ( ; ; ) {
174     while (isspace(*cp) || *cp == '\\') {
175     if (*cp == '\n')
176     lineno++;
177     *cp++ = '\0';
178     }
179 greg 2.9 if (!*cp)
180 greg 2.1 break;
181 greg 2.9 if (i >= MAXARG-1) {
182     sprintf(errmsg,
183     "%s: too many arguments near line %d (limit %d)\n",
184     inpfile, lineno+1, MAXARG-1);
185     break;
186     }
187 greg 2.1 av[i++] = cp;
188     while (*++cp && !isspace(*cp))
189     ;
190     }
191     av[i] = NULL;
192     lineno++;
193     } while (!i);
194    
195     return(i);
196     }
197    
198    
199 greg 2.3 static int
200 schorsch 2.8 cvtndx( /* convert vertex string to index */
201     register VNDX vi,
202     register char *vs
203     )
204 greg 2.1 {
205     /* get point */
206     vi[0] = atoi(vs);
207     if (vi[0] > 0) {
208     if (vi[0]-- > nvs)
209     return(0);
210     } else if (vi[0] < 0) {
211     vi[0] += nvs;
212     if (vi[0] < 0)
213     return(0);
214     } else
215     return(0);
216     /* get map coord. */
217     while (*vs)
218     if (*vs++ == '/')
219     break;
220     vi[1] = atoi(vs);
221     if (vi[1] > 0) {
222     if (vi[1]-- > nvts)
223     return(0);
224     } else if (vi[1] < 0) {
225     vi[1] += nvts;
226     if (vi[1] < 0)
227     return(0);
228     } else
229     vi[1] = -1;
230     /* get normal */
231     while (*vs)
232     if (*vs++ == '/')
233     break;
234     vi[2] = atoi(vs);
235     if (vi[2] > 0) {
236     if (vi[2]-- > nvns)
237     return(0);
238     } else if (vi[2] < 0) {
239     vi[2] += nvns;
240     if (vi[2] < 0)
241     return(0);
242     } else
243     vi[2] = -1;
244     return(1);
245     }
246    
247    
248 greg 2.3 static int
249 schorsch 2.8 putface( /* put out an N-sided polygon */
250     int ac,
251     register char **av
252     )
253 greg 2.1 {
254     char *cp;
255     register int i;
256    
257     while (ac > 3) { /* break into triangles */
258     if (!puttri(av[0], av[1], av[2]))
259     return(0);
260     ac--; /* remove vertex & rotate */
261     cp = av[0];
262     for (i = 0; i < ac-1; i++)
263     av[i] = av[i+2];
264     av[i] = cp;
265     }
266     return(puttri(av[0], av[1], av[2]));
267     }
268    
269    
270 greg 2.3 static OBJECT
271 schorsch 2.8 getmod(void) /* get current modifier ID */
272 greg 2.3 {
273     char *mnam;
274     OBJECT mod;
275    
276     if (!havemats)
277     return(OVOID);
278     if (!strcmp(material, VOIDID))
279     return(OVOID);
280     if (material[0]) /* prefer usemtl statements */
281     mnam = material;
282     else if (group[0]) /* else use group name */
283     mnam = group;
284     else
285     return(OVOID);
286     mod = modifier(mnam);
287     if (mod == OVOID) {
288     sprintf(errmsg, "%s: undefined modifier \"%s\"",
289     inpfile, mnam);
290     error(USER, errmsg);
291     }
292     return(mod);
293     }
294    
295    
296     static int
297 schorsch 2.8 puttri( /* convert a triangle */
298     char *v1,
299     char *v2,
300     char *v3
301     )
302 greg 2.1 {
303     VNDX v1i, v2i, v3i;
304 schorsch 2.5 RREAL *v1c, *v2c, *v3c;
305     RREAL *v1n, *v2n, *v3n;
306 greg 2.2
307 greg 2.7 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) {
308     error(WARNING, "bad vertex reference");
309 greg 2.1 return(0);
310 greg 2.7 }
311 greg 2.1 if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) {
312     v1c = vtlist[v1i[1]];
313     v2c = vtlist[v2i[1]];
314     v3c = vtlist[v3i[1]];
315     } else
316     v1c = v2c = v3c = NULL;
317    
318     if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) {
319     v1n = vnlist[v1i[2]];
320     v2n = vnlist[v2i[2]];
321     v3n = vnlist[v3i[2]];
322     } else
323     v1n = v2n = v3n = NULL;
324    
325 greg 2.3 return(cvtri(getmod(), vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
326 greg 2.1 v1n, v2n, v3n, v1c, v2c, v3c) >= 0);
327     }
328    
329    
330 greg 2.3 static void
331 schorsch 2.8 freeverts(void) /* free all vertices */
332 greg 2.1 {
333     if (nvs) {
334     free((void *)vlist);
335     nvs = 0;
336     }
337     if (nvts) {
338     free((void *)vtlist);
339     nvts = 0;
340     }
341     if (nvns) {
342     free((void *)vnlist);
343     nvns = 0;
344     }
345     }
346    
347    
348 greg 2.3 static int
349 schorsch 2.8 newv( /* create a new vertex */
350     double x,
351     double y,
352     double z
353     )
354 greg 2.1 {
355     if (!(nvs%CHUNKSIZ)) { /* allocate next block */
356     if (nvs == 0)
357     vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
358     else
359 greg 2.4 vlist = (FVECT *)realloc((void *)vlist,
360 greg 2.1 (nvs+CHUNKSIZ)*sizeof(FVECT));
361 greg 2.2 if (vlist == NULL)
362     error(SYSTEM, "out of memory in newv");
363 greg 2.1 }
364     /* assign new vertex */
365     vlist[nvs][0] = x;
366     vlist[nvs][1] = y;
367     vlist[nvs][2] = z;
368     return(++nvs);
369     }
370    
371    
372 greg 2.3 static int
373 schorsch 2.8 newvn( /* create a new vertex normal */
374     double x,
375     double y,
376     double z
377     )
378 greg 2.1 {
379     if (!(nvns%CHUNKSIZ)) { /* allocate next block */
380     if (nvns == 0)
381     vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
382     else
383 greg 2.4 vnlist = (FVECT *)realloc((void *)vnlist,
384 greg 2.1 (nvns+CHUNKSIZ)*sizeof(FVECT));
385 greg 2.2 if (vnlist == NULL)
386     error(SYSTEM, "out of memory in newvn");
387 greg 2.1 }
388     /* assign new normal */
389     vnlist[nvns][0] = x;
390     vnlist[nvns][1] = y;
391     vnlist[nvns][2] = z;
392     if (normalize(vnlist[nvns]) == 0.0)
393     return(0);
394     return(++nvns);
395     }
396    
397    
398 greg 2.3 static int
399 schorsch 2.8 newvt( /* create a new texture map vertex */
400     double x,
401     double y
402     )
403 greg 2.1 {
404     if (!(nvts%CHUNKSIZ)) { /* allocate next block */
405     if (nvts == 0)
406 schorsch 2.5 vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL));
407 greg 2.1 else
408 schorsch 2.5 vtlist = (RREAL (*)[2])realloc((void *)vtlist,
409     (nvts+CHUNKSIZ)*2*sizeof(RREAL));
410 greg 2.2 if (vtlist == NULL)
411     error(SYSTEM, "out of memory in newvt");
412 greg 2.1 }
413     /* assign new vertex */
414     vtlist[nvts][0] = x;
415     vtlist[nvts][1] = y;
416     return(++nvts);
417     }
418    
419    
420 greg 2.3 static void
421 schorsch 2.8 syntax( /* report syntax error and exit */
422     char *er
423     )
424 greg 2.1 {
425 greg 2.2 sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s\n",
426 greg 2.1 inpfile, lineno, er);
427 greg 2.2 error(USER, errmsg);
428 greg 2.1 }