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 (20 years, 5 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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.9 static const char RCSid[] = "$Id: obj2mesh.c,v 2.8 2004/03/27 12:41:45 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * Main program to compile a Wavefront .OBJ file into a Radiance mesh
6     */
7    
8     #include "copyright.h"
9 schorsch 2.6 #include "platform.h"
10 greg 2.1 #include "standard.h"
11 schorsch 2.8 #include "resolu.h"
12 greg 2.1 #include "cvmesh.h"
13     #include "otypes.h"
14    
15 schorsch 2.8 extern int o_face(); /* XXX should go to a header file */
16 greg 2.1
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 schorsch 2.8 static void addface(CUBE *cu, OBJECT obj);
32     static void add2full(CUBE *cu, OBJECT obj);
33 greg 2.1
34 schorsch 2.8
35     int
36     main( /* compile a .OBJ file into a mesh */
37     int argc,
38     char *argv[]
39     )
40 greg 2.1 {
41 greg 2.3 int nmatf = 0;
42     char *matinp[32];
43     int i, j;
44 greg 2.1
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 greg 2.3 case 'a': /* material file */
57     matinp[nmatf++] = argv[++i];
58     break;
59 greg 2.1 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 greg 2.7
68     if (i < argc-2)
69     error(USER, "too many file arguments");
70 greg 2.1 /* initialize mesh */
71     cvinit(i==argc-2 ? argv[i+1] : "<stdout>");
72 greg 2.3 /* 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 greg 2.1 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 schorsch 2.5 SET_FILE_BINARY(stdout);
87 greg 2.1 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 greg 2.3 if (objptr(i)->otype == OBJ_FACE)
96     addface(&ourmesh->mcube, i);
97 greg 2.1
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 greg 2.4 /* printmeshstats(ourmesh, stderr); */
109 greg 2.1
110     quit(0);
111 schorsch 2.8 return 0; /* pro forma return */
112 greg 2.1 }
113    
114    
115     void
116 schorsch 2.8 quit( /* exit program */
117     int code
118     )
119 greg 2.1 {
120     exit(code);
121     }
122    
123    
124     void
125 schorsch 2.8 cputs(void) /* interactive error */
126 greg 2.1 {
127     /* referenced, but not used */
128     }
129    
130    
131     void
132 schorsch 2.8 wputs( /* warning message */
133     char *s
134     )
135 greg 2.1 {
136     if (!nowarn)
137     eputs(s);
138     }
139    
140    
141     void
142 schorsch 2.8 eputs( /* put string to stderr */
143     register char *s
144     )
145 greg 2.1 {
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 schorsch 2.8 static void
159     addface( /* add a face to a cube */
160     register CUBE *cu,
161     OBJECT obj
162     )
163 greg 2.1 {
164    
165     if (o_face(objptr(obj), cu) == O_MISS)
166     return;
167    
168     if (istree(cu->cutree)) {
169 greg 2.2 CUBE cukid; /* do children */
170     int i, j;
171 greg 2.1 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 greg 2.2 OBJECT oset[2]; /* singular set */
186 greg 2.1 oset[0] = 1; oset[1] = obj;
187     cu->cutree = fullnode(oset);
188     return;
189     }
190     /* add to full node */
191 greg 2.2 add2full(cu, obj);
192     }
193    
194    
195 schorsch 2.8 static void
196     add2full( /* add object to full node */
197     register CUBE *cu,
198     OBJECT obj
199     )
200 greg 2.2 {
201     OCTREE ot;
202     OBJECT oset[MAXSET+1];
203     CUBE cukid;
204     register int i, j;
205    
206 greg 2.1 objset(oset, cu->cutree);
207     cukid.cusize = cu->cusize * 0.5;
208    
209 greg 2.9 if (inc==O_IN || oset[0] < objlim || cukid.cusize <
210     (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
211 greg 2.1 /* add to set */
212     if (oset[0] >= MAXSET) {
213 greg 2.2 sprintf(errmsg, "set overflow in addobject (%s)",
214 greg 2.1 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     }