ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/obj2mesh.c
Revision: 2.15
Committed: Fri Mar 3 01:25:27 2017 UTC (7 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad5R1, rad5R3
Changes since 2.14: +7 -2 lines
Log Message:
Added -v option to obj2mesh for reporting mesh statistics

File Contents

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