ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/obj2mesh.c
Revision: 2.17
Committed: Mon Feb 6 22:40:21 2023 UTC (20 months, 1 week ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.16: +6 -6 lines
Log Message:
refactor: Changed some char* args to const char* to avoid warnings

File Contents

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