1 /* Copyright (C) 1992-1998 The Geometry Center
2 * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3 *
4 * This file is part of Geomview.
5 *
6 * Geomview is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Geomview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Geomview; see the file COPYING. If not, write
18 * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19 * USA, or visit http://www.gnu.org.
20 */
21
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #if 0
27 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
28 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
29 #endif
30
31
32 /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
33
34 /*
35 * Load a NPolyList object from an "nOFF"-format file.
36 *
37 */
38
39 #include <string.h>
40 #include "npolylistP.h"
41
42 #define SIZEOF_CMAP 256
43 static ColorA *colormap;
44
45 static void
LoadCmap(char * file)46 LoadCmap(char *file)
47 {
48 IOBFILE *fp;
49 colormap = OOGLNewNE(ColorA, 256, "PolyList colormap");
50 if((file = findfile(NULL, file)) != NULL &&
51 (fp = iobfopen(file,"r")) != NULL) {
52 iobfgetnf(fp, SIZEOF_CMAP*4, (float *)colormap, 0);
53 iobfclose(fp);
54 }
55 }
56
57 NPolyList *
NPolyListFLoad(IOBFILE * file,char * fname)58 NPolyListFLoad(IOBFILE *file, char *fname)
59 {
60 NPolyList *pl;
61 Vertex **vp;
62 int edges;
63 int i;
64 float *v;
65 int binary = 0;
66 int headerseen = 0;
67 int flags = 0;
68 char *token;
69 int dimn = 3, pdim;
70 static ColorA black = { 0,0,0,0 };
71 vvec vi;
72
73 if (file == NULL)
74 return NULL;
75
76 token = GeomToken(file);
77 if(strncmp(token, "ST", 2) == 0) {
78 flags |= PL_HASST;
79 token += 2;
80 }
81 if(*token == 'C') {
82 flags = PL_HASVCOL; /* Per-vertex colors */
83 token++;
84 }
85 if(*token == '4') {
86 dimn = 4;
87 token++;
88 }
89 if(*token == 'S') { /* "smooth surface": we compute vtx normals */
90 /* ??? normals ??? */
91 token++;
92 }
93 if(strcmp(token, "nOFF") == 0) {
94 headerseen = 1;
95 if(iobfgetni(file, 1, &pdim, binary) == 0) {
96 OOGLSyntax(file, "nOFF %s: expected dimension", fname);
97 return NULL;
98 }
99 if (pdim < 4) {
100 OOGLSyntax(file, "nOFF %s: dimension %d must be > 4", fname, pdim);
101 return NULL;
102 }
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 {
110 return NULL;
111 }
112
113
114 pl = OOGLNewE(NPolyList, "NPolyListFLoad NPolyList");
115 memset(pl, 0, sizeof(NPolyList));
116 GGeomInit(pl, NPolyListMethods(), NPLMAGIC, NULL);
117
118 pl->geomflags = flags | ((dimn == 4) ? VERT_4D : 0);
119
120 #if 0
121 /* wrong: the Ndim number of the nOFF and 4nOFF file formats does
122 _NOT_ include the homogeneous component */
123 pl->pdim = pdim + (dimn == 4 ? 0 : 1);
124 #else
125 pl->pdim = pdim + 1;
126 pdim += dimn == 4; /* number of coordinates specified in OFF file */
127 #endif
128
129
130 if(iobfgetni(file, 1, &pl->n_verts, binary) <= 0 ||
131 iobfgetni(file, 1, &pl->n_polys, binary) <= 0 ||
132 iobfgetni(file, 1, &edges, binary) <= 0) {
133 if(headerseen)
134 OOGLSyntax(file,
135 "PolyList %s: Bad vertex/face/edge counts", fname);
136 goto bogus;
137 }
138 VVINIT(vi, int, 5*pl->n_polys);
139
140 pl->v = OOGLNewNE(HPtNCoord, pl->n_verts*pl->pdim, "NPolyListFLoad vertices");
141 pl->vl = OOGLNewNE(Vertex, pl->n_verts, "NPolyListFLoad vertex descriptions");
142 if(pl->geomflags & PL_HASVCOL)
143 pl->vcol = OOGLNewNE(ColorA, pl->n_verts, "NPolyListFLoad vertex colors");
144
145 for(v = pl->v, i = 0; i < pl->n_verts; v += pl->pdim, i++) {
146 if(iobfgetnf(file, pdim, v + (pdim != pl->pdim ? 1 : 0), binary) < pdim ||
147 ((flags & PL_HASVCOL) &&
148 iobfgetnf(file, 4, (float *)&pl->vcol[i], binary) < 4) ||
149 ((flags & PL_HASST) &&
150 iobfgetnf(file, 2, (float *)&pl->vl[i].st, binary) < 2)) {
151 OOGLSyntax(file, "nOFF %s: Bad vertex %d (of %d)",
152 fname, i, pl->n_verts);
153 goto bogus;
154 }
155 if (flags & PL_HASVCOL) {
156 pl->vl[i].vcol = pl->vcol[i];
157 if (pl->vcol[i].a != 1.0) {
158 pl->geomflags |= COLOR_ALPHA;
159 }
160 }
161 if (dimn == 3) v[0] = 1.0;
162 }
163 if (flags & PL_HASVCOL) { /* vcol and vl[].vcol are in sync */
164 pl->geomflags |= NPL_HASVLVCOL;
165 }
166
167 pl->pv = OOGLNewNE(int, pl->n_polys, "NPolyListFLoad polygon vertices");
168 pl->p = OOGLNewNE(Poly, pl->n_polys, "NPolyListFLoad polygons");
169 for(i = 0; i < pl->n_polys; ++i) {
170 Poly *p;
171 int k, index;
172
173 p = &pl->p[i];
174 if(iobfgetni(file, 1, &p->n_vertices, binary) <= 0 || p->n_vertices <= 0) {
175 OOGLSyntax(file, "PolyList %s: bad %d'th polygon (of %d)",
176 fname, i, pl->n_polys);
177 goto bogus_face;
178 }
179 pl->pv[i] = VVCOUNT(vi);
180 VVCOUNT(vi) += p->n_vertices;
181 vvneeds(&vi, VVCOUNT(vi));
182
183 for(k = 0; k < p->n_vertices; k++) {
184 int index;
185
186 if(iobfgetni(file, 1, &index, binary) <= 0 ||
187 index < 0 || index >= pl->n_verts) {
188 OOGLSyntax(file, "PolyList: %s: bad index %d on %d'th polygon (of %d)",
189 fname, index, i, p->n_vertices);
190 goto bogus_face;
191 }
192 VVEC(vi, int)[pl->pv[i]+k] = index;
193 }
194
195 /* Pick up the color, if any.
196 * In ASCII format, take whatever's left before end-of-line
197 */
198 p->pcol = black;
199 if(binary) {
200 int ncol;
201
202 if(iobfgetni(file, 1, &ncol, 1) <= 0
203 || iobfgetnf(file, ncol, (float *)&p->pcol, 1) < ncol)
204 goto bogus_face_color;
205 k = ncol;
206 } else {
207 for(k = 0; k < 4 && iobfnextc(file, 1) != '\n'; k++) {
208 if(iobfgetnf(file, 1, ((float *)(&p->pcol))+k, 0) < 1)
209 goto bogus_face_color;
210 }
211 }
212
213 if((flags & PL_HASVCOL) == 0) {
214 if(k > 0)
215 pl->geomflags |= PL_HASPCOL;
216
217 if(k != 1 && (p->pcol.r>1||p->pcol.g>1||p->pcol.b>1||p->pcol.a>1)) {
218 p->pcol.r /= 255, p->pcol.g /= 255,
219 p->pcol.b /= 255, p->pcol.a /= 255;
220 }
221
222 switch(k) {
223 case 0:
224 p->pcol.r = 170/255.0; /* Gray */
225 p->pcol.g = p->pcol.r;
226 case 2:
227 p->pcol.b = p->pcol.g;
228 case 3:
229 p->pcol.a = 170/255.0; /* Semitransparent */
230 break;
231 case 1: /* use colormap */
232 if ( colormap == NULL )
233 LoadCmap("cmap.fmap");
234 index = p->pcol.r;
235 if((unsigned)index >= SIZEOF_CMAP) index = 0;
236 p->pcol = colormap[index];
237 } /* case 4, all components supplied */
238 }
239 if ((pl->geomflags & PL_HASPCOL) && p->pcol.a != 1.0) {
240 pl->geomflags |= COLOR_ALPHA;
241 }
242 }
243
244 /* Hand the list of vertex-indices on to the new object */
245 vvtrim(&vi);
246 pl->nvi = VVCOUNT(vi);
247 pl->vi = VVEC(vi, int);
248
249 /* Now generate the necessary information for pl->p[], i.e. insert
250 * the pointers to the 3d vertices in the proper places; there
251 * really is no need to do this evertime again and again when
252 * drawing the object.
253 */
254 vp = OOGLNewNE(Vertex *, pl->nvi, "NPolyList 3d connectivity");
255 for (i = 0; i < pl->n_polys; i++) {
256 Poly *p = &pl->p[i];
257 int k;
258
259 p->v = vp;
260 vp += p->n_vertices;
261
262 for (k = 0; k < p->n_vertices; k++) {
263 p->v[k] = &pl->vl[pl->vi[pl->pv[i]+k]];
264 }
265 }
266
267 return pl;
268
269 bogus_face_color:
270 OOGLSyntax(file, "PolyList %s: bad face color on face %d (of %d)",
271 fname, i, pl->n_polys);
272 bogus_face:
273 pl->n_polys = i;
274 bogus:
275 GeomDelete((Geom *)pl);
276 return NULL;
277 }
278
279 /*
280 * Local Variables: ***
281 * c-basic-offset: 2 ***
282 * End: ***
283 */
284