ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/oconv.c
Revision: 2.20
Committed: Mon Apr 12 17:31:27 2004 UTC (19 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.19: +3 -2 lines
Log Message:
Made oconv more robust to set overflow

File Contents

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