ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/readmesh.c
Revision: 2.17
Committed: Sat May 4 00:36:58 2019 UTC (4 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3
Changes since 2.16: +3 -2 lines
Log Message:
Eliminated cases where stdin was being closed

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: readmesh.c,v 2.16 2018/11/27 06:30:05 greg Exp $";
3 #endif
4 /*
5 * Routines for reading a compiled mesh from a file
6 */
7
8 #include <time.h>
9
10 #include "platform.h"
11 #include "standard.h"
12 #include "octree.h"
13 #include "object.h"
14 #include "mesh.h"
15 #include "resolu.h"
16
17 static char *meshfn; /* input file name */
18 static FILE *meshfp; /* mesh file pointer */
19 static int objsize; /* sizeof(OBJECT) from writer */
20
21
22 static void
23 mesherror(etyp, msg) /* mesh read error */
24 int etyp;
25 char *msg;
26 {
27 char msgbuf[128];
28
29 sprintf(msgbuf, "(%s): %s", meshfn, msg);
30 error(etyp, msgbuf);
31 }
32
33
34 static long
35 mgetint(siz) /* get a siz-byte integer */
36 int siz;
37 {
38 long r;
39
40 r = getint(siz, meshfp);
41 if (feof(meshfp))
42 mesherror(USER, "truncated mesh file");
43 return(r);
44 }
45
46
47 static double
48 mgetflt() /* get a floating point number */
49 {
50 double r;
51
52 r = getflt(meshfp);
53 if (feof(meshfp))
54 mesherror(USER, "truncated mesh file");
55 return(r);
56 }
57
58
59 static OCTREE
60 getfullnode() /* get a set, return fullnode */
61 {
62 OBJECT set[MAXSET+1];
63 int i;
64
65 if ((set[0] = mgetint(objsize)) > MAXSET)
66 mesherror(USER, "bad set in getfullnode");
67 for (i = 1; i <= set[0]; i++)
68 set[i] = mgetint(objsize);
69 return(fullnode(set));
70 }
71
72
73 static OCTREE
74 gettree() /* get a pre-ordered octree */
75 {
76 OCTREE ot;
77 int i;
78
79 switch (getc(meshfp)) {
80 case OT_EMPTY:
81 return(EMPTY);
82 case OT_FULL:
83 return(getfullnode());
84 case OT_TREE:
85 if ((ot = octalloc()) == EMPTY)
86 mesherror(SYSTEM, "out of tree space in readmesh");
87 for (i = 0; i < 8; i++)
88 octkid(ot, i) = gettree();
89 return(ot);
90 case EOF:
91 mesherror(USER, "truncated mesh octree");
92 default:
93 mesherror(USER, "damaged mesh octree");
94 }
95 return (OCTREE)0; /* pro forma return */
96 }
97
98
99 static void
100 skiptree() /* skip octree on input */
101 {
102 int i;
103
104 switch (getc(meshfp)) {
105 case OT_EMPTY:
106 return;
107 case OT_FULL:
108 for (i = mgetint(objsize)*objsize; i-- > 0; )
109 if (getc(meshfp) == EOF)
110 mesherror(USER, "truncated mesh octree");
111 return;
112 case OT_TREE:
113 for (i = 0; i < 8; i++)
114 skiptree();
115 return;
116 case EOF:
117 mesherror(USER, "truncated mesh octree");
118 default:
119 mesherror(USER, "damaged mesh octree");
120 }
121 }
122
123
124 static void
125 getpatch(pp) /* load a mesh patch */
126 MESHPATCH *pp;
127 {
128 int flags;
129 int i, j;
130 /* vertex flags */
131 flags = mgetint(1);
132 if (!(flags & MT_V) || flags & ~(MT_V|MT_N|MT_UV))
133 mesherror(USER, "bad patch flags");
134 /* allocate vertices */
135 pp->nverts = mgetint(2);
136 if ((pp->nverts <= 0) | (pp->nverts > 256))
137 mesherror(USER, "bad number of patch vertices");
138 pp->xyz = (uint32 (*)[3])malloc(pp->nverts*3*sizeof(uint32));
139 if (pp->xyz == NULL)
140 goto nomem;
141 if (flags & MT_N) {
142 pp->norm = (int32 *)calloc(pp->nverts, sizeof(int32));
143 if (pp->norm == NULL)
144 goto nomem;
145 } else
146 pp->norm = NULL;
147 if (flags & MT_UV) {
148 pp->uv = (uint32 (*)[2])calloc(pp->nverts, 2*sizeof(uint32));
149 if (pp->uv == NULL)
150 goto nomem;
151 } else
152 pp->uv = NULL;
153 /* vertex xyz locations */
154 for (i = 0; i < pp->nverts; i++)
155 for (j = 0; j < 3; j++)
156 pp->xyz[i][j] = mgetint(4);
157 /* vertex normals */
158 if (flags & MT_N)
159 for (i = 0; i < pp->nverts; i++)
160 pp->norm[i] = mgetint(4);
161 /* uv coordinates */
162 if (flags & MT_UV)
163 for (i = 0; i < pp->nverts; i++)
164 for (j = 0; j < 2; j++)
165 pp->uv[i][j] = mgetint(4);
166 /* local triangles */
167 pp->ntris = mgetint(2);
168 if ((pp->ntris < 0) | (pp->ntris > 512))
169 mesherror(USER, "bad number of local triangles");
170 if (pp->ntris) {
171 pp->tri = (struct PTri *)malloc(pp->ntris *
172 sizeof(struct PTri));
173 if (pp->tri == NULL)
174 goto nomem;
175 for (i = 0; i < pp->ntris; i++) {
176 pp->tri[i].v1 = mgetint(1);
177 pp->tri[i].v2 = mgetint(1);
178 pp->tri[i].v3 = mgetint(1);
179 }
180 } else
181 pp->tri = NULL;
182 /* local triangle material(s) */
183 if (mgetint(2) > 1) {
184 pp->trimat = (int16 *)malloc(pp->ntris*sizeof(int16));
185 if (pp->trimat == NULL)
186 goto nomem;
187 for (i = 0; i < pp->ntris; i++)
188 pp->trimat[i] = mgetint(2);
189 } else {
190 pp->solemat = mgetint(2);
191 pp->trimat = NULL;
192 }
193 /* joiner triangles */
194 pp->nj1tris = mgetint(2);
195 if ((pp->nj1tris < 0) | (pp->nj1tris > 256))
196 mesherror(USER, "bad number of joiner triangles");
197 if (pp->nj1tris) {
198 pp->j1tri = (struct PJoin1 *)malloc(pp->nj1tris *
199 sizeof(struct PJoin1));
200 if (pp->j1tri == NULL)
201 goto nomem;
202 for (i = 0; i < pp->nj1tris; i++) {
203 pp->j1tri[i].v1j = mgetint(4);
204 pp->j1tri[i].v2 = mgetint(1);
205 pp->j1tri[i].v3 = mgetint(1);
206 pp->j1tri[i].mat = mgetint(2);
207 }
208 } else
209 pp->j1tri = NULL;
210 /* double joiner triangles */
211 pp->nj2tris = mgetint(2);
212 if ((pp->nj2tris < 0) | (pp->nj2tris > 256))
213 mesherror(USER, "bad number of double joiner triangles");
214 if (pp->nj2tris) {
215 pp->j2tri = (struct PJoin2 *)malloc(pp->nj2tris *
216 sizeof(struct PJoin2));
217 if (pp->j2tri == NULL)
218 goto nomem;
219 for (i = 0; i < pp->nj2tris; i++) {
220 pp->j2tri[i].v1j = mgetint(4);
221 pp->j2tri[i].v2j = mgetint(4);
222 pp->j2tri[i].v3 = mgetint(1);
223 pp->j2tri[i].mat = mgetint(2);
224 }
225 } else
226 pp->j2tri = NULL;
227 return;
228 nomem:
229 error(SYSTEM, "out of mesh memory in getpatch");
230 }
231
232
233 void
234 readmesh(mp, path, flags) /* read in mesh structures */
235 MESH *mp;
236 char *path;
237 int flags;
238 {
239 char *err;
240 char sbuf[64];
241 int i;
242 /* check what's loaded */
243 flags &= (IO_INFO|IO_BOUNDS|IO_TREE|IO_SCENE) & ~mp->ldflags;
244 /* open input file */
245 if (path == NULL) {
246 meshfn = "standard input";
247 meshfp = stdin;
248 } else if ((meshfp = fopen(meshfn=path, "r")) == NULL) {
249 sprintf(errmsg, "cannot open mesh file \"%s\"", path);
250 error(SYSTEM, errmsg);
251 }
252 SET_FILE_BINARY(meshfp);
253 /* read header */
254 checkheader(meshfp, MESHFMT, flags&IO_INFO ? stdout : (FILE *)NULL);
255 /* read format number */
256 objsize = getint(2, meshfp) - MESHMAGIC;
257 if ((objsize <= 0) | (objsize > MAXOBJSIZ) | (objsize > sizeof(long)))
258 mesherror(USER, "incompatible mesh format");
259 /* read boundaries */
260 if (flags & IO_BOUNDS) {
261 for (i = 0; i < 3; i++)
262 mp->mcube.cuorg[i] = atof(getstr(sbuf, meshfp));
263 mp->mcube.cusize = atof(getstr(sbuf, meshfp));
264 for (i = 0; i < 2; i++) {
265 mp->uvlim[0][i] = mgetflt();
266 mp->uvlim[1][i] = mgetflt();
267 }
268 } else {
269 for (i = 0; i < 4; i++)
270 getstr(sbuf, meshfp);
271 for (i = 0; i < 4; i++)
272 mgetflt();
273 }
274 /* read the octree */
275 if (flags & IO_TREE)
276 mp->mcube.cutree = gettree();
277 else if (flags & IO_SCENE)
278 skiptree();
279 /* read materials and patches */
280 if (flags & IO_SCENE) {
281 mp->mat0 = nobjects;
282 readscene(meshfp, objsize);
283 mp->nmats = nobjects - mp->mat0;
284 mp->npatches = mgetint(4);
285 mp->patch = (MESHPATCH *)calloc(mp->npatches,
286 sizeof(MESHPATCH));
287 if (mp->patch == NULL)
288 mesherror(SYSTEM, "out of patch memory");
289 for (i = 0; i < mp->npatches; i++)
290 getpatch(&mp->patch[i]);
291 }
292 /* clean up */
293 if (meshfp != stdin)
294 fclose(meshfp);
295 mp->ldflags |= flags;
296 /* verify data */
297 if ((err = checkmesh(mp)) != NULL)
298 mesherror(USER, err);
299 }