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