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

File Contents

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