ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/ot/oconv.c
Revision: 2.7
Committed: Sun Feb 27 10:16:42 1994 UTC (30 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +2 -1 lines
Log Message:
Added new ID to first line of header and changed use of formatval

File Contents

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