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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: wfconv.c,v 2.8 2004/03/27 12:41:45 schorsch Exp $";
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 512 /* maximum # arguments in a statement */
19
20 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 RREAL (*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(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
45
46 void
47 wfreadobj( /* read in .OBJ file and convert */
48 char *objfn
49 )
50 {
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 havemats = (nobjects > 0);
64 nstats = nunknown = 0;
65 material[0] = '\0';
66 group[0] = '\0';
67 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 syntax("bad vertex");
76 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 syntax("bad normal");
84 if (!newvn(atof(argv[1]), atof(argv[2]),
85 atof(argv[3])))
86 syntax("zero normal");
87 break;
88 case 't': /* coordinate */
89 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 syntax("too few vertices");
106 break;
107 case 3:
108 if (!puttri(argv[1], argv[2], argv[3]))
109 syntax("bad triangle");
110 break;
111 default:
112 if (!putface(argc-1, argv+1))
113 syntax("bad face");
114 break;
115 }
116 break;
117 case 'u': /* usemtl/usemap */
118 if (!strcmp(argv[0], "usemap"))
119 break;
120 if (strcmp(argv[0], "usemtl"))
121 goto unknown;
122 if (argc > 1)
123 strcpy(material, argv[1]);
124 else
125 material[0] = '\0';
126 break;
127 case 'o': /* object name */
128 if (argv[0][1])
129 goto unknown;
130 break;
131 case 'g': /* group name */
132 if (argv[0][1])
133 goto unknown;
134 if (argc > 1)
135 strcpy(group, argv[1]);
136 else
137 group[0] = '\0';
138 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 static int
160 getstmt( /* read the next statement from fp */
161 register char *av[MAXARG],
162 FILE *fp
163 )
164 {
165 static char sbuf[MAXARG*16];
166 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 if (!*cp)
180 break;
181 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 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 static int
200 cvtndx( /* convert vertex string to index */
201 register VNDX vi,
202 register char *vs
203 )
204 {
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 static int
249 putface( /* put out an N-sided polygon */
250 int ac,
251 register char **av
252 )
253 {
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 static OBJECT
271 getmod(void) /* get current modifier ID */
272 {
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 puttri( /* convert a triangle */
298 char *v1,
299 char *v2,
300 char *v3
301 )
302 {
303 VNDX v1i, v2i, v3i;
304 RREAL *v1c, *v2c, *v3c;
305 RREAL *v1n, *v2n, *v3n;
306
307 if (!cvtndx(v1i, v1) || !cvtndx(v2i, v2) || !cvtndx(v3i, v3)) {
308 error(WARNING, "bad vertex reference");
309 return(0);
310 }
311 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 return(cvtri(getmod(), vlist[v1i[0]], vlist[v2i[0]], vlist[v3i[0]],
326 v1n, v2n, v3n, v1c, v2c, v3c) >= 0);
327 }
328
329
330 static void
331 freeverts(void) /* free all vertices */
332 {
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 static int
349 newv( /* create a new vertex */
350 double x,
351 double y,
352 double z
353 )
354 {
355 if (!(nvs%CHUNKSIZ)) { /* allocate next block */
356 if (nvs == 0)
357 vlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
358 else
359 vlist = (FVECT *)realloc((void *)vlist,
360 (nvs+CHUNKSIZ)*sizeof(FVECT));
361 if (vlist == NULL)
362 error(SYSTEM, "out of memory in newv");
363 }
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 static int
373 newvn( /* create a new vertex normal */
374 double x,
375 double y,
376 double z
377 )
378 {
379 if (!(nvns%CHUNKSIZ)) { /* allocate next block */
380 if (nvns == 0)
381 vnlist = (FVECT *)malloc(CHUNKSIZ*sizeof(FVECT));
382 else
383 vnlist = (FVECT *)realloc((void *)vnlist,
384 (nvns+CHUNKSIZ)*sizeof(FVECT));
385 if (vnlist == NULL)
386 error(SYSTEM, "out of memory in newvn");
387 }
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 static int
399 newvt( /* create a new texture map vertex */
400 double x,
401 double y
402 )
403 {
404 if (!(nvts%CHUNKSIZ)) { /* allocate next block */
405 if (nvts == 0)
406 vtlist = (RREAL (*)[2])malloc(CHUNKSIZ*2*sizeof(RREAL));
407 else
408 vtlist = (RREAL (*)[2])realloc((void *)vtlist,
409 (nvts+CHUNKSIZ)*2*sizeof(RREAL));
410 if (vtlist == NULL)
411 error(SYSTEM, "out of memory in newvt");
412 }
413 /* assign new vertex */
414 vtlist[nvts][0] = x;
415 vtlist[nvts][1] = y;
416 return(++nvts);
417 }
418
419
420 static void
421 syntax( /* report syntax error and exit */
422 char *er
423 )
424 {
425 sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s\n",
426 inpfile, lineno, er);
427 error(USER, errmsg);
428 }