ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/readoct.c
Revision: 2.25
Committed: Thu Apr 29 14:36:49 2004 UTC (20 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.24: +5 -1 lines
Log Message:
Added macros to avoid flockfile(3) overhead

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: readoct.c,v 2.24 2003/10/27 10:19:31 schorsch Exp $";
3 #endif
4 /*
5 * readoct.c - routines to read octree information.
6 */
7
8 #include "copyright.h"
9
10 #include <stdio.h>
11 #include <time.h>
12
13 #include "platform.h"
14 #include "rtprocess.h"
15 #include "standard.h"
16 #include "octree.h"
17 #include "object.h"
18 #include "otypes.h"
19 #include "resolu.h"
20
21 #ifdef getc_unlocked /* avoid horrendous overhead of flockfile */
22 #define getc getc_unlocked
23 #endif
24
25 static double ogetflt(void);
26 static long ogetint(int);
27 static char *ogetstr(char *);
28 static int nonsurfinset(OBJECT *);
29 static void octerror(int etyp, char *msg);
30 static void skiptree(void);
31 static OCTREE getfullnode(void), gettree(void);
32
33 static char *infn; /* input file specification */
34 static FILE *infp; /* input file stream */
35 static int objsize; /* size of stored OBJECT's */
36 static OBJECT objorig; /* zeroeth object */
37 static OBJECT fnobjects; /* number of objects in this file */
38
39
40 int
41 readoct(inpspec, load, scene, ofn) /* read in octree file or stream */
42 char *inpspec;
43 int load;
44 CUBE *scene;
45 char *ofn[];
46 {
47 char sbuf[512];
48 int nf;
49 int i;
50 long m;
51
52 if (inpspec == NULL) {
53 infn = "standard input";
54 infp = stdin;
55 } else if (inpspec[0] == '!') {
56 infn = inpspec;
57 if ((infp = popen(inpspec+1, "r")) == NULL) {
58 sprintf(errmsg, "cannot execute \"%s\"", inpspec);
59 error(SYSTEM, errmsg);
60 }
61 } else {
62 infn = inpspec;
63 if ((infp = fopen(inpspec, "r")) == NULL) {
64 sprintf(errmsg, "cannot open octree file \"%s\"",
65 inpspec);
66 error(SYSTEM, errmsg);
67 }
68 }
69 SET_FILE_BINARY(infp);
70 /* get header */
71 if (checkheader(infp, OCTFMT, load&IO_INFO ? stdout : (FILE *)NULL) < 0)
72 octerror(USER, "not an octree");
73 /* check format */
74 if ((objsize = ogetint(2)-OCTMAGIC) <= 0 ||
75 objsize > MAXOBJSIZ || objsize > sizeof(long))
76 octerror(USER, "incompatible octree format");
77 /* get boundaries */
78 if (load & IO_BOUNDS) {
79 for (i = 0; i < 3; i++)
80 scene->cuorg[i] = atof(ogetstr(sbuf));
81 scene->cusize = atof(ogetstr(sbuf));
82 } else {
83 for (i = 0; i < 4; i++)
84 ogetstr(sbuf);
85 }
86 objorig = nobjects; /* set object offset */
87 nf = 0; /* get object files */
88 while (*ogetstr(sbuf)) {
89 if (load & IO_SCENE)
90 readobj(sbuf);
91 if (load & IO_FILES)
92 ofn[nf] = savqstr(sbuf);
93 nf++;
94 }
95 if (load & IO_FILES)
96 ofn[nf] = NULL;
97 /* get number of objects */
98 fnobjects = m = ogetint(objsize);
99 if (fnobjects != m)
100 octerror(USER, "too many objects");
101
102 if (load & IO_TREE) /* get the octree */
103 scene->cutree = gettree();
104 else if (load & IO_SCENE && nf == 0)
105 skiptree();
106
107 if (load & IO_SCENE) { /* get the scene */
108 if (nf == 0) {
109 /* load binary scene data */
110 readscene(infp, objsize);
111
112 } else { /* consistency checks */
113 /* check object count */
114 if (nobjects != objorig+fnobjects)
115 octerror(USER, "bad object count; octree stale?");
116 /* check for non-surfaces */
117 if (dosets(nonsurfinset))
118 octerror(USER, "modifier in tree; octree stale?");
119 }
120 }
121 /* close the input */
122 if (infn[0] == '!')
123 pclose(infp);
124 else
125 fclose(infp);
126 return(nf);
127 }
128
129
130 static char *
131 ogetstr(s) /* get null-terminated string */
132 char *s;
133 {
134 extern char *getstr();
135
136 if (getstr(s, infp) == NULL)
137 octerror(USER, "truncated octree");
138 return(s);
139 }
140
141
142 static OCTREE
143 getfullnode() /* get a set, return fullnode */
144 {
145 OBJECT set[MAXSET+1];
146 register int i;
147 register long m;
148
149 if ((set[0] = ogetint(objsize)) > MAXSET)
150 octerror(USER, "bad set in getfullnode");
151 for (i = 1; i <= set[0]; i++) {
152 m = ogetint(objsize) + objorig;
153 if ((set[i] = m) != m)
154 octerror(USER, "too many objects");
155 }
156 return(fullnode(set));
157 }
158
159
160 static long
161 ogetint(siz) /* get a siz-byte integer */
162 int siz;
163 {
164 extern long getint();
165 register long r;
166
167 r = getint(siz, infp);
168 if (feof(infp))
169 octerror(USER, "truncated octree");
170 return(r);
171 }
172
173
174 static double
175 ogetflt() /* get a floating point number */
176 {
177 extern double getflt();
178 double r;
179
180 r = getflt(infp);
181 if (feof(infp))
182 octerror(USER, "truncated octree");
183 return(r);
184 }
185
186
187 static OCTREE
188 gettree() /* get a pre-ordered octree */
189 {
190 register OCTREE ot;
191 register int i;
192
193 switch (getc(infp)) {
194 case OT_EMPTY:
195 return(EMPTY);
196 case OT_FULL:
197 return(getfullnode());
198 case OT_TREE:
199 if ((ot = octalloc()) == EMPTY)
200 octerror(SYSTEM, "out of tree space in gettree");
201 for (i = 0; i < 8; i++)
202 octkid(ot, i) = gettree();
203 return(ot);
204 case EOF:
205 octerror(USER, "truncated octree");
206 default:
207 octerror(USER, "damaged octree");
208 }
209 return EMPTY; /* pro forma return */
210 }
211
212
213 static int
214 nonsurfinset(os) /* check set for modifier */
215 register OBJECT *os;
216 {
217 register OBJECT s;
218 register int i;
219
220 for (i = *os; i-- > 0; )
221 if ((s = *++os) >= objorig && s < objorig+fnobjects &&
222 ismodifier(objptr(s)->otype))
223 return(1);
224 return(0);
225 }
226
227
228 static void
229 skiptree(void) /* skip octree on input */
230 {
231 register int i;
232
233 switch (getc(infp)) {
234 case OT_EMPTY:
235 return;
236 case OT_FULL:
237 for (i = ogetint(objsize)*objsize; i-- > 0; )
238 if (getc(infp) == EOF)
239 octerror(USER, "truncated octree");
240 return;
241 case OT_TREE:
242 for (i = 0; i < 8; i++)
243 skiptree();
244 return;
245 case EOF:
246 octerror(USER, "truncated octree");
247 default:
248 octerror(USER, "damaged octree");
249 }
250 }
251
252
253 static void
254 octerror(etyp, msg) /* octree error */
255 int etyp;
256 char *msg;
257 {
258 char msgbuf[128];
259
260 sprintf(msgbuf, "(%s): %s", infn, msg);
261 error(etyp, msgbuf);
262 }