ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/wfconv.c
Revision: 2.1
Committed: Tue Mar 11 17:08:55 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
First working version of new "mesh" primitive, obj2mesh converter

File Contents

# Content
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 syntax("Bad vertex");
58 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 syntax("Bad normal");
66 if (!newvn(atof(argv[1]), atof(argv[2]),
67 atof(argv[3])))
68 syntax("Zero normal");
69 break;
70 case 't': /* texture map */
71 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 syntax("Too few vertices");
88 break;
89 case 3:
90 if (!puttri(argv[1], argv[2], argv[3]))
91 syntax("Bad triangle");
92 break;
93 default:
94 if (!putface(argc-1, argv+1))
95 syntax("Bad face");
96 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 VNDX vi;
217 char *cp;
218 register int i;
219
220 while (ac > 3) { /* break into triangles */
221 if (!puttri(av[0], av[1], av[2]))
222 {
223 fprintf(stderr, "f %s %s %s\n", av[0], av[1], av[2]);
224 return(0);
225 }
226 ac--; /* remove vertex & rotate */
227 cp = av[0];
228 for (i = 0; i < ac-1; i++)
229 av[i] = av[i+2];
230 av[i] = cp;
231 }
232 return(puttri(av[0], av[1], av[2]));
233 }
234
235
236 puttri(v1, v2, v3) /* convert a triangle */
237 char *v1, *v2, *v3;
238 {
239 VNDX v1i, v2i, v3i;
240 FLOAT *v1c, *v2c, *v3c;
241 FLOAT *v1n, *v2n, *v3n;
242
243 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3))
244 return(0);
245
246 if (v1i[1]>=0 && v2i[1]>=0 && v3i[1]>=0) {
247 v1c = vtlist[v1i[1]];
248 v2c = vtlist[v2i[1]];
249 v3c = vtlist[v3i[1]];
250 } else
251 v1c = v2c = v3c = NULL;
252
253 if (v1i[2]>=0 && v2i[2]>=0 && v3i[2]>=0) {
254 v1n = vnlist[v1i[2]];
255 v2n = vnlist[v2i[2]];
256 v3n = vnlist[v3i[2]];
257 } else
258 v1n = v2n = v3n = NULL;
259
260 return(cvtri(vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
261 v1n, v2n, v3n, v1c, v2c, v3c) >= 0);
262 }
263
264
265 freeverts() /* free all vertices */
266 {
267 if (nvs) {
268 free((void *)vlist);
269 nvs = 0;
270 }
271 if (nvts) {
272 free((void *)vtlist);
273 nvts = 0;
274 }
275 if (nvns) {
276 free((void *)vnlist);
277 nvns = 0;
278 }
279 }
280
281
282 int
283 newv(x, y, z) /* create a new vertex */
284 double x, y, z;
285 {
286 if (!(nvs%CHUNKSIZ)) { /* allocate next block */
287 if (nvs == 0)
288 vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
289 else
290 vlist = (FVECT *)realloc((char *)vlist,
291 (nvs+CHUNKSIZ)*sizeof(FVECT));
292 if (vlist == NULL) {
293 fprintf(stderr,
294 "Out of memory while allocating vertex %d\n", nvs);
295 exit(1);
296 }
297 }
298 /* assign new vertex */
299 vlist[nvs][0] = x;
300 vlist[nvs][1] = y;
301 vlist[nvs][2] = z;
302 return(++nvs);
303 }
304
305
306 int
307 newvn(x, y, z) /* create a new vertex normal */
308 double x, y, z;
309 {
310 if (!(nvns%CHUNKSIZ)) { /* allocate next block */
311 if (nvns == 0)
312 vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
313 else
314 vnlist = (FVECT *)realloc((char *)vnlist,
315 (nvns+CHUNKSIZ)*sizeof(FVECT));
316 if (vnlist == NULL) {
317 fprintf(stderr,
318 "Out of memory while allocating normal %d\n", nvns);
319 exit(1);
320 }
321 }
322 /* assign new normal */
323 vnlist[nvns][0] = x;
324 vnlist[nvns][1] = y;
325 vnlist[nvns][2] = z;
326 if (normalize(vnlist[nvns]) == 0.0)
327 return(0);
328 return(++nvns);
329 }
330
331
332 int
333 newvt(x, y) /* create a new texture map vertex */
334 double x, y;
335 {
336 if (!(nvts%CHUNKSIZ)) { /* allocate next block */
337 if (nvts == 0)
338 vtlist = (FLOAT (*)[2])malloc(CHUNKSIZ*2*sizeof(FLOAT));
339 else
340 vtlist = (FLOAT (*)[2])realloc((char *)vtlist,
341 (nvts+CHUNKSIZ)*2*sizeof(FLOAT));
342 if (vtlist == NULL) {
343 fprintf(stderr,
344 "Out of memory while allocating texture vertex %d\n",
345 nvts);
346 exit(1);
347 }
348 }
349 /* assign new vertex */
350 vtlist[nvts][0] = x;
351 vtlist[nvts][1] = y;
352 return(++nvts);
353 }
354
355
356 syntax(er) /* report syntax error and exit */
357 char *er;
358 {
359 fprintf(stderr, "%s: Wavefront syntax error near line %d: %s\n",
360 inpfile, lineno, er);
361 exit(1);
362 }