File: | src/limn/io.c |
Location: | line 318, column 21 |
Description: | Array access (from variable 'vertBase') results in a null pointer dereference |
1 | /* | |||
2 | Teem: Tools to process and visualize scientific data and images . | |||
3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||
4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||
5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||
6 | ||||
7 | This library is free software; you can redistribute it and/or | |||
8 | modify it under the terms of the GNU Lesser General Public License | |||
9 | (LGPL) as published by the Free Software Foundation; either | |||
10 | version 2.1 of the License, or (at your option) any later version. | |||
11 | The terms of redistributing and/or modifying this software also | |||
12 | include exceptions to the LGPL that facilitate static linking. | |||
13 | ||||
14 | This library is distributed in the hope that it will be useful, | |||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
17 | Lesser General Public License for more details. | |||
18 | ||||
19 | You should have received a copy of the GNU Lesser General Public License | |||
20 | along with this library; if not, write to Free Software Foundation, Inc., | |||
21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
22 | */ | |||
23 | ||||
24 | ||||
25 | #include "limn.h" | |||
26 | ||||
27 | int | |||
28 | limnObjectDescribe(FILE *file, const limnObject *obj) { | |||
29 | limnFace *face; unsigned int si, fii; | |||
30 | limnEdge *edge; unsigned int eii; | |||
31 | limnVertex *vert; unsigned int vii; | |||
32 | limnPart *part; unsigned int partIdx; | |||
33 | limnLook *look; | |||
34 | ||||
35 | fprintf(file, "parts: %d\n", obj->partNum); | |||
36 | for (partIdx=0; partIdx<obj->partNum; partIdx++) { | |||
37 | part = obj->part[partIdx]; | |||
38 | fprintf(file, "part %d | verts: %d ========\n", partIdx, part->vertIdxNum); | |||
39 | for (vii=0; vii<part->vertIdxNum; vii++) { | |||
40 | vert = obj->vert + part->vertIdx[vii]; | |||
41 | fprintf(file, "part %d | %d(%d): w=(%g,%g,%g)\n", | |||
42 | partIdx, vii, part->vertIdx[vii], | |||
43 | vert->world[0], vert->world[1], vert->world[2]); | |||
44 | /* vert->view[0], vert->view[1], vert->view[2]); */ | |||
45 | /* vert->screen[0], vert->screen[1], vert->screen[2]); */ | |||
46 | } | |||
47 | fprintf(file, "part %d | edges: %d ========\n", partIdx, part->edgeIdxNum); | |||
48 | for (eii=0; eii<part->edgeIdxNum; eii++) { | |||
49 | edge = obj->edge + part->edgeIdx[eii]; | |||
50 | fprintf(file, "part %d==%d | %d(%d): " | |||
51 | "vert(%d,%d), face(%d,%d)\n", | |||
52 | partIdx, edge->partIdx, eii, part->edgeIdx[eii], | |||
53 | edge->vertIdx[0], edge->vertIdx[1], | |||
54 | edge->faceIdx[0], edge->faceIdx[1]); | |||
55 | } | |||
56 | fprintf(file, "part %d | faces: %d ========\n", partIdx, part->faceIdxNum); | |||
57 | for (fii=0; fii<part->faceIdxNum; fii++) { | |||
58 | face = obj->face + part->faceIdx[fii]; | |||
59 | fprintf(file, "part %d==%d | %d(%d): [", | |||
60 | partIdx, face->partIdx, fii, part->faceIdx[fii]); | |||
61 | for (si=0; si<face->sideNum; si++) { | |||
62 | fprintf(file, "%d", face->vertIdx[si]); | |||
63 | if (si < face->sideNum-1) { | |||
64 | fprintf(file, ","); | |||
65 | } | |||
66 | } | |||
67 | fprintf(file, "]; wn = (%g,%g,%g) |%g|", face->worldNormal[0], | |||
68 | face->worldNormal[1], face->worldNormal[2], | |||
69 | ELL_3V_LEN(face->worldNormal)(sqrt((((face->worldNormal))[0]*((face->worldNormal))[0 ] + ((face->worldNormal))[1]*((face->worldNormal))[1] + ((face->worldNormal))[2]*((face->worldNormal))[2])))); | |||
70 | look = obj->look + face->lookIdx; | |||
71 | fprintf(file, "; RGB=(%g,%g,%g)", | |||
72 | look->rgba[0], look->rgba[1], look->rgba[2]); | |||
73 | fprintf(file, "\n"); | |||
74 | } | |||
75 | } | |||
76 | ||||
77 | return 0; | |||
78 | } | |||
79 | ||||
80 | int | |||
81 | limnObjectWriteOFF(FILE *file, const limnObject *obj) { | |||
82 | static const char me[]="limnObjectWriteOFF"; | |||
83 | unsigned int si; | |||
84 | limnVertex *vert; unsigned int vii; | |||
85 | limnFace *face; unsigned int fii; | |||
86 | limnPart *part; unsigned int partIdx; | |||
87 | ||||
88 | if (!( obj && file )) { | |||
89 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
90 | return 1; | |||
91 | } | |||
92 | fprintf(file, "OFF # created by Teem/limn\n"); | |||
93 | fprintf(file, "%d %d %d\n", obj->vertNum, obj->faceNum, obj->edgeNum); | |||
94 | ||||
95 | /* write vertices */ | |||
96 | for (partIdx=0; partIdx<obj->partNum; partIdx++) { | |||
97 | fprintf(file, "### LIMN BEGIN PART %d\n", partIdx); | |||
98 | part = obj->part[partIdx]; | |||
99 | for (vii=0; vii<part->vertIdxNum; vii++) { | |||
100 | vert = obj->vert + part->vertIdx[vii]; | |||
101 | fprintf(file, "%g %g %g", | |||
102 | vert->world[0]/vert->world[3], | |||
103 | vert->world[1]/vert->world[3], | |||
104 | vert->world[2]/vert->world[3]); | |||
105 | /* verts no longer have a lookIdx | |||
106 | if (vert->lookIdx) { | |||
107 | fprintf(file, " %g %g %g", | |||
108 | obj->look[vert->lookIdx].rgba[0], | |||
109 | obj->look[vert->lookIdx].rgba[1], | |||
110 | obj->look[vert->lookIdx].rgba[2]); | |||
111 | } | |||
112 | */ | |||
113 | fprintf(file, "\n"); | |||
114 | } | |||
115 | } | |||
116 | ||||
117 | /* write faces */ | |||
118 | for (partIdx=0; partIdx<obj->partNum; partIdx++) { | |||
119 | fprintf(file, "### LIMN BEGIN PART %d\n", partIdx); | |||
120 | part = obj->part[partIdx]; | |||
121 | for (fii=0; fii<part->faceIdxNum; fii++) { | |||
122 | face = obj->face + part->faceIdx[fii]; | |||
123 | fprintf(file, "%d", face->sideNum); | |||
124 | for (si=0; si<face->sideNum; si++) { | |||
125 | fprintf(file, " %d", face->vertIdx[si]); | |||
126 | } | |||
127 | if (face->lookIdx) { | |||
128 | fprintf(file, " %g %g %g", | |||
129 | obj->look[face->lookIdx].rgba[0], | |||
130 | obj->look[face->lookIdx].rgba[1], | |||
131 | obj->look[face->lookIdx].rgba[2]); | |||
132 | } | |||
133 | fprintf(file, "\n"); | |||
134 | } | |||
135 | } | |||
136 | ||||
137 | return 0; | |||
138 | } | |||
139 | ||||
140 | int | |||
141 | limnPolyDataWriteIV(FILE *file, const limnPolyData *pld) { | |||
142 | static const char me[]="limnPolyDataWriteIV"; | |||
143 | unsigned int primIdx, xyzwIdx, rgbaIdx, normIdx, bitFlag, | |||
144 | baseVertIdx; | |||
145 | int haveStrips, haveTris, haveElse; | |||
146 | double xyz[3], norm[3], len; | |||
147 | ||||
148 | if (!(file && pld)) { | |||
149 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
150 | return 1; | |||
151 | } | |||
152 | haveStrips = haveTris = haveElse = AIR_FALSE0; | |||
153 | for (primIdx=0; primIdx<pld->primNum; primIdx++) { | |||
154 | int isTri, isStrip, isElse; | |||
155 | isTri = limnPrimitiveTriangles == pld->type[primIdx]; | |||
156 | isStrip = limnPrimitiveTriangleStrip == pld->type[primIdx]; | |||
157 | isElse = !(isTri || isStrip); | |||
158 | haveTris |= isTri; | |||
159 | haveStrips |= isStrip; | |||
160 | haveElse |= isElse; | |||
161 | if (isElse) { | |||
162 | biffAddf(LIMNlimnBiffKey, | |||
163 | "%s: sorry, can only have %s or %s prims (prim[%u] is %s)", | |||
164 | me, airEnumStr(limnPrimitive, limnPrimitiveTriangles), | |||
165 | airEnumStr(limnPrimitive, limnPrimitiveTriangleStrip), | |||
166 | primIdx, airEnumStr(limnPrimitive, pld->type[primIdx])); | |||
167 | return 1; | |||
168 | } | |||
169 | } | |||
170 | if (haveStrips && 1 != pld->primNum) { | |||
171 | biffAddf(LIMNlimnBiffKey, "%s: sorry, can only have a single triangle strip", me); | |||
172 | return 1; | |||
173 | } | |||
174 | ||||
175 | fprintf(file, "#Inventor V2.0 ascii\n"); | |||
176 | fprintf(file, "# written by Teem/limn\n\n"); | |||
177 | fprintf(file, "Separator {\n"); | |||
178 | fprintf(file, " Coordinate3 {\n"); | |||
179 | fprintf(file, " point [\n"); | |||
180 | if (haveStrips) { | |||
181 | unsigned int vii; | |||
182 | for (vii=0; vii<pld->icnt[0]; vii++) { | |||
183 | xyzwIdx = (pld->indx)[vii]; | |||
184 | ELL_34V_HOMOG(xyz, pld->xyzw + 4*xyzwIdx)((xyz)[0] = (pld->xyzw + 4*xyzwIdx)[0]/(pld->xyzw + 4*xyzwIdx )[3], (xyz)[1] = (pld->xyzw + 4*xyzwIdx)[1]/(pld->xyzw + 4*xyzwIdx)[3], (xyz)[2] = (pld->xyzw + 4*xyzwIdx)[2]/(pld ->xyzw + 4*xyzwIdx)[3]); | |||
185 | fprintf(file, " %g %g %g%s\n", | |||
186 | xyz[0], xyz[1], xyz[2], | |||
187 | vii < pld->icnt[0]-1 ? "," : ""); | |||
188 | } | |||
189 | } else { | |||
190 | for (xyzwIdx=0; xyzwIdx<pld->xyzwNum; xyzwIdx++) { | |||
191 | ELL_34V_HOMOG(xyz, pld->xyzw + 4*xyzwIdx)((xyz)[0] = (pld->xyzw + 4*xyzwIdx)[0]/(pld->xyzw + 4*xyzwIdx )[3], (xyz)[1] = (pld->xyzw + 4*xyzwIdx)[1]/(pld->xyzw + 4*xyzwIdx)[3], (xyz)[2] = (pld->xyzw + 4*xyzwIdx)[2]/(pld ->xyzw + 4*xyzwIdx)[3]); | |||
192 | fprintf(file, " %g %g %g%s\n", | |||
193 | xyz[0], xyz[1], xyz[2], | |||
194 | xyzwIdx < pld->xyzwNum-1 ? "," : ""); | |||
195 | } | |||
196 | } | |||
197 | fprintf(file, " ]\n"); | |||
198 | fprintf(file, " }\n"); | |||
199 | ||||
200 | bitFlag = limnPolyDataInfoBitFlag(pld); | |||
201 | if (bitFlag & (1 << limnPolyDataInfoNorm)) { | |||
202 | fprintf(file, " NormalBinding { value PER_VERTEX_INDEXED }\n"); | |||
203 | fprintf(file, " Normal {\n"); | |||
204 | fprintf(file, " vector [\n"); | |||
205 | if (haveStrips) { | |||
206 | unsigned int vii; | |||
207 | for (vii=0; vii<pld->icnt[0]; vii++) { | |||
208 | normIdx = (pld->indx)[vii]; | |||
209 | ELL_3V_SET(norm,((norm)[0] = (pld->norm[0 + 3*normIdx]), (norm)[1] = (pld-> norm[1 + 3*normIdx]), (norm)[2] = (pld->norm[2 + 3*normIdx ])) | |||
210 | pld->norm[0 + 3*normIdx],((norm)[0] = (pld->norm[0 + 3*normIdx]), (norm)[1] = (pld-> norm[1 + 3*normIdx]), (norm)[2] = (pld->norm[2 + 3*normIdx ])) | |||
211 | pld->norm[1 + 3*normIdx],((norm)[0] = (pld->norm[0 + 3*normIdx]), (norm)[1] = (pld-> norm[1 + 3*normIdx]), (norm)[2] = (pld->norm[2 + 3*normIdx ])) | |||
212 | pld->norm[2 + 3*normIdx])((norm)[0] = (pld->norm[0 + 3*normIdx]), (norm)[1] = (pld-> norm[1 + 3*normIdx]), (norm)[2] = (pld->norm[2 + 3*normIdx ])); | |||
213 | ELL_3V_NORM(norm, norm, len)(len = (sqrt((((norm))[0]*((norm))[0] + ((norm))[1]*((norm))[ 1] + ((norm))[2]*((norm))[2]))), ((norm)[0] = (1.0/len)*(norm )[0], (norm)[1] = (1.0/len)*(norm)[1], (norm)[2] = (1.0/len)* (norm)[2])); | |||
214 | fprintf(file, " %g %g %g%s\n", norm[0], norm[1], norm[2], | |||
215 | vii < pld->icnt[0]-1 ? "," : ""); | |||
216 | } | |||
217 | } else { | |||
218 | for (normIdx=0; normIdx<pld->normNum; normIdx++) { | |||
219 | fprintf(file, " %g %g %g%s\n", | |||
220 | pld->norm[0 + 3*normIdx], | |||
221 | pld->norm[1 + 3*normIdx], | |||
222 | pld->norm[2 + 3*normIdx], | |||
223 | normIdx < pld->normNum-1 ? "," : ""); | |||
224 | } | |||
225 | } | |||
226 | fprintf(file, " ]\n"); | |||
227 | fprintf(file, " }\n"); | |||
228 | } | |||
229 | if (!haveStrips) { | |||
230 | if (bitFlag & (1 << limnPolyDataInfoRGBA)) { | |||
231 | fprintf(file, " MaterialBinding { value PER_VERTEX_INDEXED }\n"); | |||
232 | fprintf(file, " Material {\n"); | |||
233 | fprintf(file, " diffuseColor [\n"); | |||
234 | for (rgbaIdx=0; rgbaIdx<pld->rgbaNum; rgbaIdx++) { | |||
235 | fprintf(file, " %g %g %g%s\n", | |||
236 | pld->rgba[0 + 4*rgbaIdx]/255.0, | |||
237 | pld->rgba[1 + 4*rgbaIdx]/255.0, | |||
238 | pld->rgba[2 + 4*rgbaIdx]/255.0, | |||
239 | rgbaIdx < pld->rgbaNum-1 ? "," : ""); | |||
240 | } | |||
241 | fprintf(file, " ]\n"); | |||
242 | fprintf(file, " }\n"); | |||
243 | } | |||
244 | } | |||
245 | ||||
246 | if (haveStrips) { | |||
247 | fprintf(file, " TriangleStripSet {\n"); | |||
248 | fprintf(file, " numVertices %u\n", pld->icnt[0]); | |||
249 | fprintf(file, " }\n"); | |||
250 | } else { | |||
251 | fprintf(file, " IndexedFaceSet {\n"); | |||
252 | fprintf(file, " coordIndex [\n"); | |||
253 | ||||
254 | baseVertIdx = 0; | |||
255 | for (primIdx=0; primIdx<pld->primNum; primIdx++) { | |||
256 | unsigned int triIdx, triNum, *indx3; | |||
257 | triNum = pld->icnt[primIdx]/3; | |||
258 | for (triIdx=0; triIdx<triNum; triIdx++) { | |||
259 | indx3 = pld->indx + baseVertIdx + 3*triIdx; | |||
260 | fprintf(file, " %u, %u, %u, -1%s\n", | |||
261 | indx3[0], indx3[1], indx3[2], | |||
262 | triIdx < triNum-1 ? "," : ""); | |||
263 | } | |||
264 | baseVertIdx += 3*triNum; | |||
265 | } | |||
266 | fprintf(file, " ]\n"); | |||
267 | fprintf(file, " }\n"); | |||
268 | } | |||
269 | ||||
270 | fprintf(file, "}\n"); | |||
271 | ||||
272 | return 0; | |||
273 | } | |||
274 | ||||
275 | int | |||
276 | limnObjectReadOFF(limnObject *obj, FILE *file) { | |||
277 | static const char me[]="limnObjectReadOFF"; | |||
278 | double vert[6]; | |||
279 | char line[AIR_STRLEN_LARGE(512+1)]; /* HEY: bad Gordon */ | |||
280 | int lineCount, lookIdx, partIdx, idxTmp, faceNum, faceGot, got; | |||
281 | unsigned int vertGot,vertNum; | |||
282 | unsigned int ibuff[1024]; /* HEY: bad Gordon */ | |||
283 | float fbuff[1024]; /* HEY: bad bad Gordon */ | |||
284 | float lastRGB[3]={-1,-1,-1}; int lastLook; | |||
285 | unsigned int lret; | |||
286 | ||||
287 | int *vertBase; | |||
288 | airArray *vertBaseArr, *mop; | |||
289 | airPtrPtrUnion appu; | |||
290 | ||||
291 | if (!( obj && file )) { | |||
| ||||
292 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
293 | return 1; | |||
294 | } | |||
295 | vertBase = NULL((void*)0); | |||
296 | appu.i = &vertBase; | |||
297 | vertBaseArr = airArrayNew(appu.v, NULL((void*)0), sizeof(int), 128); | |||
298 | mop = airMopNew(); | |||
299 | airMopAdd(mop, vertBaseArr, (airMopper)airArrayNuke, airMopAlways); | |||
300 | got = 0; | |||
301 | lineCount = 0; | |||
302 | do { | |||
303 | if (!airOneLine(file, line, AIR_STRLEN_LARGE(512+1))) { | |||
304 | biffAddf(LIMNlimnBiffKey, "%s: hit EOF before getting #vert #face #edge line", me); | |||
305 | airMopError(mop); return 1; | |||
306 | } | |||
307 | lineCount++; | |||
308 | got = airParseStrUI(ibuff, line, AIR_WHITESPACE" \t\n\r\v\f", 3); | |||
309 | } while (3 != got); | |||
310 | vertNum = ibuff[0]; | |||
311 | faceNum = ibuff[1]; | |||
312 | ||||
313 | /* read all vertex information */ | |||
314 | lastLook = -1; | |||
315 | partIdx = limnObjectPartAdd(obj); | |||
316 | vertGot = 0; | |||
317 | airArrayLenIncr(vertBaseArr, 1); | |||
318 | vertBase[partIdx] = vertGot; | |||
| ||||
319 | while (vertGot < vertNum) { | |||
320 | do { | |||
321 | lret = airOneLine(file, line, AIR_STRLEN_LARGE(512+1)); | |||
322 | lineCount++; | |||
323 | } while (1 == lret); | |||
324 | if (!lret) { | |||
325 | biffAddf(LIMNlimnBiffKey, | |||
326 | "%s: (near line %d) hit EOF trying to read vert %d (of %d)", | |||
327 | me, lineCount, vertGot, vertNum); | |||
328 | airMopError(mop); return 1; | |||
329 | } | |||
330 | if (1 == sscanf(line, "### LIMN BEGIN PART %d", &idxTmp)) { | |||
331 | if (idxTmp != 0) { | |||
332 | partIdx = limnObjectPartAdd(obj); | |||
333 | if (idxTmp != partIdx) { | |||
334 | biffAddf(LIMNlimnBiffKey, "%s: got signal to start part %d, not %d", | |||
335 | me, idxTmp, partIdx); | |||
336 | airMopError(mop); return 1; | |||
337 | } | |||
338 | airArrayLenIncr(vertBaseArr, 1); | |||
339 | vertBase[partIdx] = vertGot; | |||
340 | } | |||
341 | continue; | |||
342 | } | |||
343 | if (3 != airParseStrD(vert, line, AIR_WHITESPACE" \t\n\r\v\f", 3)) { | |||
344 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse 3 doubles from \"%s\" " | |||
345 | "for vert %d (of %d)", | |||
346 | me, line, vertGot, vertNum); | |||
347 | airMopError(mop); return 1; | |||
348 | } | |||
349 | if (6 == airParseStrD(vert, line, AIR_WHITESPACE" \t\n\r\v\f", 6)) { | |||
350 | /* we could also parse an RGB color */ | |||
351 | if (-1 == lastLook || !ELL_3V_EQUAL(lastRGB, vert+3)((lastRGB)[0] == (vert+3)[0] && (lastRGB)[1] == (vert +3)[1] && (lastRGB)[2] == (vert+3)[2])) { | |||
352 | lookIdx = limnObjectLookAdd(obj); | |||
353 | ELL_4V_SET(obj->look[lookIdx].rgba,((obj->look[lookIdx].rgba)[0] = (((float)(vert[3]))), (obj ->look[lookIdx].rgba)[1] = (((float)(vert[4]))), (obj-> look[lookIdx].rgba)[2] = (((float)(vert[5]))), (obj->look[ lookIdx].rgba)[3] = (1)) | |||
354 | AIR_CAST(float, vert[3]),((obj->look[lookIdx].rgba)[0] = (((float)(vert[3]))), (obj ->look[lookIdx].rgba)[1] = (((float)(vert[4]))), (obj-> look[lookIdx].rgba)[2] = (((float)(vert[5]))), (obj->look[ lookIdx].rgba)[3] = (1)) | |||
355 | AIR_CAST(float, vert[4]),((obj->look[lookIdx].rgba)[0] = (((float)(vert[3]))), (obj ->look[lookIdx].rgba)[1] = (((float)(vert[4]))), (obj-> look[lookIdx].rgba)[2] = (((float)(vert[5]))), (obj->look[ lookIdx].rgba)[3] = (1)) | |||
356 | AIR_CAST(float, vert[5]),((obj->look[lookIdx].rgba)[0] = (((float)(vert[3]))), (obj ->look[lookIdx].rgba)[1] = (((float)(vert[4]))), (obj-> look[lookIdx].rgba)[2] = (((float)(vert[5]))), (obj->look[ lookIdx].rgba)[3] = (1)) | |||
357 | 1)((obj->look[lookIdx].rgba)[0] = (((float)(vert[3]))), (obj ->look[lookIdx].rgba)[1] = (((float)(vert[4]))), (obj-> look[lookIdx].rgba)[2] = (((float)(vert[5]))), (obj->look[ lookIdx].rgba)[3] = (1)); | |||
358 | lastLook = lookIdx; | |||
359 | ELL_3V_COPY_TT(lastRGB, float, vert+3)((lastRGB)[0] = ((float)((vert+3)[0])), (lastRGB)[1] = ((float )((vert+3)[1])), (lastRGB)[2] = ((float)((vert+3)[2]))); | |||
360 | } else { | |||
361 | lookIdx = lastLook; | |||
362 | } | |||
363 | } else { | |||
364 | lookIdx = 0; | |||
365 | } | |||
366 | /* | |||
367 | fprintf(stderr, "line %d: vertGot = %d; lookIdx = %d; partIdx = %d\n", | |||
368 | lineCount, vertGot, lookIdx, partIdx); | |||
369 | */ | |||
370 | limnObjectVertexAdd(obj, partIdx, | |||
371 | AIR_CAST(float, vert[0])((float)(vert[0])), | |||
372 | AIR_CAST(float, vert[1])((float)(vert[1])), | |||
373 | AIR_CAST(float, vert[2])((float)(vert[2]))); | |||
374 | vertGot++; | |||
375 | } | |||
376 | /* read face information */ | |||
377 | partIdx = 0; | |||
378 | faceGot = 0; | |||
379 | while (faceGot < faceNum) { | |||
380 | do { | |||
381 | lret = airOneLine(file, line, AIR_STRLEN_LARGE(512+1)); | |||
382 | lineCount++; | |||
383 | } while (1 == lret); | |||
384 | if (!lret) { | |||
385 | biffAddf(LIMNlimnBiffKey, | |||
386 | "%s: (near line %d) hit EOF trying to read face %d (of %d)", | |||
387 | me, lineCount, faceGot, faceNum); | |||
388 | airMopError(mop); return 1; | |||
389 | } | |||
390 | if (1 == sscanf(line, "### LIMN BEGIN PART %d", &idxTmp)) { | |||
391 | if (idxTmp != 0) { | |||
392 | partIdx += 1; | |||
393 | if (idxTmp != partIdx) { | |||
394 | biffAddf(LIMNlimnBiffKey, "%s: (near line %d) got signal to start " | |||
395 | "part %d, not %d", | |||
396 | me, lineCount, idxTmp, partIdx); | |||
397 | airMopError(mop); return 1; | |||
398 | } | |||
399 | } | |||
400 | continue; | |||
401 | } | |||
402 | if ('#' == line[0]) { | |||
403 | /* its some other kind of comment line */ | |||
404 | continue; | |||
405 | } | |||
406 | if (1 != sscanf(line, "%u", &vertNum)) { | |||
407 | biffAddf(LIMNlimnBiffKey, "%s: (near line %d) can't get first int " | |||
408 | "(#verts) from \"%s\" for face %d (of %d)", | |||
409 | me, lineCount, line, faceGot, faceNum); | |||
410 | airMopError(mop); return 1; | |||
411 | } | |||
412 | if (vertNum+1 != airParseStrUI(ibuff, line, AIR_WHITESPACE" \t\n\r\v\f", vertNum+1)) { | |||
413 | biffAddf(LIMNlimnBiffKey, "%s: (near line %d) couldn't parse %d ints from \"%s\" " | |||
414 | "for face %d (of %d)", | |||
415 | me, lineCount, vertNum+1, line, faceGot, faceNum); | |||
416 | airMopError(mop); return 1; | |||
417 | } | |||
418 | if (vertNum+1+3 == airParseStrF(fbuff, line, | |||
419 | AIR_WHITESPACE" \t\n\r\v\f", vertNum+1+3)) { | |||
420 | /* could also parse color */ | |||
421 | if (-1 == lastLook || !ELL_3V_EQUAL(lastRGB, fbuff+vertNum+1)((lastRGB)[0] == (fbuff+vertNum+1)[0] && (lastRGB)[1] == (fbuff+vertNum+1)[1] && (lastRGB)[2] == (fbuff+vertNum +1)[2])) { | |||
422 | lookIdx = limnObjectLookAdd(obj); | |||
423 | ELL_4V_SET(obj->look[lookIdx].rgba, fbuff[vertNum+1+0],((obj->look[lookIdx].rgba)[0] = (fbuff[vertNum+1+0]), (obj ->look[lookIdx].rgba)[1] = (fbuff[vertNum+1+1]), (obj-> look[lookIdx].rgba)[2] = (fbuff[vertNum+1+2]), (obj->look[ lookIdx].rgba)[3] = (1)) | |||
424 | fbuff[vertNum+1+1], fbuff[vertNum+1+2], 1)((obj->look[lookIdx].rgba)[0] = (fbuff[vertNum+1+0]), (obj ->look[lookIdx].rgba)[1] = (fbuff[vertNum+1+1]), (obj-> look[lookIdx].rgba)[2] = (fbuff[vertNum+1+2]), (obj->look[ lookIdx].rgba)[3] = (1)); | |||
425 | lastLook = lookIdx; | |||
426 | ELL_3V_COPY(lastRGB, fbuff+vertNum+1)((lastRGB)[0] = (fbuff+vertNum+1)[0], (lastRGB)[1] = (fbuff+vertNum +1)[1], (lastRGB)[2] = (fbuff+vertNum+1)[2]); | |||
427 | } else { | |||
428 | lookIdx = lastLook; | |||
429 | } | |||
430 | } else { | |||
431 | lookIdx = 0; | |||
432 | } | |||
433 | /* | |||
434 | fprintf(stderr, "line %d: faceGot = %d; lookIdx = %d; partIdx = %d\n", | |||
435 | lineCount, faceGot, lookIdx, partIdx); | |||
436 | */ | |||
437 | limnObjectFaceAdd(obj, partIdx, lookIdx, vertNum, ibuff+1); | |||
438 | faceGot++; | |||
439 | } | |||
440 | ||||
441 | airMopOkay(mop); | |||
442 | return 0; | |||
443 | } | |||
444 | ||||
445 | /* | |||
446 | http://www.npr.org/templates/story/story.php?storyId=4531695 | |||
447 | */ | |||
448 | ||||
449 | #define LMPD_MAGIC"LIMN0001" "LIMN0001" | |||
450 | #define DEMARK_STR"====== " "====== " | |||
451 | #define DEMARK_CHAR'=' '=' | |||
452 | #define NUM_STR"num:" "num:" | |||
453 | #define INFO_STR"info:" "info:" | |||
454 | #define TYPE_STR"type:" "type:" | |||
455 | #define ICNT_STR"icnt:" "icnt:" | |||
456 | #define INDX_STR"indx:" "indx:" | |||
457 | #define XYZW_STR"xyzw:" "xyzw:" | |||
458 | ||||
459 | int | |||
460 | limnPolyDataWriteLMPD(FILE *file, const limnPolyData *pld) { | |||
461 | static const char me[]="limnPolyDataWriteLMPD"; | |||
462 | char infoS[AIR_STRLEN_MED(256+1)]; | |||
463 | unsigned int primIdx, infoNum, flag, bit; | |||
464 | Nrrd *nrrd; | |||
465 | airArray *mop; | |||
466 | ||||
467 | if (!(file && pld)) { | |||
468 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
469 | return 1; | |||
470 | } | |||
471 | ||||
472 | for (primIdx=0; primIdx<pld->primNum; primIdx++) { | |||
473 | if (limnPrimitiveNoop == pld->type[primIdx]) { | |||
474 | biffAddf(LIMNlimnBiffKey, "%s: sorry, can't save with prim[%u] type %s", me, | |||
475 | primIdx, airEnumStr(limnPrimitive, pld->type[primIdx])); | |||
476 | return 1; | |||
477 | } | |||
478 | } | |||
479 | ||||
480 | mop = airMopNew(); | |||
481 | ||||
482 | fprintf(file, "%s\n", LMPD_MAGIC"LIMN0001"); | |||
483 | fprintf(file, "%s%s %u %u %u\n", DEMARK_STR"====== ", NUM_STR"num:", | |||
484 | pld->xyzwNum, pld->indxNum, pld->primNum); | |||
485 | ||||
486 | flag = limnPolyDataInfoBitFlag(pld); | |||
487 | infoNum = 0; | |||
488 | bit = 0; | |||
489 | strcpy(infoS, "")__builtin___strcpy_chk (infoS, "", __builtin_object_size (infoS , 2 > 1 ? 1 : 0)); | |||
490 | while (flag) { | |||
491 | if (flag & 1) { | |||
492 | infoNum += 1; | |||
493 | strcat(infoS, airEnumStr(limnPolyDataInfo, bit))__builtin___strcat_chk (infoS, airEnumStr(limnPolyDataInfo, bit ), __builtin_object_size (infoS, 2 > 1 ? 1 : 0)); | |||
494 | strcat(infoS, "\n")__builtin___strcat_chk (infoS, "\n", __builtin_object_size (infoS , 2 > 1 ? 1 : 0)); | |||
495 | } | |||
496 | flag /= 2; | |||
497 | bit += 1; | |||
498 | } | |||
499 | fprintf(file, "%s%s %u\n%s", DEMARK_STR"====== ", INFO_STR"info:", infoNum, infoS); | |||
500 | ||||
501 | fprintf(file, "%s%s\n", DEMARK_STR"====== ", TYPE_STR"type:"); | |||
502 | for (primIdx=0; primIdx<pld->primNum; primIdx++) { | |||
503 | fprintf(file, "%s\n", airEnumStr(limnPrimitive, pld->type[primIdx])); | |||
504 | } | |||
505 | fprintf(file, "%s%s\n", DEMARK_STR"====== ", ICNT_STR"icnt:"); | |||
506 | for (primIdx=0; primIdx<pld->primNum; primIdx++) { | |||
507 | fprintf(file, "%u\n", pld->icnt[primIdx]); | |||
508 | } | |||
509 | nrrd = nrrdNew(); | |||
510 | airMopAdd(mop, nrrd, (airMopper)nrrdNix, airMopAlways); /* nix, not nuke */ | |||
511 | ||||
512 | fprintf(file, "%s%s\n", DEMARK_STR"====== ", INDX_STR"indx:"); | |||
513 | if (nrrdWrap_va(nrrd, pld->indx, nrrdTypeUInt, 1, pld->indxNum) | |||
514 | || nrrdWrite(file, nrrd, NULL((void*)0))) { | |||
515 | biffMovef(LIMNlimnBiffKey, NRRDnrrdBiffKey, "%s: problem saving indx array", me); | |||
516 | airMopError(mop); return 1; | |||
517 | } | |||
518 | fflush(file); | |||
519 | fprintf(file, "\n"); | |||
520 | ||||
521 | fprintf(file, "%s%s\n", DEMARK_STR"====== ", XYZW_STR"xyzw:"); | |||
522 | if (nrrdWrap_va(nrrd, pld->xyzw, nrrdTypeFloat, 2, 4, pld->xyzwNum) | |||
523 | || nrrdWrite(file, nrrd, NULL((void*)0))) { | |||
524 | biffMovef(LIMNlimnBiffKey, NRRDnrrdBiffKey, "%s: problem saving xyzw array", me); | |||
525 | airMopError(mop); return 1; | |||
526 | } | |||
527 | fflush(file); | |||
528 | fprintf(file, "\n"); | |||
529 | ||||
530 | if (infoNum) { | |||
531 | flag = limnPolyDataInfoBitFlag(pld); | |||
532 | bit = 0; | |||
533 | while (flag) { | |||
534 | if (flag & 1) { | |||
535 | int E; | |||
536 | fprintf(file, "%s%s %s\n", DEMARK_STR"====== ", INFO_STR"info:", | |||
537 | airEnumStr(limnPolyDataInfo, bit)); | |||
538 | switch (bit) { | |||
539 | case limnPolyDataInfoRGBA: | |||
540 | E = nrrdWrap_va(nrrd, pld->rgba, nrrdTypeUChar, 2, 4, pld->rgbaNum); | |||
541 | break; | |||
542 | case limnPolyDataInfoNorm: | |||
543 | E = nrrdWrap_va(nrrd, pld->norm, nrrdTypeFloat, 2, 3, pld->normNum); | |||
544 | break; | |||
545 | case limnPolyDataInfoTex2: | |||
546 | E = nrrdWrap_va(nrrd, pld->tex2, nrrdTypeFloat, 2, 2, pld->tex2Num); | |||
547 | break; | |||
548 | case limnPolyDataInfoTang: | |||
549 | E = nrrdWrap_va(nrrd, pld->tang, nrrdTypeFloat, 2, 3, pld->tangNum); | |||
550 | break; | |||
551 | default: | |||
552 | biffAddf(LIMNlimnBiffKey, "%s: info %d (%s) not handled", me, bit, | |||
553 | airEnumStr(limnPolyDataInfo, bit)); | |||
554 | airMopError(mop); return 1; | |||
555 | break; | |||
556 | } | |||
557 | if (E || nrrdWrite(file, nrrd, NULL((void*)0))) { | |||
558 | biffMovef(LIMNlimnBiffKey, NRRDnrrdBiffKey, "%s: problem saving %s info", | |||
559 | me, airEnumStr(limnPolyDataInfo, bit)); | |||
560 | airMopError(mop); return 1; | |||
561 | } | |||
562 | fflush(file); | |||
563 | fprintf(file, "\n"); | |||
564 | } | |||
565 | flag /= 2; | |||
566 | bit += 1; | |||
567 | } | |||
568 | } | |||
569 | ||||
570 | airMopOkay(mop); | |||
571 | return 0; | |||
572 | } | |||
573 | ||||
574 | /* | |||
575 | ******** limnPolyDataReadLMPD | |||
576 | ** | |||
577 | ** reads a limnPolyData from an LMPD file | |||
578 | ** | |||
579 | ** HEY: this was written in a hurry, is pretty hacky, and so it | |||
580 | ** needs some serious clean-up | |||
581 | */ | |||
582 | int | |||
583 | limnPolyDataReadLMPD(limnPolyData *pld, FILE *file) { | |||
584 | static const char me[]="limnPolyDatReadLMPD"; | |||
585 | char line[AIR_STRLEN_MED(256+1)], name[AIR_STRLEN_MED(256+1)], *tmp; | |||
586 | unsigned int vertNum, indxNum, primNum, primIdx, lineLen, | |||
587 | infoNum, infoIdx, info, flag; | |||
588 | Nrrd *nrrd; | |||
589 | airArray *mop; | |||
590 | int hackhack, tmpChar; | |||
591 | ||||
592 | if (!(pld && file)) { | |||
593 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
594 | return 1; | |||
595 | } | |||
596 | ||||
597 | sprintf(name, "magic")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "magic"); | |||
598 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
599 | if (!lineLen) { | |||
600 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
601 | return 1; | |||
602 | } | |||
603 | if (strcmp(line, LMPD_MAGIC"LIMN0001")) { | |||
604 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" not expected \"%s\"", | |||
605 | me, name, line, LMPD_MAGIC"LIMN0001"); | |||
606 | return 1; | |||
607 | } | |||
608 | ||||
609 | sprintf(name, "nums")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "nums"); | |||
610 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
611 | if (!lineLen) { | |||
612 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
613 | return 1; | |||
614 | } | |||
615 | if (strncmp(line, DEMARK_STR"====== " NUM_STR"num:", strlen(DEMARK_STR"====== " NUM_STR"num:"))) { | |||
616 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" didn't start w/ expected \"%s\"", | |||
617 | me, name, line, NUM_STR"num:"); | |||
618 | return 1; | |||
619 | } | |||
620 | tmp = line + strlen(DEMARK_STR"====== " NUM_STR"num:"); | |||
621 | if (3 != sscanf(tmp, " %u %u %u", &vertNum, &indxNum, &primNum)) { | |||
622 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse \"%s\" as 3 uints on %s line", | |||
623 | me, tmp, name); | |||
624 | return 1; | |||
625 | } | |||
626 | ||||
627 | sprintf(name, "info")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "info"); | |||
628 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
629 | if (!lineLen) { | |||
630 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
631 | return 1; | |||
632 | } | |||
633 | if (strncmp(line, DEMARK_STR"====== " INFO_STR"info:", strlen(DEMARK_STR"====== " INFO_STR"info:"))) { | |||
634 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" didn't start w/ expected \"%s\"", | |||
635 | me, name, line, DEMARK_STR"====== " INFO_STR"info:"); | |||
636 | return 1; | |||
637 | } | |||
638 | tmp = line + strlen(DEMARK_STR"====== " INFO_STR"info:"); | |||
639 | if (1 != sscanf(tmp, " %u", &infoNum)) { | |||
640 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse \"%s\" as 1 uints on %s line", | |||
641 | me, tmp, name); | |||
642 | return 1; | |||
643 | } | |||
644 | flag = 0; | |||
645 | for (infoIdx=0; infoIdx<infoNum; infoIdx++) { | |||
646 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
647 | if (!lineLen) { | |||
648 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line %u/%u", | |||
649 | me, name, infoIdx, infoNum); | |||
650 | return 1; | |||
651 | } | |||
652 | info = airEnumVal(limnPolyDataInfo, line); | |||
653 | if (!info) { | |||
654 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse \"%s\" %s line %u/%u", | |||
655 | me, line, name, infoIdx, infoNum); | |||
656 | return 1; | |||
657 | } | |||
658 | flag |= (1 << info); | |||
659 | } | |||
660 | ||||
661 | /* finally, allocate the polydata */ | |||
662 | if (limnPolyDataAlloc(pld, flag, vertNum, indxNum, primNum)) { | |||
663 | biffAddf(LIMNlimnBiffKey, "%s: couldn't allocate polydata", me); | |||
664 | return 1; | |||
665 | } | |||
666 | /* actually, caller owns pld, so we don't register it with mop */ | |||
667 | ||||
668 | sprintf(name, "type")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "type"); | |||
669 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
670 | if (!lineLen) { | |||
671 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
672 | return 1; | |||
673 | } | |||
674 | if (strcmp(line, DEMARK_STR"====== " TYPE_STR"type:")) { | |||
675 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" not expected \"%s\"", | |||
676 | me, name, line, DEMARK_STR"====== " TYPE_STR"type:"); | |||
677 | return 1; | |||
678 | } | |||
679 | for (primIdx=0; primIdx<primNum; primIdx++) { | |||
680 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
681 | if (!lineLen) { | |||
682 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line %u/%u", | |||
683 | me, name, primIdx, primNum); | |||
684 | return 1; | |||
685 | } | |||
686 | pld->type[primIdx] = airEnumVal(limnPrimitive, line); | |||
687 | if (!(pld->type[primIdx])) { | |||
688 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse \"%s\" %s line %u/%u", | |||
689 | me, line, name, primIdx, primNum); | |||
690 | return 1; | |||
691 | } | |||
692 | } | |||
693 | ||||
694 | sprintf(name, "icnt")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "icnt"); | |||
695 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
696 | if (!lineLen) { | |||
697 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
698 | return 1; | |||
699 | } | |||
700 | if (strcmp(line, DEMARK_STR"====== " ICNT_STR"icnt:")) { | |||
701 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" not expected \"%s\"", | |||
702 | me, name, line, DEMARK_STR"====== " ICNT_STR"icnt:"); | |||
703 | return 1; | |||
704 | } | |||
705 | for (primIdx=0; primIdx<primNum; primIdx++) { | |||
706 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
707 | if (!lineLen) { | |||
708 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line %u/%u", | |||
709 | me, name, primIdx, primNum); | |||
710 | return 1; | |||
711 | } | |||
712 | if (1 != sscanf(line, "%u", &(pld->icnt[primIdx]))) { | |||
713 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse \"%s\" %s line %u/%u", | |||
714 | me, line, name, primIdx, primNum); | |||
715 | return 1; | |||
716 | } | |||
717 | } | |||
718 | ||||
719 | sprintf(name, "indx")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "indx"); | |||
720 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
721 | if (!lineLen) { | |||
722 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
723 | return 1; | |||
724 | } | |||
725 | if (strcmp(line, DEMARK_STR"====== " INDX_STR"indx:")) { | |||
726 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" not expected \"%s\"", | |||
727 | me, name, line, DEMARK_STR"====== " ICNT_STR"icnt:"); | |||
728 | return 1; | |||
729 | } | |||
730 | ||||
731 | /* NOW its finally time to create the mop */ | |||
732 | mop = airMopNew(); | |||
733 | nrrd = nrrdNew(); | |||
734 | airMopAdd(mop, nrrd, (airMopper)nrrdNuke, airMopAlways); | |||
735 | /* HEY HEY HEY HOLY CRAP! | |||
736 | ** why the hell isn't the verbosity level a field in NrrdIoState ?!?! | |||
737 | ** THIS NEES TO BE FIXED (in nrrd) ASAP! | |||
738 | */ | |||
739 | hackhack = nrrdStateVerboseIO; | |||
740 | nrrdStateVerboseIO = 0; | |||
741 | if (nrrdRead(nrrd, file, NULL((void*)0))) { | |||
742 | biffMovef(LIMNlimnBiffKey, NRRDnrrdBiffKey, "%s: trouble reading %s data", me, name); | |||
743 | airMopError(mop); return 1; | |||
744 | } | |||
745 | if (!(nrrdTypeUInt == nrrd->type | |||
746 | && 1 == nrrd->dim | |||
747 | && indxNum == nrrd->axis[0].size)) { | |||
748 | biffAddf(LIMNlimnBiffKey, "%s: didn't get 1-D %s-type %u-sample array " | |||
749 | "(got %u-D %s-type %u-by-? array)", me, | |||
750 | airEnumStr(nrrdType, nrrdTypeUInt), | |||
751 | AIR_CAST(unsigned int, indxNum)((unsigned int)(indxNum)), | |||
752 | nrrd->dim, | |||
753 | airEnumStr(nrrdType, nrrd->type), | |||
754 | AIR_CAST(unsigned int, nrrd->axis[0].size)((unsigned int)(nrrd->axis[0].size))); | |||
755 | airMopError(mop); return 1; | |||
756 | } | |||
757 | /* now copy the data */ | |||
758 | memcpy(pld->indx, nrrd->data, nrrdElementSize(nrrd)*nrrdElementNumber(nrrd))__builtin___memcpy_chk (pld->indx, nrrd->data, nrrdElementSize (nrrd)*nrrdElementNumber(nrrd), __builtin_object_size (pld-> indx, 0)); | |||
759 | do { | |||
760 | tmpChar = getc(file); | |||
761 | if (EOF(-1) == tmpChar) { | |||
762 | biffAddf(LIMNlimnBiffKey, "%s: hit EOF seeking to begin next line", me); | |||
763 | airMopError(mop); return 1; | |||
764 | } | |||
765 | } while (DEMARK_CHAR'=' != tmpChar); | |||
766 | ungetc(tmpChar, file); | |||
767 | ||||
768 | sprintf(name, "xyzw")__builtin___sprintf_chk (name, 0, __builtin_object_size (name , 2 > 1 ? 1 : 0), "xyzw"); | |||
769 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
770 | if (!lineLen) { | |||
771 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line", me, name); | |||
772 | return 1; | |||
773 | } | |||
774 | if (strcmp(line, DEMARK_STR"====== " XYZW_STR"xyzw:")) { | |||
775 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" not expected \"%s\"", | |||
776 | me, name, line, DEMARK_STR"====== " XYZW_STR"xyzw:"); | |||
777 | return 1; | |||
778 | } | |||
779 | if (nrrdRead(nrrd, file, NULL((void*)0))) { | |||
780 | biffMovef(LIMNlimnBiffKey, NRRDnrrdBiffKey, "%s: trouble reading %s data", me, name); | |||
781 | airMopError(mop); return 1; | |||
782 | } | |||
783 | if (!(nrrdTypeFloat == nrrd->type | |||
784 | && 2 == nrrd->dim | |||
785 | && 4 == nrrd->axis[0].size | |||
786 | && vertNum == nrrd->axis[1].size)) { | |||
787 | biffAddf(LIMNlimnBiffKey, "%s: didn't get 2-D %s-type 4-by-%u array " | |||
788 | "(got %u-D %s-type %u-by-%u array)", me, | |||
789 | airEnumStr(nrrdType, nrrdTypeFloat), | |||
790 | AIR_CAST(unsigned int, vertNum)((unsigned int)(vertNum)), | |||
791 | nrrd->dim, | |||
792 | airEnumStr(nrrdType, nrrd->type), | |||
793 | AIR_CAST(unsigned int, nrrd->axis[0].size)((unsigned int)(nrrd->axis[0].size)), | |||
794 | AIR_CAST(unsigned int, nrrd->axis[1].size)((unsigned int)(nrrd->axis[1].size))); | |||
795 | airMopError(mop); return 1; | |||
796 | } | |||
797 | /* now copy the data */ | |||
798 | memcpy(pld->xyzw, nrrd->data, nrrdElementSize(nrrd)*nrrdElementNumber(nrrd))__builtin___memcpy_chk (pld->xyzw, nrrd->data, nrrdElementSize (nrrd)*nrrdElementNumber(nrrd), __builtin_object_size (pld-> xyzw, 0)); | |||
799 | ||||
800 | if (infoNum) { | |||
801 | int wantType; | |||
802 | unsigned int wantSize; | |||
803 | void *data; | |||
804 | for (infoIdx=0; infoIdx<infoNum; infoIdx++) { | |||
805 | do { | |||
806 | tmpChar = getc(file); | |||
807 | if (EOF(-1) == tmpChar) { | |||
808 | biffAddf(LIMNlimnBiffKey, "%s: hit EOF seeking to begin next line", me); | |||
809 | airMopError(mop); return 1; | |||
810 | } | |||
811 | } while (DEMARK_CHAR'=' != tmpChar); | |||
812 | ungetc(tmpChar, file); | |||
813 | lineLen = airOneLine(file, line, AIR_STRLEN_MED(256+1)); | |||
814 | if (!lineLen) { | |||
815 | biffAddf(LIMNlimnBiffKey, "%s: didn't get %s line %u/%u", me, | |||
816 | INFO_STR"info:", infoIdx, infoNum); | |||
817 | return 1; | |||
818 | } | |||
819 | if (strncmp(line, DEMARK_STR"====== " INFO_STR"info:", strlen(DEMARK_STR"====== " INFO_STR"info:"))) { | |||
820 | biffAddf(LIMNlimnBiffKey, "%s: %s line \"%s\" not expected \"%s\"", | |||
821 | me, INFO_STR"info:", line, DEMARK_STR"====== " INFO_STR"info:"); | |||
822 | return 1; | |||
823 | } | |||
824 | tmp = line + strlen(DEMARK_STR"====== " INFO_STR"info:") + strlen(" "); | |||
825 | info = airEnumVal(limnPolyDataInfo, tmp); | |||
826 | if (!info) { | |||
827 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse \"%s\" as %s in %s line \"%s\"", | |||
828 | me, tmp, limnPolyDataInfo->name, INFO_STR"info:", line); | |||
829 | return 1; | |||
830 | } | |||
831 | if (nrrdRead(nrrd, file, NULL((void*)0))) { | |||
832 | biffMovef(LIMNlimnBiffKey, NRRDnrrdBiffKey, "%s: trouble reading %s %s data", | |||
833 | me, INFO_STR"info:", tmp); | |||
834 | airMopError(mop); return 1; | |||
835 | } | |||
836 | switch (info) { | |||
837 | case limnPolyDataInfoRGBA: | |||
838 | wantType = nrrdTypeUChar; | |||
839 | wantSize = 4; | |||
840 | data = pld->rgba; | |||
841 | break; | |||
842 | case limnPolyDataInfoNorm: | |||
843 | wantType = nrrdTypeFloat; | |||
844 | wantSize = 3; | |||
845 | data = pld->norm; | |||
846 | break; | |||
847 | case limnPolyDataInfoTex2: | |||
848 | wantType = nrrdTypeFloat; | |||
849 | wantSize = 2; | |||
850 | data = pld->tex2; | |||
851 | break; | |||
852 | case limnPolyDataInfoTang: | |||
853 | wantType = nrrdTypeFloat; | |||
854 | wantSize = 3; | |||
855 | data = pld->tang; | |||
856 | break; | |||
857 | default: | |||
858 | biffAddf(LIMNlimnBiffKey, "%s: info %d (%s) not handled", me, info, | |||
859 | airEnumStr(limnPolyDataInfo, info)); | |||
860 | airMopError(mop); return 1; | |||
861 | break; | |||
862 | } | |||
863 | if (!(wantType == nrrd->type | |||
864 | && 2 == nrrd->dim | |||
865 | && wantSize == nrrd->axis[0].size | |||
866 | && vertNum == nrrd->axis[1].size)) { | |||
867 | biffAddf(LIMNlimnBiffKey, "%s: didn't get 2-D %s-type %u-by-%u array " | |||
868 | "(got %u-D %s-type %u-by-%u-by-? array)", me, | |||
869 | airEnumStr(nrrdType, wantType), | |||
870 | wantSize, AIR_CAST(unsigned int, vertNum)((unsigned int)(vertNum)), | |||
871 | nrrd->dim, | |||
872 | airEnumStr(nrrdType, nrrd->type), | |||
873 | AIR_CAST(unsigned int, nrrd->axis[0].size)((unsigned int)(nrrd->axis[0].size)), | |||
874 | AIR_CAST(unsigned int, nrrd->axis[1].size)((unsigned int)(nrrd->axis[1].size))); | |||
875 | airMopError(mop); return 1; | |||
876 | } | |||
877 | /* now copy the data */ | |||
878 | memcpy(data, nrrd->data, nrrdElementSize(nrrd)*nrrdElementNumber(nrrd))__builtin___memcpy_chk (data, nrrd->data, nrrdElementSize( nrrd)*nrrdElementNumber(nrrd), __builtin_object_size (data, 0 )); | |||
879 | } | |||
880 | } | |||
881 | ||||
882 | airMopOkay(mop); | |||
883 | nrrdStateVerboseIO = hackhack; | |||
884 | return 0; | |||
885 | } | |||
886 | ||||
887 | int | |||
888 | _limnHestPolyDataLMPDParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE(1024+1)]) { | |||
889 | static const char me[] = "_limnHestPolyDataLMPDParse"; | |||
890 | char *nerr; | |||
891 | limnPolyData **lpldP; | |||
892 | airArray *mop; | |||
893 | FILE *file; | |||
894 | ||||
895 | if (!(ptr && str)) { | |||
896 | sprintf(err, "%s: got NULL pointer", me)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s: got NULL pointer", me); | |||
897 | return 1; | |||
898 | } | |||
899 | ||||
900 | lpldP = (limnPolyData **)ptr; | |||
901 | if (!strlen(str)) { | |||
902 | /* got empty filename; user didn't really want data, that's okay*/ | |||
903 | *lpldP = NULL((void*)0); | |||
904 | return 0; | |||
905 | } | |||
906 | ||||
907 | mop = airMopNew(); | |||
908 | if (!( file = airFopen(str, stdin__stdinp, "rb") )) { | |||
909 | sprintf(err, "%s: couldn't fopen(\"%s\",\"rb\"): %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s: couldn't fopen(\"%s\",\"rb\"): %s", me , str, strerror((*__error()))) | |||
910 | me, str, strerror(errno))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s: couldn't fopen(\"%s\",\"rb\"): %s", me , str, strerror((*__error()))); | |||
911 | biffAdd(LIMNlimnBiffKey, err); airMopError(mop); return 1; | |||
912 | } | |||
913 | airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); | |||
914 | *lpldP = limnPolyDataNew(); | |||
915 | airMopAdd(mop, *lpldP, (airMopper)limnPolyDataNix, airMopOnError); | |||
916 | if (limnPolyDataReadLMPD(*lpldP, file)) { | |||
917 | airMopAdd(mop, nerr = biffGetDone(LIMNlimnBiffKey), airFree, airMopOnError); | |||
918 | airStrcpy(err, AIR_STRLEN_HUGE(1024+1), nerr); | |||
919 | airMopError(mop); | |||
920 | return 1; | |||
921 | } | |||
922 | airMopOkay(mop); | |||
923 | return 0; | |||
924 | } | |||
925 | ||||
926 | hestCB | |||
927 | _limnHestPolyDataLMPD = { | |||
928 | sizeof(limnPolyData *), | |||
929 | "polydata", | |||
930 | _limnHestPolyDataLMPDParse, | |||
931 | (airMopper)limnPolyDataNix | |||
932 | }; | |||
933 | ||||
934 | hestCB * | |||
935 | limnHestPolyDataLMPD = &_limnHestPolyDataLMPD; | |||
936 | ||||
937 | int | |||
938 | _limnHestPolyDataOFFParse(void *ptr, char *str, char err[AIR_STRLEN_HUGE(1024+1)]) { | |||
939 | static const char me[] = "_limnHestPolyDataOFFParse"; | |||
940 | char *nerr; | |||
941 | limnPolyData **lpldP; | |||
942 | airArray *mop; | |||
943 | FILE *file; | |||
944 | ||||
945 | if (!(ptr && str)) { | |||
946 | sprintf(err, "%s: got NULL pointer", me)__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s: got NULL pointer", me); | |||
947 | return 1; | |||
948 | } | |||
949 | ||||
950 | lpldP = (limnPolyData **)ptr; | |||
951 | if (!strlen(str)) { | |||
952 | /* got empty filename; user didn't really want data, that's okay*/ | |||
953 | *lpldP = NULL((void*)0); | |||
954 | return 0; | |||
955 | } | |||
956 | ||||
957 | mop = airMopNew(); | |||
958 | if (!( file = airFopen(str, stdin__stdinp, "rb") )) { | |||
959 | sprintf(err, "%s: couldn't fopen(\"%s\",\"rb\"): %s",__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s: couldn't fopen(\"%s\",\"rb\"): %s", me , str, strerror((*__error()))) | |||
960 | me, str, strerror(errno))__builtin___sprintf_chk (err, 0, __builtin_object_size (err, 2 > 1 ? 1 : 0), "%s: couldn't fopen(\"%s\",\"rb\"): %s", me , str, strerror((*__error()))); | |||
961 | airMopError(mop); return 1; | |||
962 | } | |||
963 | airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); | |||
964 | *lpldP = limnPolyDataNew(); | |||
965 | airMopAdd(mop, *lpldP, (airMopper)limnPolyDataNix, airMopOnError); | |||
966 | if (limnPolyDataReadOFF(*lpldP, file)) { | |||
967 | airMopAdd(mop, nerr = biffGetDone(LIMNlimnBiffKey), airFree, airMopOnError); | |||
968 | strncpy(err, nerr, AIR_STRLEN_HUGE-1)__builtin___strncpy_chk (err, nerr, (1024+1)-1, __builtin_object_size (err, 2 > 1 ? 1 : 0)); | |||
969 | airMopError(mop); | |||
970 | return 1; | |||
971 | } | |||
972 | airMopOkay(mop); | |||
973 | return 0; | |||
974 | } | |||
975 | ||||
976 | hestCB | |||
977 | _limnHestPolyDataOFF = { | |||
978 | sizeof(limnPolyData *), | |||
979 | "polydata", | |||
980 | _limnHestPolyDataOFFParse, | |||
981 | (airMopper)limnPolyDataNix | |||
982 | }; | |||
983 | ||||
984 | hestCB * | |||
985 | limnHestPolyDataOFF = &_limnHestPolyDataOFF; | |||
986 | ||||
987 | int | |||
988 | limnPolyDataWriteVTK(FILE *file, const limnPolyData *pld) { | |||
989 | static const char me[]="limnPolyDataWriteVTK"; | |||
990 | unsigned int pntIdx, prmIdx, *indx, idxNum; | |||
991 | int linesOnly; | |||
992 | ||||
993 | if (!(file && pld)) { | |||
994 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
995 | return 1; | |||
996 | } | |||
997 | fprintf(file, "# vtk DataFile Version 2.0\n"); | |||
998 | fprintf(file, "limnPolyData\n"); | |||
999 | fprintf(file, "ASCII\n"); | |||
1000 | fprintf(file, "DATASET POLYDATA\n"); | |||
1001 | fprintf(file, "POINTS %u float\n", pld->xyzwNum); | |||
1002 | for (pntIdx=0; pntIdx<pld->xyzwNum; pntIdx++) { | |||
1003 | float xyz[3]; | |||
1004 | ELL_34V_HOMOG(xyz, pld->xyzw + 4*pntIdx)((xyz)[0] = (pld->xyzw + 4*pntIdx)[0]/(pld->xyzw + 4*pntIdx )[3], (xyz)[1] = (pld->xyzw + 4*pntIdx)[1]/(pld->xyzw + 4*pntIdx)[3], (xyz)[2] = (pld->xyzw + 4*pntIdx)[2]/(pld-> xyzw + 4*pntIdx)[3]); | |||
1005 | fprintf(file, "%f %f %f\n", xyz[0], xyz[1], xyz[2]); | |||
1006 | } | |||
1007 | ||||
1008 | fprintf(file, "\n"); | |||
1009 | ||||
1010 | /* first check if its only lines... */ | |||
1011 | linesOnly = AIR_TRUE1; | |||
1012 | for (prmIdx=0; prmIdx<pld->primNum; prmIdx++) { | |||
1013 | linesOnly &= (limnPrimitiveLineStrip == pld->type[prmIdx]); | |||
1014 | } | |||
1015 | if (linesOnly) { | |||
1016 | fprintf(file, "LINES %u %u\n", pld->primNum, pld->primNum + pld->indxNum); | |||
1017 | indx = pld->indx; | |||
1018 | for (prmIdx=0; prmIdx<pld->primNum; prmIdx++) { | |||
1019 | unsigned int ii; | |||
1020 | idxNum = pld->icnt[prmIdx]; | |||
1021 | fprintf(file, "%u", idxNum); | |||
1022 | for (ii=0; ii<idxNum; ii++) { | |||
1023 | fprintf(file, " %u", indx[ii]); | |||
1024 | } | |||
1025 | fprintf(file, "\n"); | |||
1026 | indx += idxNum; | |||
1027 | } | |||
1028 | } else { | |||
1029 | indx = pld->indx; | |||
1030 | for (prmIdx=0; prmIdx<pld->primNum; prmIdx++) { | |||
1031 | unsigned int triNum, triIdx; | |||
1032 | idxNum = pld->icnt[prmIdx]; | |||
1033 | switch (pld->type[prmIdx]) { | |||
1034 | case limnPrimitiveTriangleFan: | |||
1035 | biffAddf(LIMNlimnBiffKey, "%s: %s prims (prim[%u]) not supported in VTK?", | |||
1036 | me, airEnumStr(limnPrimitive, pld->type[prmIdx]), prmIdx); | |||
1037 | return 1; | |||
1038 | break; | |||
1039 | case limnPrimitiveQuads: | |||
1040 | case limnPrimitiveTriangleStrip: | |||
1041 | biffAddf(LIMNlimnBiffKey, "%s: sorry, saving %s prims (prim[%u]) not implemented", | |||
1042 | me, airEnumStr(limnPrimitive, pld->type[prmIdx]), prmIdx); | |||
1043 | return 1; | |||
1044 | break; | |||
1045 | case limnPrimitiveLineStrip: | |||
1046 | biffAddf(LIMNlimnBiffKey, "%s: confusion", me); | |||
1047 | return 1; | |||
1048 | break; | |||
1049 | case limnPrimitiveTriangles: | |||
1050 | triNum = idxNum/3; | |||
1051 | fprintf(file, "POLYGONS %u %u\n", triNum, triNum + idxNum); | |||
1052 | for (triIdx=0; triIdx<triNum; triIdx++) { | |||
1053 | fprintf(file, "3 %u %u %u\n", | |||
1054 | indx[0 + 3*triIdx], indx[1 + 3*triIdx], indx[2 + 3*triIdx]); | |||
1055 | } | |||
1056 | break; | |||
1057 | default: | |||
1058 | biffAddf(LIMNlimnBiffKey, "%s: sorry, type %s (prim %u) not handled here", me, | |||
1059 | airEnumStr(limnPrimitive, pld->type[prmIdx]), prmIdx); | |||
1060 | return 1; | |||
1061 | break; | |||
1062 | } | |||
1063 | fprintf(file, "\n"); | |||
1064 | indx += idxNum; | |||
1065 | } | |||
1066 | } | |||
1067 | ||||
1068 | return 0; | |||
1069 | } | |||
1070 | ||||
1071 | /* | |||
1072 | ******** limnPolyDataReadOFF | |||
1073 | ** | |||
1074 | ** HEY: this has to be re-written with different allocation strategies | |||
1075 | ** if it is to support anything other than a single limnPrimitiveTriangles | |||
1076 | */ | |||
1077 | int | |||
1078 | limnPolyDataReadOFF(limnPolyData *pld, FILE *file) { | |||
1079 | static const char me[]="limnPolyDataReadOFF"; | |||
1080 | char line[AIR_STRLEN_LARGE(512+1)]; /* HEY: bad Gordon */ | |||
1081 | unsigned int num[3], xyzwNum, xyzwGot, | |||
1082 | faceNum, faceGot, lineCount, got, lret; | |||
1083 | ||||
1084 | if (!( pld && file )) { | |||
1085 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
1086 | return 1; | |||
1087 | } | |||
1088 | ||||
1089 | /* HEY: this just snarfs lines until it parses 3 uints, | |||
1090 | disregarding whether the "OFF" magic was actually there! */ | |||
1091 | got = 0; | |||
1092 | lineCount = 0; | |||
1093 | do { | |||
1094 | if (!airOneLine(file, line, AIR_STRLEN_LARGE(512+1))) { | |||
1095 | biffAddf(LIMNlimnBiffKey, "%s: hit EOF before getting #vert #face #edge line", me); | |||
1096 | return 1; | |||
1097 | } | |||
1098 | lineCount++; | |||
1099 | got = airParseStrUI(num, line, AIR_WHITESPACE" \t\n\r\v\f", 3); | |||
1100 | } while (3 != got); | |||
1101 | xyzwNum = num[0]; | |||
1102 | faceNum = num[1]; | |||
1103 | ||||
1104 | /* allocate */ | |||
1105 | if (limnPolyDataAlloc(pld, 0 /* no extra info */, | |||
1106 | xyzwNum, 3*faceNum, 1)) { | |||
1107 | biffAddf(LIMNlimnBiffKey, "%s: couldn't allocate", me); | |||
1108 | return 1; | |||
1109 | } | |||
1110 | ||||
1111 | /* read all vertex information */ | |||
1112 | xyzwGot = 0; | |||
1113 | while (xyzwGot < xyzwNum) { | |||
1114 | float *xyzw; | |||
1115 | do { | |||
1116 | lret = airOneLine(file, line, AIR_STRLEN_LARGE(512+1)); | |||
1117 | lineCount++; | |||
1118 | } while (1 == lret); | |||
1119 | if (!lret) { | |||
1120 | biffAddf(LIMNlimnBiffKey, | |||
1121 | "%s: (near line %d) hit EOF trying to read vert %d (of %d)", | |||
1122 | me, lineCount, xyzwGot, xyzwNum); | |||
1123 | return 1; | |||
1124 | } | |||
1125 | xyzw = pld->xyzw + 4*xyzwGot; | |||
1126 | if (3 != airParseStrF(xyzw, line, AIR_WHITESPACE" \t\n\r\v\f", 3)) { | |||
1127 | biffAddf(LIMNlimnBiffKey, "%s: couldn't parse 3 floats from \"%s\" " | |||
1128 | "for vert %d (of %d)", | |||
1129 | me, line, xyzwGot, xyzwNum); | |||
1130 | return 1; | |||
1131 | } | |||
1132 | xyzw[3] = 1.0; | |||
1133 | xyzwGot++; | |||
1134 | } | |||
1135 | ||||
1136 | /* read face information */ | |||
1137 | faceGot = 0; | |||
1138 | while (faceGot < faceNum) { | |||
1139 | unsigned int *indx, indxSingle[4], indxNum; | |||
1140 | do { | |||
1141 | lret = airOneLine(file, line, AIR_STRLEN_LARGE(512+1)); | |||
1142 | lineCount++; | |||
1143 | } while (1 == lret); | |||
1144 | if (!lret) { | |||
1145 | biffAddf(LIMNlimnBiffKey, | |||
1146 | "%s: (near line %d) hit EOF trying to read face %d (of %d)", | |||
1147 | me, lineCount, faceGot, faceNum); | |||
1148 | return 1; | |||
1149 | } | |||
1150 | if ('#' == line[0]) { | |||
1151 | /* its some kind of comment, either LIMN BEGIN PART or otherwise */ | |||
1152 | continue; | |||
1153 | } | |||
1154 | if (1 != sscanf(line, "%u", &indxNum)) { | |||
1155 | biffAddf(LIMNlimnBiffKey, "%s: (near line %d) can't get first uint " | |||
1156 | "(#verts) from \"%s\" for face %d (of %d)", | |||
1157 | me, lineCount, line, faceGot, faceNum); | |||
1158 | return 1; | |||
1159 | } | |||
1160 | if (3 != indxNum) { | |||
1161 | biffAddf(LIMNlimnBiffKey, "%s: sorry, can only handle triangles (not %u verts)", | |||
1162 | me, indxNum); | |||
1163 | return 1; | |||
1164 | } | |||
1165 | if (indxNum+1 != airParseStrUI(indxSingle, line, | |||
1166 | AIR_WHITESPACE" \t\n\r\v\f", indxNum+1)) { | |||
1167 | biffAddf(LIMNlimnBiffKey, "%s: (near line %d) couldn't parse %d uints from \"%s\" " | |||
1168 | "for face %d (of %d)", | |||
1169 | me, lineCount, indxNum+1, line, faceGot, faceNum); | |||
1170 | return 1; | |||
1171 | } | |||
1172 | indx = pld->indx + 3*faceGot; | |||
1173 | ELL_3V_SET(indx, indxSingle[1], indxSingle[2], indxSingle[3])((indx)[0] = (indxSingle[1]), (indx)[1] = (indxSingle[2]), (indx )[2] = (indxSingle[3])); | |||
1174 | /* for now ignoring the color information */ | |||
1175 | faceGot++; | |||
1176 | } | |||
1177 | ||||
1178 | /* set remaining info */ | |||
1179 | pld->type[0] = limnPrimitiveTriangles; | |||
1180 | pld->icnt[0] = 3*faceNum; | |||
1181 | ||||
1182 | return 0; | |||
1183 | } | |||
1184 | ||||
1185 | int | |||
1186 | limnPolyDataSave(const char *_fname, const limnPolyData *lpld) { | |||
1187 | static const char me[]="limnPolyDataSave"; | |||
1188 | char *fname; | |||
1189 | FILE *file; | |||
1190 | airArray *mop; | |||
1191 | int ret; | |||
1192 | ||||
1193 | if (!(_fname && lpld)) { | |||
1194 | biffAddf(LIMNlimnBiffKey, "%s: got NULL pointer", me); | |||
1195 | return 1; | |||
1196 | } | |||
1197 | mop = airMopNew(); | |||
1198 | ||||
1199 | if (!( file = airFopen(_fname, stdout__stdoutp, "wb") )) { | |||
1200 | biffAddf(LIMNlimnBiffKey, "%s: couldn't fopen(\"%s\",\"wb\"): %s", | |||
1201 | me, _fname, strerror(errno(*__error()))); | |||
1202 | airMopError(mop); return 1; | |||
1203 | } | |||
1204 | airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); | |||
1205 | ||||
1206 | fname = airToLower(airStrdup(_fname)); | |||
1207 | airMopAdd(mop, fname, (airMopper)airFree, airMopAlways); | |||
1208 | if (airEndsWith(fname, ".vtk")) { | |||
1209 | ret = limnPolyDataWriteVTK(file, lpld); | |||
1210 | } else if (airEndsWith(fname, ".iv")) { | |||
1211 | ret = limnPolyDataWriteIV(file, lpld); | |||
1212 | } else { | |||
1213 | if (strcmp(_fname, "-") && !airEndsWith(fname, ".lmpd")) { | |||
1214 | fprintf(stderr__stderrp, "%s: WARNING: unknown or no suffix on \"%s\"; " | |||
1215 | "using LMPD format", me, _fname); | |||
1216 | } | |||
1217 | ret = limnPolyDataWriteLMPD(file, lpld); | |||
1218 | } | |||
1219 | if (ret) { | |||
1220 | biffAddf(LIMNlimnBiffKey, "%s: trouble", me); | |||
1221 | airMopError(mop); return 1; | |||
1222 | } | |||
1223 | ||||
1224 | airMopOkay(mop); | |||
1225 | return 0; | |||
1226 | } |