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

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: oconv.c,v 2.23 2023/02/06 22:40:21 greg Exp $";
3 #endif
4 /*
5 * oconv.c - main program for object to octree conversion.
6 *
7 * 7/29/85
8 */
9
10 #include "platform.h"
11 #include "standard.h"
12 #include "octree.h"
13 #include "object.h"
14 #include "otypes.h"
15 #include "paths.h"
16 #include "resolu.h"
17 #include "oconv.h"
18
19 #define OMARGIN (10*FTINY) /* margin around global cube */
20
21 #define MAXOBJFIL 255 /* maximum number of scene files */
22
23 int nowarn = 0; /* supress warnings? */
24
25 int objlim = 6; /* # of objects before split */
26
27 int resolu = 16384; /* octree resolution limit */
28
29 CUBE thescene = {{0.0, 0.0, 0.0}, 0.0, EMPTY}; /* our scene */
30
31 char *ofname[MAXOBJFIL+1]; /* object file names */
32 int nfiles = 0; /* number of object files */
33
34 double mincusize; /* minimum cube size from resolu */
35
36 void (*addobjnotify[])() = {NULL}; /* new object notifier functions */
37
38 static void addobject(CUBE *cu, OBJECT obj);
39 static void add2full(CUBE *cu, OBJECT obj, int inc);
40
41
42 int
43 main( /* convert object files to an octree */
44 int argc,
45 char *argv[]
46 )
47 {
48 FVECT bbmin, bbmax;
49 char *infile = NULL;
50 int inpfrozen = 0;
51 int outflags = IO_ALL;
52 OBJECT startobj;
53 int i;
54
55 fixargv0(argv[0]); /* sets global progname */
56
57 ot_initotypes();
58
59 for (i = 1; i < argc && argv[i][0] == '-'; i++)
60 switch (argv[i][1]) {
61 case '\0': /* scene from stdin */
62 goto breakopt;
63 case 'i': /* input octree */
64 infile = argv[++i];
65 break;
66 case 'b': /* bounding cube */
67 thescene.cuorg[0] = atof(argv[++i]) - OMARGIN;
68 thescene.cuorg[1] = atof(argv[++i]) - OMARGIN;
69 thescene.cuorg[2] = atof(argv[++i]) - OMARGIN;
70 thescene.cusize = atof(argv[++i]) + 2*OMARGIN;
71 break;
72 case 'n': /* set limit */
73 objlim = atoi(argv[++i]);
74 break;
75 case 'r': /* resolution limit */
76 resolu = atoi(argv[++i]);
77 break;
78 case 'f': /* freeze octree */
79 outflags &= ~IO_FILES;
80 break;
81 case 'w': /* supress warnings */
82 nowarn = 1;
83 break;
84 default:
85 sprintf(errmsg, "unknown option: '%s'", argv[i]);
86 error(USER, errmsg);
87 break;
88 }
89 breakopt:
90 SET_FILE_BINARY(stdout);
91 if (infile != NULL) { /* get old octree & objects */
92 if (thescene.cusize > FTINY)
93 error(USER, "only one of '-b' or '-i'");
94 nfiles = readoct(infile, IO_ALL, &thescene, ofname);
95 if (nfiles == 0)
96 inpfrozen++;
97 } else
98 newheader("RADIANCE", stdout); /* new binary file header */
99 printargs(argc, argv, stdout);
100 fputformat(OCTFMT, stdout);
101 printf("\n");
102
103 startobj = nobjects; /* previous objects already converted */
104
105 for ( ; i < argc; i++) /* read new scene descriptions */
106 if (!strcmp(argv[i], "-")) { /* from stdin */
107 readobj(NULL);
108 outflags &= ~IO_FILES;
109 } else { /* from file */
110 if (nfiles >= MAXOBJFIL)
111 error(INTERNAL, "too many scene files");
112 readobj(ofname[nfiles++] = argv[i]);
113 }
114
115 ofname[nfiles] = NULL;
116
117 if (inpfrozen && outflags & IO_FILES) {
118 error(WARNING, "frozen octree");
119 outflags &= ~IO_FILES;
120 }
121 /* find bounding box */
122 bbmin[0] = bbmin[1] = bbmin[2] = FHUGE;
123 bbmax[0] = bbmax[1] = bbmax[2] = -FHUGE;
124 for (i = startobj; i < nobjects; i++)
125 add2bbox(objptr(i), bbmin, bbmax);
126 /* set/check cube */
127 if (thescene.cusize == 0.0) {
128 if (bbmin[0] <= bbmax[0]) {
129 for (i = 0; i < 3; i++) {
130 bbmin[i] -= OMARGIN;
131 bbmax[i] += OMARGIN;
132 }
133 for (i = 0; i < 3; i++)
134 if (bbmax[i] - bbmin[i] > thescene.cusize)
135 thescene.cusize = bbmax[i] - bbmin[i];
136 for (i = 0; i < 3; i++)
137 thescene.cuorg[i] =
138 (bbmax[i]+bbmin[i]-thescene.cusize)*.5;
139 }
140 } else {
141 for (i = 0; i < 3; i++)
142 if (bbmin[i] < thescene.cuorg[i] ||
143 bbmax[i] > thescene.cuorg[i] + thescene.cusize)
144 error(USER, "boundary does not encompass scene");
145 }
146
147 mincusize = thescene.cusize / resolu - FTINY;
148
149 for (i = startobj; i < nobjects; i++) /* add new objects */
150 addobject(&thescene, i);
151
152 thescene.cutree = combine(thescene.cutree); /* optimize */
153
154 writeoct(outflags, &thescene, ofname); /* write structures to stdout */
155
156 quit(0);
157 return 0; /* pro forma return */
158 }
159
160
161 void
162 quit( /* exit program */
163 int code
164 )
165 {
166 exit(code);
167 }
168
169
170 void
171 cputs(void) /* interactive error */
172 {
173 /* referenced, but not used */
174 }
175
176
177 void
178 wputs( /* warning message */
179 const char *s
180 )
181 {
182 if (!nowarn)
183 eputs(s);
184 }
185
186
187 void
188 eputs( /* put string to stderr */
189 const char *s
190 )
191 {
192 static int inln = 0;
193
194 if (!inln++) {
195 fputs(progname, stderr);
196 fputs(": ", stderr);
197 }
198 fputs(s, stderr);
199 if (*s && s[strlen(s)-1] == '\n')
200 inln = 0;
201 }
202
203 /* conflicting def's in param.h */
204 #undef tstbit
205 #undef setbit
206 #undef clrbit
207 #undef tglbit
208
209 #define bitop(f,i,op) (f[((i)>>3)] op (1<<((i)&7)))
210 #define tstbit(f,i) bitop(f,i,&)
211 #define setbit(f,i) bitop(f,i,|=)
212 #define clrbit(f,i) bitop(f,i,&=~)
213 #define tglbit(f,i) bitop(f,i,^=)
214
215
216 static void
217 addobject( /* add an object to a cube */
218 CUBE *cu,
219 OBJECT obj
220 )
221 {
222 int inc;
223
224 inc = (*ofun[objptr(obj)->otype].funp)(objptr(obj), cu);
225
226 if (inc == O_MISS)
227 return; /* no intersection */
228
229 if (istree(cu->cutree)) {
230 CUBE cukid; /* do children */
231 int i, j;
232 cukid.cusize = cu->cusize * 0.5;
233 for (i = 0; i < 8; i++) {
234 cukid.cutree = octkid(cu->cutree, i);
235 for (j = 0; j < 3; j++) {
236 cukid.cuorg[j] = cu->cuorg[j];
237 if ((1<<j) & i)
238 cukid.cuorg[j] += cukid.cusize;
239 }
240 addobject(&cukid, obj);
241 octkid(cu->cutree, i) = cukid.cutree;
242 }
243 return;
244 }
245 if (isempty(cu->cutree)) {
246 OBJECT oset[2]; /* singular set */
247 oset[0] = 1; oset[1] = obj;
248 cu->cutree = fullnode(oset);
249 return;
250 }
251 /* add to full node */
252 add2full(cu, obj, inc);
253 }
254
255
256 static void
257 add2full( /* add object to full node */
258 CUBE *cu,
259 OBJECT obj,
260 int inc
261 )
262 {
263 OCTREE ot;
264 OBJECT oset[MAXSET+1];
265 CUBE cukid;
266 unsigned char inflg[(MAXSET+7)/8], volflg[(MAXSET+7)/8];
267 int i, j;
268
269 objset(oset, cu->cutree);
270 cukid.cusize = cu->cusize * 0.5;
271
272 if (inc==O_IN || oset[0] < objlim || cukid.cusize <
273 (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
274 /* add to set */
275 if (oset[0] >= MAXSET) {
276 sprintf(errmsg, "set overflow in addobject (%s)",
277 objptr(obj)->oname);
278 error(INTERNAL, errmsg);
279 }
280 insertelem(oset, obj);
281 cu->cutree = fullnode(oset);
282 return;
283 }
284 /* subdivide cube */
285 if ((ot = octalloc()) == EMPTY)
286 error(SYSTEM, "out of octree space");
287 /* mark volumes */
288 j = (oset[0]+7)>>3;
289 while (j--)
290 volflg[j] = inflg[j] = 0;
291 for (j = 1; j <= oset[0]; j++)
292 if (isvolume(objptr(oset[j])->otype)) {
293 setbit(volflg,j-1);
294 if ((*ofun[objptr(oset[j])->otype].funp)
295 (objptr(oset[j]), cu) == O_IN)
296 setbit(inflg,j-1);
297 }
298 /* assign subcubes */
299 for (i = 0; i < 8; i++) {
300 cukid.cutree = EMPTY;
301 for (j = 0; j < 3; j++) {
302 cukid.cuorg[j] = cu->cuorg[j];
303 if ((1<<j) & i)
304 cukid.cuorg[j] += cukid.cusize;
305 }
306 /* surfaces first */
307 for (j = 1; j <= oset[0]; j++)
308 if (!tstbit(volflg,j-1))
309 addobject(&cukid, oset[j]);
310 /* then this object */
311 addobject(&cukid, obj);
312 /* then partial volumes */
313 for (j = 1; j <= oset[0]; j++)
314 if (tstbit(volflg,j-1) &&
315 !tstbit(inflg,j-1))
316 addobject(&cukid, oset[j]);
317 /* full volumes last */
318 for (j = 1; j <= oset[0]; j++)
319 if (tstbit(inflg,j-1))
320 addobject(&cukid, oset[j]);
321 /* returned node */
322 octkid(ot, i) = cukid.cutree;
323 }
324 cu->cutree = ot;
325 }