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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.20 static const char RCSid[] = "$Id: oconv.c,v 2.19 2004/03/27 12:41:45 schorsch Exp $";
3 greg 1.1 #endif
4     /*
5     * oconv.c - main program for object to octree conversion.
6     *
7     * 7/29/85
8     */
9    
10 greg 2.18 #include "platform.h"
11 greg 1.1 #include "standard.h"
12     #include "octree.h"
13     #include "object.h"
14     #include "otypes.h"
15 greg 2.4 #include "paths.h"
16 schorsch 2.19 #include "resolu.h"
17     #include "oconv.h"
18 greg 1.14
19 greg 2.4 #define OMARGIN (10*FTINY) /* margin around global cube */
20 greg 1.2
21 greg 2.11 #define MAXOBJFIL 127 /* maximum number of scene files */
22 greg 1.1
23     char *progname; /* argv[0] */
24    
25     int nowarn = 0; /* supress warnings? */
26    
27 greg 2.14 int objlim = 6; /* # of objects before split */
28 greg 1.1
29 greg 2.14 int resolu = 16384; /* octree resolution limit */
30 greg 1.1
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 greg 2.4 double mincusize; /* minimum cube size from resolu */
37 greg 1.1
38 greg 2.12 void (*addobjnotify[])() = {NULL}; /* new object notifier functions */
39 greg 1.7
40 schorsch 2.19 static void addobject(CUBE *cu, OBJECT obj);
41     static void add2full(CUBE *cu, OBJECT obj, int inc);
42 greg 1.1
43 schorsch 2.19
44     int
45     main( /* convert object files to an octree */
46     int argc,
47     char *argv[]
48     )
49 greg 1.1 {
50     FVECT bbmin, bbmax;
51     char *infile = NULL;
52 greg 2.6 int inpfrozen = 0;
53 greg 1.1 int outflags = IO_ALL;
54 greg 2.4 OBJECT startobj;
55 greg 1.1 int i;
56    
57 greg 2.5 progname = argv[0] = fixargv0(argv[0]);
58 greg 1.1
59 schorsch 2.19 ot_initotypes();
60 greg 1.12
61 greg 1.5 for (i = 1; i < argc && argv[i][0] == '-'; i++)
62 greg 1.1 switch (argv[i][1]) {
63 greg 1.5 case '\0': /* scene from stdin */
64     goto breakopt;
65 greg 1.1 case 'i': /* input octree */
66     infile = argv[++i];
67     break;
68     case 'b': /* bounding cube */
69 greg 1.2 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 greg 1.1 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 greg 1.5 breakopt:
92 schorsch 2.15 SET_FILE_BINARY(stdout);
93 greg 1.1 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 greg 2.6 if (nfiles == 0)
98     inpfrozen++;
99 greg 2.8 } else
100     newheader("RADIANCE", stdout); /* new binary file header */
101 greg 2.7 printargs(argc, argv, stdout);
102 greg 1.13 fputformat(OCTFMT, stdout);
103 greg 1.1 printf("\n");
104    
105     startobj = nobjects; /* previous objects already converted */
106 greg 2.5
107 greg 1.4 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 greg 1.1 ofname[nfiles] = NULL;
118 greg 2.6
119     if (inpfrozen && outflags & IO_FILES) {
120     error(WARNING, "frozen octree");
121     outflags &= ~IO_FILES;
122     }
123 greg 1.1 /* 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 greg 1.2 bbmin[i] -= OMARGIN;
133     bbmax[i] += OMARGIN;
134 greg 1.1 }
135     for (i = 0; i < 3; i++)
136     if (bbmax[i] - bbmin[i] > thescene.cusize)
137     thescene.cusize = bbmax[i] - bbmin[i];
138 greg 1.3 for (i = 0; i < 3; i++)
139     thescene.cuorg[i] =
140     (bbmax[i]+bbmin[i]-thescene.cusize)*.5;
141 greg 1.1 }
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 greg 2.5
151 greg 1.1 for (i = startobj; i < nobjects; i++) /* add new objects */
152     addobject(&thescene, i);
153 greg 2.5
154 greg 1.1 thescene.cutree = combine(thescene.cutree); /* optimize */
155    
156     writeoct(outflags, &thescene, ofname); /* write structures to stdout */
157    
158     quit(0);
159 schorsch 2.19 return 0; /* pro forma return */
160 greg 1.1 }
161    
162    
163 greg 2.12 void
164 schorsch 2.19 quit( /* exit program */
165     int code
166     )
167 greg 1.1 {
168     exit(code);
169     }
170    
171    
172 greg 2.12 void
173 schorsch 2.19 cputs(void) /* interactive error */
174 greg 1.1 {
175     /* referenced, but not used */
176     }
177    
178    
179 greg 2.12 void
180 schorsch 2.19 wputs( /* warning message */
181     char *s
182     )
183 greg 1.1 {
184     if (!nowarn)
185     eputs(s);
186     }
187    
188    
189 greg 2.12 void
190 schorsch 2.19 eputs( /* put string to stderr */
191     register char *s
192     )
193 greg 1.1 {
194 greg 1.9 static int inln = 0;
195 greg 1.1
196 greg 1.9 if (!inln++) {
197 greg 1.1 fputs(progname, stderr);
198     fputs(": ", stderr);
199     }
200     fputs(s, stderr);
201     if (*s && s[strlen(s)-1] == '\n')
202 greg 1.9 inln = 0;
203 greg 1.1 }
204    
205 greg 2.17 /* conflicting def's in param.h */
206     #undef tstbit
207     #undef setbit
208     #undef clrbit
209     #undef tglbit
210 greg 1.1
211 greg 2.4 #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 greg 1.11
217    
218 schorsch 2.19 static void
219     addobject( /* add an object to a cube */
220     register CUBE *cu,
221     OBJECT obj
222     )
223 greg 1.1 {
224 greg 2.13 int inc;
225 greg 1.1
226 greg 2.13 inc = (*ofun[objptr(obj)->otype].funp)(objptr(obj), cu);
227 greg 1.1
228 greg 2.13 if (inc == O_MISS)
229 greg 1.1 return; /* no intersection */
230 greg 2.5
231 greg 1.1 if (istree(cu->cutree)) {
232 greg 2.13 CUBE cukid; /* do children */
233     int i, j;
234 greg 1.1 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 greg 1.11 return;
246     }
247     if (isempty(cu->cutree)) {
248 greg 2.13 OBJECT oset[2]; /* singular set */
249 greg 1.1 oset[0] = 1; oset[1] = obj;
250     cu->cutree = fullnode(oset);
251 greg 1.11 return;
252     }
253     /* add to full node */
254 greg 2.13 add2full(cu, obj, inc);
255     }
256    
257    
258 schorsch 2.19 static void
259     add2full( /* add object to full node */
260     register CUBE *cu,
261     OBJECT obj,
262     int inc
263     )
264 greg 2.13 {
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 greg 1.11 objset(oset, cu->cutree);
272     cukid.cusize = cu->cusize * 0.5;
273 greg 2.5
274 greg 2.20 if (inc==O_IN || oset[0] < objlim || cukid.cusize <
275     (oset[0] < MAXSET ? mincusize : mincusize/256.0)) {
276 greg 1.11 /* add to set */
277     if (oset[0] >= MAXSET) {
278 greg 2.3 sprintf(errmsg, "set overflow in addobject (%s)",
279 greg 1.11 objptr(obj)->oname);
280     error(INTERNAL, errmsg);
281 greg 1.1 }
282 greg 1.11 insertelem(oset, obj);
283     cu->cutree = fullnode(oset);
284     return;
285 greg 1.1 }
286 greg 1.11 /* 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 greg 2.3 (objptr(oset[j]), cu) == O_IN)
298 greg 1.11 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 greg 2.3 /* then partial volumes */
315 greg 1.11 for (j = 1; j <= oset[0]; j++)
316     if (tstbit(volflg,j-1) &&
317     !tstbit(inflg,j-1))
318     addobject(&cukid, oset[j]);
319 greg 2.3 /* full volumes last */
320 greg 1.11 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 greg 1.1 }