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, 7 months 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

# 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': /* coordinate */
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 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
239 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 if (vlist == NULL)
289 error(SYSTEM, "out of memory in newv");
290 }
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 if (vnlist == NULL)
310 error(SYSTEM, "out of memory in newvn");
311 }
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 if (vtlist == NULL)
333 error(SYSTEM, "out of memory in newvt");
334 }
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 sprintf(errmsg, "%s: Wavefront syntax error near line %d: %s\n",
346 inpfile, lineno, er);
347 error(USER, errmsg);
348 }