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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: obj2mesh.c,v 2.14 2016/03/22 03:56:17 greg 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 "paths.h"
10 #include "platform.h"
11 #include "standard.h"
12 #include "resolu.h"
13 #include "cvmesh.h"
14 #include "otypes.h"
15
16 extern int o_face(); /* XXX should go to a header file */
17
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 int objlim = 9; /* # of objects before split */
27
28 int resolu = 16384; /* octree resolution limit */
29
30 double mincusize; /* minimum cube size from resolu */
31
32 static void addface(CUBE *cu, OBJECT obj);
33 static void add2full(CUBE *cu, OBJECT obj);
34
35
36 int
37 main( /* compile a .OBJ file into a mesh */
38 int argc,
39 char *argv[]
40 )
41 {
42 int nmatf = 0;
43 int verbose = 0;
44 char pathnames[12800];
45 char *pns = pathnames;
46 char *matinp[128];
47 char *cp;
48 int i, j;
49
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 case 'a': /* material file */
62 matinp[nmatf++] = argv[++i];
63 break;
64 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 error(SYSTEM, errmsg);
71 }
72 matinp[nmatf++] = strcpy(pns, cp);
73 while (*pns++)
74 ;
75 break;
76 case 'w': /* supress warnings */
77 nowarn = 1;
78 break;
79 case 'v': /* print mesh stats */
80 verbose = 1;
81 break;
82 default:
83 sprintf(errmsg, "unknown option: '%s'", argv[i]);
84 error(USER, errmsg);
85 break;
86 }
87
88 if (i < argc-2)
89 error(USER, "too many file arguments");
90 /* initialize mesh */
91 cvinit(i==argc-2 ? argv[i+1] : "<stdout>");
92 /* 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 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 SET_FILE_BINARY(stdout);
107 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 if (objptr(i)->otype == OBJ_FACE)
116 addface(&ourmesh->mcube, i);
117
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 if (verbose)
129 printmeshstats(ourmesh, stderr);
130
131 quit(0);
132 return 0; /* pro forma return */
133 }
134
135
136 void
137 quit( /* exit program */
138 int code
139 )
140 {
141 exit(code);
142 }
143
144
145 void
146 cputs(void) /* interactive error */
147 {
148 /* referenced, but not used */
149 }
150
151
152 void
153 wputs( /* warning message */
154 char *s
155 )
156 {
157 if (!nowarn)
158 eputs(s);
159 }
160
161
162 void
163 eputs( /* put string to stderr */
164 register char *s
165 )
166 {
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 static void
180 addface( /* add a face to a cube */
181 register CUBE *cu,
182 OBJECT obj
183 )
184 {
185
186 if (o_face(objptr(obj), cu) == O_MISS)
187 return;
188
189 if (istree(cu->cutree)) {
190 CUBE cukid; /* do children */
191 int i, j;
192 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 OBJECT oset[2]; /* singular set */
207 oset[0] = 1; oset[1] = obj;
208 cu->cutree = fullnode(oset);
209 return;
210 }
211 /* add to full node */
212 add2full(cu, obj);
213 }
214
215
216 static void
217 add2full( /* add object to full node */
218 register CUBE *cu,
219 OBJECT obj
220 )
221 {
222 OCTREE ot;
223 OBJECT oset[MAXSET+1];
224 CUBE cukid;
225 register int i, j;
226
227 objset(oset, cu->cutree);
228 cukid.cusize = cu->cusize * 0.5;
229
230 if (oset[0] < objlim || cukid.cusize <
231 (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
232 /* add to set */
233 if (oset[0] >= MAXSET) {
234 sprintf(errmsg, "set overflow in addobject (%s)",
235 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 }