ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/obj2mesh.c
Revision: 2.18
Committed: Tue Jun 3 21:31:51 2025 UTC (3 days, 13 hours ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.17: +3 -4 lines
Log Message:
refactor: More consistent use of global char * progname and fixargv0()

File Contents

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