ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/obj2mesh.c
Revision: 2.9
Committed: Thu Apr 22 17:33:48 2004 UTC (19 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +3 -2 lines
Log Message:
Made obj2mesh more robust to set overflow

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: obj2mesh.c,v 2.8 2004/03/27 12:41:45 schorsch Exp $";
3 #endif
4 /*
5 * Main program to compile a Wavefront .OBJ file into a Radiance mesh
6 */
7
8 #include "copyright.h"
9 #include "platform.h"
10 #include "standard.h"
11 #include "resolu.h"
12 #include "cvmesh.h"
13 #include "otypes.h"
14
15 extern int o_face(); /* XXX should go to a header file */
16
17 int o_default() { return(O_MISS); }
18
19 FUN ofun[NUMOTYPE] = INIT_OTYPE; /* needed for link resolution */
20
21 char *progname; /* argv[0] */
22
23 int nowarn = 0; /* supress warnings? */
24
25 int objlim = 15; /* # of objects before split */
26
27 int resolu = 16384; /* octree resolution limit */
28
29 double mincusize; /* minimum cube size from resolu */
30
31 static void addface(CUBE *cu, OBJECT obj);
32 static void add2full(CUBE *cu, OBJECT obj);
33
34
35 int
36 main( /* compile a .OBJ file into a mesh */
37 int argc,
38 char *argv[]
39 )
40 {
41 int nmatf = 0;
42 char *matinp[32];
43 int i, j;
44
45 progname = argv[0];
46 ofun[OBJ_FACE].funp = o_face;
47
48 for (i = 1; i < argc && argv[i][0] == '-'; i++)
49 switch (argv[i][1]) {
50 case 'n': /* set limit */
51 objlim = atoi(argv[++i]);
52 break;
53 case 'r': /* resolution limit */
54 resolu = atoi(argv[++i]);
55 break;
56 case 'a': /* material file */
57 matinp[nmatf++] = argv[++i];
58 break;
59 case 'w': /* supress warnings */
60 nowarn = 1;
61 break;
62 default:
63 sprintf(errmsg, "unknown option: '%s'", argv[i]);
64 error(USER, errmsg);
65 break;
66 }
67
68 if (i < argc-2)
69 error(USER, "too many file arguments");
70 /* initialize mesh */
71 cvinit(i==argc-2 ? argv[i+1] : "<stdout>");
72 /* load material input */
73 for (j = 0; j < nmatf; j++)
74 readobj(matinp[j]);
75 /* read .OBJ file into triangles */
76 if (i == argc)
77 wfreadobj(NULL);
78 else
79 wfreadobj(argv[i]);
80
81 cvmeshbounds(); /* set octree boundaries */
82
83 if (i == argc-2) /* open output file */
84 if (freopen(argv[i+1], "w", stdout) == NULL)
85 error(SYSTEM, "cannot open output file");
86 SET_FILE_BINARY(stdout);
87 newheader("RADIANCE", stdout); /* new binary file header */
88 printargs(i<argc ? i+1 : argc, argv, stdout);
89 fputformat(MESHFMT, stdout);
90 fputc('\n', stdout);
91
92 mincusize = ourmesh->mcube.cusize / resolu - FTINY;
93
94 for (i = 0; i < nobjects; i++) /* add triangles to octree */
95 if (objptr(i)->otype == OBJ_FACE)
96 addface(&ourmesh->mcube, i);
97
98 /* optimize octree */
99 ourmesh->mcube.cutree = combine(ourmesh->mcube.cutree);
100
101 if (ourmesh->mcube.cutree == EMPTY)
102 error(WARNING, "mesh is empty");
103
104 cvmesh(); /* convert mesh and leaf nodes */
105
106 writemesh(ourmesh, stdout); /* write mesh to output */
107
108 /* printmeshstats(ourmesh, stderr); */
109
110 quit(0);
111 return 0; /* pro forma return */
112 }
113
114
115 void
116 quit( /* exit program */
117 int code
118 )
119 {
120 exit(code);
121 }
122
123
124 void
125 cputs(void) /* interactive error */
126 {
127 /* referenced, but not used */
128 }
129
130
131 void
132 wputs( /* warning message */
133 char *s
134 )
135 {
136 if (!nowarn)
137 eputs(s);
138 }
139
140
141 void
142 eputs( /* put string to stderr */
143 register char *s
144 )
145 {
146 static int inln = 0;
147
148 if (!inln++) {
149 fputs(progname, stderr);
150 fputs(": ", stderr);
151 }
152 fputs(s, stderr);
153 if (*s && s[strlen(s)-1] == '\n')
154 inln = 0;
155 }
156
157
158 static void
159 addface( /* add a face to a cube */
160 register CUBE *cu,
161 OBJECT obj
162 )
163 {
164
165 if (o_face(objptr(obj), cu) == O_MISS)
166 return;
167
168 if (istree(cu->cutree)) {
169 CUBE cukid; /* do children */
170 int i, j;
171 cukid.cusize = cu->cusize * 0.5;
172 for (i = 0; i < 8; i++) {
173 cukid.cutree = octkid(cu->cutree, i);
174 for (j = 0; j < 3; j++) {
175 cukid.cuorg[j] = cu->cuorg[j];
176 if ((1<<j) & i)
177 cukid.cuorg[j] += cukid.cusize;
178 }
179 addface(&cukid, obj);
180 octkid(cu->cutree, i) = cukid.cutree;
181 }
182 return;
183 }
184 if (isempty(cu->cutree)) {
185 OBJECT oset[2]; /* singular set */
186 oset[0] = 1; oset[1] = obj;
187 cu->cutree = fullnode(oset);
188 return;
189 }
190 /* add to full node */
191 add2full(cu, obj);
192 }
193
194
195 static void
196 add2full( /* add object to full node */
197 register CUBE *cu,
198 OBJECT obj
199 )
200 {
201 OCTREE ot;
202 OBJECT oset[MAXSET+1];
203 CUBE cukid;
204 register int i, j;
205
206 objset(oset, cu->cutree);
207 cukid.cusize = cu->cusize * 0.5;
208
209 if (inc==O_IN || oset[0] < objlim || cukid.cusize <
210 (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
211 /* add to set */
212 if (oset[0] >= MAXSET) {
213 sprintf(errmsg, "set overflow in addobject (%s)",
214 objptr(obj)->oname);
215 error(INTERNAL, errmsg);
216 }
217 insertelem(oset, obj);
218 cu->cutree = fullnode(oset);
219 return;
220 }
221 /* subdivide cube */
222 if ((ot = octalloc()) == EMPTY)
223 error(SYSTEM, "out of octree space");
224 /* assign subcubes */
225 for (i = 0; i < 8; i++) {
226 cukid.cutree = EMPTY;
227 for (j = 0; j < 3; j++) {
228 cukid.cuorg[j] = cu->cuorg[j];
229 if ((1<<j) & i)
230 cukid.cuorg[j] += cukid.cusize;
231 }
232 for (j = 1; j <= oset[0]; j++)
233 addface(&cukid, oset[j]);
234 addface(&cukid, obj);
235 /* returned node */
236 octkid(ot, i) = cukid.cutree;
237 }
238 cu->cutree = ot;
239 }