1 /* Copyright (C) 1992-1998 The Geometry Center
2 * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3 * Copyright (C) 2006 Claus-Justus Heine
4 *
5 * This file is part of Geomview.
6 *
7 * Geomview is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * Geomview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Geomview; see the file COPYING. If not, write
19 * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
20 * USA, or visit http://www.gnu.org.
21 */
22
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #if 0
28 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
29 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
30 #endif
31
32
33 /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
34
35 /*
36 * Load a PolyList object from an "off"-format file.
37 *
38 */
39
40 #include <string.h>
41 #include <stdlib.h>
42 #include "polylistP.h"
43
44 #define SIZEOF_CMAP 256
45 static ColorA *colormap;
46
47 static void
LoadCmap(char * file)48 LoadCmap(char *file)
49 {
50 IOBFILE *fp;
51
52 colormap = OOGLNewNE(ColorA, 256, "PolyList colormap");
53 if((file = findfile(NULL, file)) != NULL &&
54 (fp = iobfopen(file,"r")) != NULL) {
55 iobfgetnf(fp, SIZEOF_CMAP*4, (float *)colormap, 0);
56 iobfclose(fp);
57 }
58 }
59
60 PolyList *
PolyListFLoad(IOBFILE * file,char * fname)61 PolyListFLoad(IOBFILE *file, char *fname)
62 {
63 PolyList *pl;
64 int edges;
65 int i;
66 char *token;
67 Vertex *v;
68 int binary = 0;
69 int preread = 0;
70 int headerseen = 0;
71 int flags = 0;
72 bool makenorm = false;
73 int dimn = 3;
74 static ColorA black = { 0,0,0,0 };
75
76 if (file == NULL)
77 return NULL;
78
79 token = GeomToken(file);
80
81 if(strncmp(token, "ST", 2) == 0) {
82 flags |= PL_HASST;
83 token += 2;
84 }
85 if(*token == 'C') {
86 flags |= PL_HASVCOL; /* Per-vertex colors */
87 token++;
88 }
89 if(*token == 'N') {
90 flags |= PL_HASVN; /* Per-vertex normals */
91 token++;
92 }
93 if(*token == '4') {
94 dimn = 4;
95 token++;
96 }
97 if(*token == 'S') { /* "smooth surface": we compute vtx normals */
98 makenorm = true;
99 token++;
100 }
101 if(strcmp(token, "OFF") == 0) {
102 headerseen = 1;
103 if(iobfnextc(file, 1) == 'B' && iobfexpectstr(file, "BINARY") == 0) {
104 binary = 1;
105 if(iobfnextc(file, 1) != '\n') /* Expect \n after BINARY */
106 return NULL;
107 (void) iobfgetc(file); /* Toss \n */
108 }
109 } else { /* Hack, in case first token was a number */
110 if(dimn == 4)
111 token--;
112 preread = strtol(token, &token, 10);
113 if(*token != '\0')
114 return NULL;
115 /* May be a header-less OFF */
116 flags = 0;
117 dimn = 3;
118 }
119
120 pl = OOGLNewE(PolyList, "PolyListFLoad PolyList");
121 GGeomInit(pl, PolyListMethods(), PLMAGIC, NULL);
122 pl->p = NULL;
123 pl->vl = NULL;
124 pl->n_verts = preread; /* In case prefetched token was our vert count */
125 pl->geomflags = flags | ((dimn == 4) ? VERT_4D : 0);
126 pl->pdim = 4;
127 pl->plproj = NULL;
128
129 if((!preread && iobfgetni(file, 1, &pl->n_verts, binary) <= 0) ||
130 iobfgetni(file, 1, &pl->n_polys, binary) <= 0 ||
131 iobfgetni(file, 1, &edges, binary) <= 0) {
132 if(headerseen)
133 OOGLSyntax(file, "PolyList %s: Bad vertex/face/edge counts", fname);
134 goto bogus;
135 }
136
137 pl->vl = OOGLNewNE(Vertex, pl->n_verts, "PolyListFLoad vertices");
138
139 for(v = pl->vl, i = 0; i < pl->n_verts; v++, i++) {
140 if((iobfgetnf(file, dimn, (float *)&v->pt, binary) < dimn)
141 ||
142 (flags & PL_HASVN && iobfgetnf(file, 3, (float *)&v->vn, binary) < 3)
143 ||
144 (flags & PL_HASVCOL && iobfgetnf(file, 4, (float *)&v->vcol, binary) < 4)
145 ||
146 (flags & PL_HASST && iobfgetnf(file, 2, (float *)&v->st, binary) < 2)
147 ) {
148 OOGLSyntax(file, "PolyList %s: Bad vertex %d (of %d)", fname, i, pl->n_verts);
149 goto bogus;
150 }
151 if (dimn == 3) v->pt.w = 1.0;
152 if ((flags & PL_HASVCOL) && v->vcol.a != 1.0) {
153 pl->geomflags |= COLOR_ALPHA;
154 }
155 }
156
157 pl->p = OOGLNewNE(Poly, pl->n_polys, "PolyListFLoad polygons");
158 for(i = 0; i < pl->n_polys; ) {
159 Poly *p;
160 int k,index;
161
162 p = &pl->p[i];
163 if(iobfgetni(file, 1, &p->n_vertices, binary) <= 0 || p->n_vertices <= 0) {
164 OOGLSyntax(file, "PolyList %s: bad %d'th polygon (of %d)",
165 fname, i, pl->n_polys);
166 goto bogus_face;
167 }
168 p->v = OOGLNewNE(Vertex *, p->n_vertices, "PolyListFLoad polygon");
169 i++;
170
171 for(k = 0; k < p->n_vertices; k++) {
172 int index;
173
174 if(iobfgetni(file, 1, &index, binary) <= 0 ||
175 index < 0 || index >= pl->n_verts) {
176 OOGLSyntax(file, "PolyList: %s: bad index %d on %d'th polygon (of %d)",
177 fname, index, i, p->n_vertices);
178 goto bogus_face;
179 }
180 p->v[k] = &pl->vl[index];
181 }
182
183 /* Pick up the color, if any.
184 * In ASCII format, take whatever's left before end-of-line
185 * (or end-of-file, or close-brace)
186 */
187 p->pcol = black;
188 if(binary) {
189 int ncol;
190
191 if(iobfgetni(file, 1, &ncol, 1) <= 0
192 || iobfgetnf(file, ncol, (float *)&p->pcol, 1) < ncol)
193 goto bogus_face_color;
194 k = ncol;
195 } else {
196 int c;
197 for(k = 0; k < 4 &&
198 (c = iobfnextc(file, 1)) != '\n' && c!='}' && c!=EOF; k++) {
199 if(iobfgetnf(file, 1, ((float *)(&p->pcol))+k, 0) < 1) {
200 goto bogus_face_color;
201 }
202 }
203 }
204
205 if(true || (flags & PL_HASVCOL) == 0) {
206 if(k > 0)
207 pl->geomflags |= PL_HASPCOL;
208
209 if(k != 1 && (p->pcol.r>1||p->pcol.g>1||p->pcol.b>1||p->pcol.a>1)) {
210 p->pcol.r /= 255, p->pcol.g /= 255,
211 p->pcol.b /= 255, p->pcol.a /= 255;
212 }
213
214 switch(k) {
215 case 0:
216 p->pcol.r = 170/255.0; /* Gray */
217 p->pcol.g = p->pcol.r;
218 case 2:
219 p->pcol.b = p->pcol.g;
220 case 3:
221 p->pcol.a = 170/255.0; /* Semitransparent */
222 break;
223 case 1: /* use colormap */
224 if ( colormap == NULL )
225 LoadCmap("cmap.fmap");
226 index = p->pcol.r;
227 if((unsigned)index >= SIZEOF_CMAP) index = 0;
228 p->pcol = colormap[index];
229 } /* case 4, all components supplied */
230 }
231
232 if ((pl->geomflags & PL_HASPCOL) && p->pcol.a != 1.0) {
233 pl->geomflags |= COLOR_ALPHA;
234 }
235 }
236
237 if(makenorm && !(flags & PL_HASVN)) {
238 pl->geomflags |= PL_HASVN; /* ???? where ???? */
239 }
240 return pl;
241
242
243 bogus_face_color:
244 OOGLSyntax(file, "PolyList %s: bad face color on face %d (of %d)",
245 fname, i, pl->n_polys);
246 bogus_face:
247 pl->n_polys = i;
248 bogus:
249 GeomDelete((Geom *)pl);
250 return NULL;
251 }
252
253 /*
254 * Local Variables: ***
255 * c-basic-offset: 2 ***
256 * End: ***
257 */
258