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