ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/wfconv.c
Revision: 2.2
Committed: Wed Mar 12 04:59:04 2003 UTC (21 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.1: +16 -30 lines
Log Message:
Numerous bug fixes in new mesh code

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     FVECT *vlist; /* our vertex list */
15     int nvs; /* number of vertices in our list */
16     FVECT *vnlist; /* vertex normal list */
17     int nvns;
18     FLOAT (*vtlist)[2]; /* map vertex list */
19     int nvts;
20    
21     typedef int VNDX[3]; /* vertex index (point,map,normal) */
22    
23     #define CHUNKSIZ 1024 /* vertex allocation chunk size */
24    
25     #define MAXARG 64 /* maximum # arguments in a statement */
26    
27     char *inpfile; /* input file name */
28     int lineno; /* current line number */
29     int faceno; /* current face number */
30    
31    
32     wfreadobj(objfn) /* read in .OBJ file and convert */
33     char *objfn;
34     {
35     FILE *fp;
36     char *argv[MAXARG];
37     int argc;
38     int nstats, nunknown;
39     int i;
40    
41     if (objfn == NULL) {
42     inpfile = "<stdin>";
43     fp = stdin;
44     } else if ((fp = fopen(inpfile=objfn, "r")) == NULL) {
45     sprintf(errmsg, "cannot open \"%s\"", inpfile);
46     error(USER, errmsg);
47     }
48     nstats = nunknown = 0;
49     lineno = 0; faceno = 0;
50     /* scan until EOF */
51     while (argc = getstmt(argv, fp)) {
52     switch (argv[0][0]) {
53     case 'v': /* vertex */
54     switch (argv[0][1]) {
55     case '\0': /* point */
56     if (badarg(argc-1,argv+1,"fff"))
57 greg 2.2 syntax("bad vertex");
58 greg 2.1 newv(atof(argv[1]), atof(argv[2]),
59     atof(argv[3]));
60     break;
61     case 'n': /* normal */
62     if (argv[0][2])
63     goto unknown;
64     if (badarg(argc-1,argv+1,"fff"))
65 greg 2.2 syntax("bad normal");
66 greg 2.1 if (!newvn(atof(argv[1]), atof(argv[2]),
67     atof(argv[3])))
68 greg 2.2 syntax("zero normal");
69 greg 2.1 break;
70 greg 2.2 case 't': /* coordinate */
71 greg 2.1 if (argv[0][2])
72     goto unknown;
73     if (badarg(argc-1,argv+1,"ff"))
74     goto unknown;
75     newvt(atof(argv[1]), atof(argv[2]));
76     break;
77     default:
78     goto unknown;
79     }
80     break;
81     case 'f': /* face */
82     if (argv[0][1])
83     goto unknown;
84     faceno++;
85     switch (argc-1) {
86     case 0: case 1: case 2:
87 greg 2.2 syntax("too few vertices");
88 greg 2.1 break;
89     case 3:
90     if (!puttri(argv[1], argv[2], argv[3]))
91 greg 2.2 syntax("bad triangle");
92 greg 2.1 break;
93     default:
94     if (!putface(argc-1, argv+1))
95 greg 2.2 syntax("bad face");
96 greg 2.1 break;
97     }
98     break;
99     case 'u':
100     if (strcmp(argv[0], "usemtl") &&
101     strcmp(argv[0], "usemap"))
102     goto unknown;
103     break;
104     case 'o': /* object name */
105     if (argv[0][1])
106     goto unknown;
107     break;
108     case 'g': /* group name(s) */
109     if (argv[0][1])
110     goto unknown;
111     break;
112     case '#': /* comment */
113     break;
114     default:; /* something we don't deal with */
115     unknown:
116     nunknown++;
117     break;
118     }
119     nstats++;
120     }
121     /* clean up */
122     freeverts();
123     fclose(fp);
124     if (nunknown > 0) {
125     sprintf(errmsg, "%d of %d statements unrecognized",
126     nunknown, nstats);
127     error(WARNING, errmsg);
128     }
129     }
130    
131    
132     int
133     getstmt(av, fp) /* read the next statement from fp */
134     register char *av[MAXARG];
135     FILE *fp;
136     {
137     static char sbuf[MAXARG*10];
138     register char *cp;
139     register int i;
140    
141     do {
142     if (fgetline(cp=sbuf, sizeof(sbuf), fp) == NULL)
143     return(0);
144     i = 0;
145     for ( ; ; ) {
146     while (isspace(*cp) || *cp == '\\') {
147     if (*cp == '\n')
148     lineno++;
149     *cp++ = '\0';
150     }
151     if (!*cp || i >= MAXARG-1)
152     break;
153     av[i++] = cp;
154     while (*++cp && !isspace(*cp))
155     ;
156     }
157     av[i] = NULL;
158     lineno++;
159     } while (!i);
160    
161     return(i);
162     }
163    
164    
165     cvtndx(vi, vs) /* convert vertex string to index */
166     register VNDX vi;
167     register char *vs;
168     {
169     /* get point */
170     vi[0] = atoi(vs);
171     if (vi[0] > 0) {
172     if (vi[0]-- > nvs)
173     return(0);
174     } else if (vi[0] < 0) {
175     vi[0] += nvs;
176     if (vi[0] < 0)
177     return(0);
178     } else
179     return(0);
180     /* get map coord. */
181     while (*vs)
182     if (*vs++ == '/')
183     break;
184     vi[1] = atoi(vs);
185     if (vi[1] > 0) {
186     if (vi[1]-- > nvts)
187     return(0);
188     } else if (vi[1] < 0) {
189     vi[1] += nvts;
190     if (vi[1] < 0)
191     return(0);
192     } else
193     vi[1] = -1;
194     /* get normal */
195     while (*vs)
196     if (*vs++ == '/')
197     break;
198     vi[2] = atoi(vs);
199     if (vi[2] > 0) {
200     if (vi[2]-- > nvns)
201     return(0);
202     } else if (vi[2] < 0) {
203     vi[2] += nvns;
204     if (vi[2] < 0)
205     return(0);
206     } else
207     vi[2] = -1;
208     return(1);
209     }
210    
211    
212     putface(ac, av) /* put out an N-sided polygon */
213     int ac;
214     register char **av;
215     {
216     char *cp;
217     register int i;
218    
219     while (ac > 3) { /* break into triangles */
220     if (!puttri(av[0], av[1], av[2]))
221     return(0);
222     ac--; /* remove vertex & rotate */
223     cp = av[0];
224     for (i = 0; i < ac-1; i++)
225     av[i] = av[i+2];
226     av[i] = cp;
227     }
228     return(puttri(av[0], av[1], av[2]));
229     }
230    
231    
232     puttri(v1, v2, v3) /* convert a triangle */
233     char *v1, *v2, *v3;
234     {
235     VNDX v1i, v2i, v3i;
236     FLOAT *v1c, *v2c, *v3c;
237     FLOAT *v1n, *v2n, *v3n;
238 greg 2.2
239 greg 2.1 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
240     return(0);
241    
242     if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) {
243     v1c = vtlist[v1i[1]];
244     v2c = vtlist[v2i[1]];
245     v3c = vtlist[v3i[1]];
246     } else
247     v1c = v2c = v3c = NULL;
248    
249     if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) {
250     v1n = vnlist[v1i[2]];
251     v2n = vnlist[v2i[2]];
252     v3n = vnlist[v3i[2]];
253     } else
254     v1n = v2n = v3n = NULL;
255    
256     return(cvtri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
257     v1n, v2n, v3n, v1c, v2c, v3c) >= 0);
258     }
259    
260    
261     freeverts() /* free all vertices */
262     {
263     if (nvs) {
264     free((void *)vlist);
265     nvs = 0;
266     }
267     if (nvts) {
268     free((void *)vtlist);
269     nvts = 0;
270     }
271     if (nvns) {
272     free((void *)vnlist);
273     nvns = 0;
274     }
275     }
276    
277    
278     int
279     newv(x, y, z) /* create a new vertex */
280     double x, y, z;
281     {
282     if (!(nvs%CHUNKSIZ)) { /* allocate next block */
283     if (nvs == 0)
284     vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
285     else
286     vlist = (FVECT *)realloc((char *)vlist,
287     (nvs+CHUNKSIZ)*sizeof(FVECT));
288 greg 2.2 if (vlist == NULL)
289     error(SYSTEM, "out of memory in newv");
290 greg 2.1 }
291     /* assign new vertex */
292     vlist[nvs][0] = x;
293     vlist[nvs][1] = y;
294     vlist[nvs][2] = z;
295     return(++nvs);
296     }
297    
298    
299     int
300     newvn(x, y, z) /* create a new vertex normal */
301     double x, y, z;
302     {
303     if (!(nvns%CHUNKSIZ)) { /* allocate next block */
304     if (nvns == 0)
305     vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
306     else
307     vnlist = (FVECT *)realloc((char *)vnlist,
308     (nvns+CHUNKSIZ)*sizeof(FVECT));
309 greg 2.2 if (vnlist == NULL)
310     error(SYSTEM, "out of memory in newvn");
311 greg 2.1 }
312     /* assign new normal */
313     vnlist[nvns][0] = x;
314     vnlist[nvns][1] = y;
315     vnlist[nvns][2] = z;
316     if (normalize(vnlist[nvns]) == 0.0)
317     return(0);
318     return(++nvns);
319     }
320    
321    
322     int
323     newvt(x, y) /* create a new texture map vertex */
324     double x, y;
325     {
326     if (!(nvts%CHUNKSIZ)) { /* allocate next block */
327     if (nvts == 0)
328     vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
329     else
330     vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
331     (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
332 greg 2.2 if (vtlist == NULL)
333     error(SYSTEM, "out of memory in newvt");
334 greg 2.1 }
335     /* assign new vertex */
336     vtlist[nvts][0] = x;
337     vtlist[nvts][1] = y;
338     return(++nvts);
339     }
340    
341    
342     syntax(er) /* report syntax error and exit */
343     char *er;
344     {
345 greg 2.2 sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s\n",
346 greg 2.1 inpfile, lineno, er);
347 greg 2.2 error(USER, errmsg);
348 greg 2.1 }