ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/readoct.c
Revision: 2.32
Committed: Tue Feb 7 20:28:16 2023 UTC (15 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.31: +8 -1 lines
Log Message:
perf: added calls to flockfile()/funlockfile() for more efficient reading

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: readoct.c,v 2.31 2019/05/04 00:32:47 greg 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 "paths.h"
15 #include "standard.h"
16 #include "octree.h"
17 #include "object.h"
18 #include "otypes.h"
19 #include "resolu.h"
20
21 static double ogetflt(void);
22 static long ogetint(int);
23 static char *ogetstr(char *);
24 static int nonsurfintree(OCTREE ot);
25 static void octerror(int etyp, char *msg);
26 static void skiptree(void);
27 static OCTREE getfullnode(void), gettree(void);
28
29 static char *infn; /* input file specification */
30 static FILE *infp; /* input file stream */
31 static int objsize; /* size of stored OBJECT's */
32 static OBJECT objorig; /* zeroeth object */
33 static OBJECT fnobjects; /* number of objects in this file */
34
35
36 int
37 readoct( /* read in octree file or stream */
38 char *inpspec,
39 int load,
40 CUBE *scene,
41 char *ofn[]
42 )
43 {
44 char sbuf[512];
45 int nf;
46 int i;
47 long m;
48
49 if (inpspec == NULL) {
50 infn = "standard input";
51 infp = stdin;
52 } else if (inpspec[0] == '!') {
53 infn = inpspec;
54 if ((infp = popen(inpspec+1, "r")) == NULL) {
55 sprintf(errmsg, "cannot execute \"%s\"", inpspec);
56 error(SYSTEM, errmsg);
57 }
58 } else {
59 infn = inpspec;
60 if ((infp = fopen(inpspec, "r")) == NULL) {
61 sprintf(errmsg, "cannot open octree file \"%s\"",
62 inpspec);
63 error(SYSTEM, errmsg);
64 }
65 }
66 #ifdef getc_unlocked /* avoid stupid semaphores */
67 flockfile(infp);
68 #endif
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 (nonsurfintree(scene->cutree))
118 octerror(USER, "modifier in tree; octree stale?");
119 }
120 }
121 /* close the input */
122 if (infn[0] == '!')
123 pclose(infp);
124 else if (infp != stdin)
125 fclose(infp);
126 #ifdef getc_unlocked
127 else
128 funlockfile(infp);
129 #endif
130 return(nf);
131 }
132
133
134 static char *
135 ogetstr(char *s) /* get null-terminated string */
136 {
137 extern char *getstr();
138
139 if (getstr(s, infp) == NULL)
140 octerror(USER, "truncated octree");
141 return(s);
142 }
143
144
145 static OCTREE
146 getfullnode() /* get a set, return fullnode */
147 {
148 OBJECT set[MAXSET+1];
149 register int i;
150 register long m;
151
152 if ((set[0] = ogetint(objsize)) > MAXSET)
153 octerror(USER, "bad set in getfullnode");
154 for (i = 1; i <= set[0]; i++) {
155 m = ogetint(objsize) + objorig;
156 if ((set[i] = m) != m)
157 octerror(USER, "too many objects");
158 }
159 return(fullnode(set));
160 }
161
162
163 static long
164 ogetint(int siz) /* get a siz-byte integer */
165 {
166 extern long getint();
167 register long r;
168
169 r = getint(siz, infp);
170 if (feof(infp))
171 octerror(USER, "truncated octree");
172 return(r);
173 }
174
175
176 static double
177 ogetflt() /* get a floating point number */
178 {
179 extern double getflt();
180 double r;
181
182 r = getflt(infp);
183 if (feof(infp))
184 octerror(USER, "truncated octree");
185 return(r);
186 }
187
188
189 static OCTREE
190 gettree() /* get a pre-ordered octree */
191 {
192 register OCTREE ot;
193 register int i;
194
195 switch (getc(infp)) {
196 case OT_EMPTY:
197 return(EMPTY);
198 case OT_FULL:
199 return(getfullnode());
200 case OT_TREE:
201 if ((ot = octalloc()) == EMPTY)
202 octerror(SYSTEM, "out of tree space in gettree");
203 for (i = 0; i < 8; i++)
204 octkid(ot, i) = gettree();
205 return(ot);
206 case EOF:
207 octerror(USER, "truncated octree");
208 default:
209 octerror(USER, "damaged octree");
210 }
211 return EMPTY; /* pro forma return */
212 }
213
214
215 static int
216 nonsurfintree(OCTREE ot) /* check tree for modifiers */
217 {
218 OBJECT set[MAXSET+1];
219 register int i;
220
221 if (isempty(ot))
222 return(0);
223 if (istree(ot)) {
224 for (i = 0; i < 8; i++)
225 if (nonsurfintree(octkid(ot, i)))
226 return(1);
227 return(0);
228 }
229 objset(set, ot);
230 for (i = set[0]; i > 0; i-- )
231 if (ismodifier(objptr(set[i])->otype))
232 return(1);
233 return(0);
234 }
235
236
237 static void
238 skiptree(void) /* skip octree on input */
239 {
240 register int i;
241
242 switch (getc(infp)) {
243 case OT_EMPTY:
244 return;
245 case OT_FULL:
246 for (i = ogetint(objsize)*objsize; i-- > 0; )
247 if (getc(infp) == EOF)
248 octerror(USER, "truncated octree");
249 return;
250 case OT_TREE:
251 for (i = 0; i < 8; i++)
252 skiptree();
253 return;
254 case EOF:
255 octerror(USER, "truncated octree");
256 default:
257 octerror(USER, "damaged octree");
258 }
259 }
260
261
262 static void
263 octerror(int etyp, char *msg) /* octree error */
264 {
265 char msgbuf[128];
266
267 sprintf(msgbuf, "(%s): %s", infn, msg);
268 error(etyp, msgbuf);
269 }