ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/wfconv.c
Revision: 2.3
Committed: Fri Mar 14 21:27:46 2003 UTC (21 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.2: +78 -20 lines
Log Message:
Added -a option to obj2mesh to incorporate materials in mesh

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #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     #define MAXARG 64 /* maximum # arguments in a statement */
19    
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     static FLOAT (*vtlist)[2]; /* map vertex list */
25     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     static int getstmt();
35     static int cvtndx();
36     static OBJECT getmod();
37     static int putface();
38     static int puttri();
39     static void freeverts();
40     static int newv();
41     static int newvn();
42     static int newvt();
43     static void syntax();
44 greg 2.1
45    
46 greg 2.3 void
47 greg 2.1 wfreadobj(objfn) /* read in .OBJ file and convert */
48     char *objfn;
49     {
50     FILE *fp;
51     char *argv[MAXARG];
52     int argc;
53     int nstats, nunknown;
54     int i;
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     while (argc = getstmt(argv, fp)) {
70     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 greg 2.1 getstmt(av, fp) /* read the next statement from fp */
161     register char *av[MAXARG];
162     FILE *fp;
163     {
164 greg 2.3 static char sbuf[MAXARG*16];
165 greg 2.1 register char *cp;
166     register int i;
167    
168     do {
169     if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
170     return(0);
171     i = 0;
172     for ( ; ; ) {
173     while (isspace(*cp) || *cp == '\\') {
174     if (*cp == '\n')
175     lineno++;
176     *cp++ = '\0';
177     }
178     if (!*cp || i >= MAXARG-1)
179     break;
180     av[i++] = cp;
181     while (*++cp && !isspace(*cp))
182     ;
183     }
184     av[i] = NULL;
185     lineno++;
186     } while (!i);
187    
188     return(i);
189     }
190    
191    
192 greg 2.3 static int
193 greg 2.1 cvtndx(vi, vs) /* convert vertex string to index */
194     register VNDX vi;
195     register char *vs;
196     {
197     /* get point */
198     vi[0] = atoi(vs);
199     if (vi[0] > 0) {
200     if (vi[0]-- > nvs)
201     return(0);
202     } else if (vi[0] < 0) {
203     vi[0] += nvs;
204     if (vi[0] < 0)
205     return(0);
206     } else
207     return(0);
208     /* get map coord. */
209     while (*vs)
210     if (*vs++ == '/')
211     break;
212     vi[1] = atoi(vs);
213     if (vi[1] > 0) {
214     if (vi[1]-- > nvts)
215     return(0);
216     } else if (vi[1] < 0) {
217     vi[1] += nvts;
218     if (vi[1] < 0)
219     return(0);
220     } else
221     vi[1] = -1;
222     /* get normal */
223     while (*vs)
224     if (*vs++ == '/')
225     break;
226     vi[2] = atoi(vs);
227     if (vi[2] > 0) {
228     if (vi[2]-- > nvns)
229     return(0);
230     } else if (vi[2] < 0) {
231     vi[2] += nvns;
232     if (vi[2] < 0)
233     return(0);
234     } else
235     vi[2] = -1;
236     return(1);
237     }
238    
239    
240 greg 2.3 static int
241 greg 2.1 putface(ac, av) /* put out an N-sided polygon */
242     int ac;
243     register char **av;
244     {
245     char *cp;
246     register int i;
247    
248     while (ac > 3) { /* break into triangles */
249     if (!puttri(av[0], av[1], av[2]))
250     return(0);
251     ac--; /* remove vertex & rotate */
252     cp = av[0];
253     for (i = 0; i < ac-1; i++)
254     av[i] = av[i+2];
255     av[i] = cp;
256     }
257     return(puttri(av[0], av[1], av[2]));
258     }
259    
260    
261 greg 2.3 static OBJECT
262     getmod() /* get current modifier ID */
263     {
264     char *mnam;
265     OBJECT mod;
266    
267     if (!havemats)
268     return(OVOID);
269     if (!strcmp(material, VOIDID))
270     return(OVOID);
271     if (material[0]) /* prefer usemtl statements */
272     mnam = material;
273     else if (group[0]) /* else use group name */
274     mnam = group;
275     else
276     return(OVOID);
277     mod = modifier(mnam);
278     if (mod == OVOID) {
279     sprintf(errmsg, "%s: undefined modifier \"%s\"",
280     inpfile, mnam);
281     error(USER, errmsg);
282     }
283     return(mod);
284     }
285    
286    
287     static int
288 greg 2.1 puttri(v1, v2, v3) /* convert a triangle */
289     char *v1, *v2, *v3;
290     {
291     VNDX v1i, v2i, v3i;
292     FLOAT *v1c, *v2c, *v3c;
293     FLOAT *v1n, *v2n, *v3n;
294 greg 2.2
295 greg 2.1 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
296     return(0);
297    
298     if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) {
299     v1c = vtlist[v1i[1]];
300     v2c = vtlist[v2i[1]];
301     v3c = vtlist[v3i[1]];
302     } else
303     v1c = v2c = v3c = NULL;
304    
305     if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) {
306     v1n = vnlist[v1i[2]];
307     v2n = vnlist[v2i[2]];
308     v3n = vnlist[v3i[2]];
309     } else
310     v1n = v2n = v3n = NULL;
311    
312 greg 2.3 return(cvtri(getmod(), vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
313 greg 2.1 v1n, v2n, v3n, v1c, v2c, v3c) >= 0);
314     }
315    
316    
317 greg 2.3 static void
318 greg 2.1 freeverts() /* free all vertices */
319     {
320     if (nvs) {
321     free((void *)vlist);
322     nvs = 0;
323     }
324     if (nvts) {
325     free((void *)vtlist);
326     nvts = 0;
327     }
328     if (nvns) {
329     free((void *)vnlist);
330     nvns = 0;
331     }
332     }
333    
334    
335 greg 2.3 static int
336 greg 2.1 newv(x, y, z) /* create a new vertex */
337     double x, y, z;
338     {
339     if (!(nvs%CHUNKSIZ)) { /* allocate next block */
340     if (nvs == 0)
341     vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
342     else
343     vlist = (FVECT *)realloc((char *)vlist,
344     (nvs+CHUNKSIZ)*sizeof(FVECT));
345 greg 2.2 if (vlist == NULL)
346     error(SYSTEM, "out of memory in newv");
347 greg 2.1 }
348     /* assign new vertex */
349     vlist[nvs][0] = x;
350     vlist[nvs][1] = y;
351     vlist[nvs][2] = z;
352     return(++nvs);
353     }
354    
355    
356 greg 2.3 static int
357 greg 2.1 newvn(x, y, z) /* create a new vertex normal */
358     double x, y, z;
359     {
360     if (!(nvns%CHUNKSIZ)) { /* allocate next block */
361     if (nvns == 0)
362     vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
363     else
364     vnlist = (FVECT *)realloc((char *)vnlist,
365     (nvns+CHUNKSIZ)*sizeof(FVECT));
366 greg 2.2 if (vnlist == NULL)
367     error(SYSTEM, "out of memory in newvn");
368 greg 2.1 }
369     /* assign new normal */
370     vnlist[nvns][0] = x;
371     vnlist[nvns][1] = y;
372     vnlist[nvns][2] = z;
373     if (normalize(vnlist[nvns]) == 0.0)
374     return(0);
375     return(++nvns);
376     }
377    
378    
379 greg 2.3 static int
380 greg 2.1 newvt(x, y) /* create a new texture map vertex */
381     double x, y;
382     {
383     if (!(nvts%CHUNKSIZ)) { /* allocate next block */
384     if (nvts == 0)
385     vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
386     else
387     vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
388     (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
389 greg 2.2 if (vtlist == NULL)
390     error(SYSTEM, "out of memory in newvt");
391 greg 2.1 }
392     /* assign new vertex */
393     vtlist[nvts][0] = x;
394     vtlist[nvts][1] = y;
395     return(++nvts);
396     }
397    
398    
399 greg 2.3 static void
400 greg 2.1 syntax(er) /* report syntax error and exit */
401     char *er;
402     {
403 greg 2.2 sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s\n",
404 greg 2.1 inpfile, lineno, er);
405 greg 2.2 error(USER, errmsg);
406 greg 2.1 }