1 /****************************************************************************
2 * VCGLib                                                            o o     *
3 * Visual and Computer Graphics Library                            o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2004-2016                                           \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is Free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 /****************************************************************************
25   History
26 
27  $Log: not supported by cvs2svn $
28  Revision 1.1  2007/02/14 01:20:37  ganovelli
29  working draft of VCG Mesh Image importer and exporter. Does not consider optional attributes. The mesh atributes are only vn and fn (no bbox, texture coordiantes)
30 
31 
32 
33 ****************************************************************************/
34 
35 #ifndef __VCGLIB_IMPORT_VMI
36 #define __VCGLIB_IMPORT_VMI
37 
38 #include <wrap/io_trimesh/io_mask.h>
39 #include <wrap/callback.h>
40 /*
41     VMI VCG Mesh Image.
42     The vmi image file consists of a header containing the description of the vertex and face type,
43     the length of vectors containing vertices of faces and the memory image of the object mesh as it is when
44     passed to the function Save(SaveMeshType m)
45     NOTE: THIS IS NOT A FILE FORMAT. IT IS ONLY USEFUL FOR DUMPING MESH IMAGES FOR DEBUG PURPOSE.
46     Example of use: say you are running a time consuming mesh processing and you want to save intermediate
47     state, but no file format support all the attributes you need in your vertex/face type.
48     NOTE2: At the present if you add members to your TriMesh these will NOT be saved. More precisely, this file and
49     import_vmi must be updated to reflect changes in vcg/complex/trimesh/base.h
50 
51 */
52 
53 namespace vcg {
54 namespace tri {
55 namespace io {
56 
57     template <int N> struct DummyType{ char placeholder[N]; };
58 
59     /* ------------------------- derivation chain for the vertex attribute ---------------------------*/
60 
61     /** this class is for testing only the equality with the type optionally provided by the user when calling Open
62     */
63     template <class MeshType, class A, class T>
64     struct Der:public T{
65         typedef typename std::set<typename MeshType::PointerToAttribute >::iterator HWIte;
66 
67         template <int VoF>
AddAttribDer68         static void AddAttrib(MeshType &m, const char * name, unsigned int s, void * data){
69             switch(VoF)
70             {
71             case 0: if(s == sizeof(A)){
72                     typename MeshType::template PerVertexAttributeHandle<A> h = vcg::tri::Allocator<MeshType>:: template AddPerVertexAttribute<A>(m,name);
73                     for(unsigned int i  = 0; i < m.vert.size(); ++i)
74                         memcpy(&h[i], (void*) &((A*)data)[i],sizeof(A)); // we don't want the type conversion
75                         }
76                     else
77                         T::template AddAttrib<0>(m,name,s,data);
78                 break;
79             case 1: if(s == sizeof(A)){
80                     typename MeshType::template PerFaceAttributeHandle<A> h = vcg::tri::Allocator<MeshType>:: template AddPerFaceAttribute<A>(m,name);
81                     for(unsigned int i  = 0; i < m.face.size(); ++i)
82                         memcpy(&h[i], (void*) &((A*)data)[i],sizeof(A)); // we don't want the type conversion
83                     }
84                     else
85                         T::template AddAttrib<0>(m,name,s,data);
86                 break;
87             case 2:
88                 if(s == sizeof(A)){
89                     typename MeshType::template PerMeshAttributeHandle<A> h = vcg::tri::Allocator<MeshType>:: template AddPerMeshAttribute<A>(m,name);
90                         memcpy(&h(), (void*) ((A*)data),sizeof(A)); // we don't want the type conversion
91                 }
92                     else
93                         T::template AddAttrib<2>(m,name,s,data);
94                 break;
95 
96             default:break;
97             }
98         }
99     };
100 
101     /** this class is for testing the list of increasing size types until one is larger than the size of the unknown type
102     */
103     template <class MeshType, class A, class T>
104     struct DerK:public T{
105         typedef typename std::set<typename MeshType::PointerToAttribute >::iterator HWIte;
106         template <int VoF>
AddAttribDerK107         static void AddAttrib(MeshType &m, const char * name, unsigned int s, void * data){
108             switch(VoF){
109                     case 0:
110                     if(s == sizeof(A)){
111                         typename MeshType::template PerVertexAttributeHandle<A> h = vcg::tri::Allocator<MeshType>::template AddPerVertexAttribute<A>(m,name);
112                         for(unsigned int i  = 0; i < m.vert.size(); ++i)
113                             memcpy((void*) &(h[i]), (void*) &((A*)data)[i],sizeof(A)); // we don't want the type conversion
114                     }
115                     else
116                         if(s < sizeof(A)){
117                             // padding
118                             int padd = sizeof(A) - s;
119                             typename MeshType::template PerVertexAttributeHandle<A> h = vcg::tri::Allocator<MeshType>::template AddPerVertexAttribute<A>(m,name);
120                             for(unsigned int i  = 0; i < m.vert.size(); ++i){
121                                 char * dest =  &((char*)(&h[i]))[0];
122                                 memcpy( (void *)dest , (void*) &((A*)data)[i],s); // we don't want the type conversion
123                             }
124                             typename MeshType::PointerToAttribute pa;
125                             pa._name = std::string(name);
126                             HWIte res = m.vert_attr.find(pa);
127                             pa = *res;
128                             m.vert_attr.erase(res);
129                             pa._padding = padd;
130                             std::pair<HWIte,bool > new_pa = m.vert_attr.insert(pa);
131                             (void)new_pa;
132                             assert(new_pa.second);
133                         }
134                         else
135                             T::template AddAttrib<0>(m,name,s,data);
136                     break;
137                     case 1:
138                         if(s == sizeof(A)){
139                             typename MeshType::template PerVertexAttributeHandle<A> h = vcg::tri::Allocator<MeshType>::template AddPerVertexAttribute<A>(m,name);
140                             for(unsigned int i  = 0; i < m.vert.size(); ++i)
141                             memcpy((void*) &(h[i]), (void*) &((A*)data)[i],sizeof(A)); // we don't want the type conversion
142                             }
143                         else
144                             if(s < sizeof(A)){
145                                 // padding
146                                 int padd = sizeof(A) - s;
147                                 typename MeshType::template PerFaceAttributeHandle<A> h = vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<A>(m,name);
148                                 for(unsigned int i  = 0; i < m.face.size(); ++i){
149                                     char * dest =  &((char*)(&h[i]))[0];
150                                     memcpy( (void *)dest , (void*) &((A*)data)[i],s); // we don't want the type conversion
151                                 }
152                                 typename MeshType::PointerToAttribute pa;
153                                 pa._name = std::string(name);
154                                 HWIte res = m.face_attr.find(pa);
155                                 pa = *res;
156                                 m.face_attr.erase(res);
157                                 pa._padding = padd;
158                                 std::pair<HWIte,bool > new_pa = m.face_attr.insert(pa);
159                                 (void)new_pa;
160                                 assert(new_pa.second);
161                             }
162                         else
163                             T::template AddAttrib<1>(m,name,s,data);
164                         break;
165                     case 2:
166                         if(s == sizeof(A)){
167                             typename MeshType::template PerMeshAttributeHandle<A> h = vcg::tri::Allocator<MeshType>::template AddPerMeshAttribute<A>(m,name);
168                                 memcpy((void*)&h(), (void*)((A*)data),sizeof(A)); // we don't want the type conversion
169                             }
170                         else
171                             if(s < sizeof(A)){
172                                 // padding
173                                 int padd = sizeof(A) - s;
174                                 typename MeshType::template PerMeshAttributeHandle<A> h = vcg::tri::Allocator<MeshType>::template AddPerMeshAttribute<A>(m,name);
175                                 char * dest =  & ((char*)(&h()))[0];
176                                 memcpy( (void *)dest , (void*)((A*)data),s); // we don't want the type conversion
177 
178                                 typename MeshType::PointerToAttribute pa;
179                                 pa._name = std::string(name);
180                                 HWIte res = m.mesh_attr.find(pa);
181                                 pa = *res;
182                                 m.mesh_attr.erase(res);
183                                 pa._padding = padd;
184                                 std::pair<HWIte,bool > new_pa = m.mesh_attr.insert(pa);
185                                 (void)new_pa;
186                                 assert(new_pa.second);
187                             }
188                         else
189                             T::template AddAttrib<2>(m,name,s,data);
190                         break;
191                     default: assert(0);break;
192             }
193         }
194     };
195 
196     /**
197     This is the templated derivation  chain
198     */
199     template <class MeshType>	struct K	{
200         template <int VoF>
AddAttribK201         static void AddAttrib(MeshType &/*m*/, const char * /*name*/, unsigned int /*s*/, void * /*data*/){
202             // if yohu got this your attribute is larger than	1048576. Honestly...
203             assert(0);
204         }
205     };
206 
207     template <class MeshType, class B0 >																												struct K0	: public DerK<  MeshType, B0,	K<MeshType> > {};
208     template <class MeshType, class B0, class B1 >																										struct K1	: public DerK<  MeshType, B1,	K0<MeshType, B0> > {};
209     template <class MeshType, class B0, class B1, class B2 >																							struct K2	: public DerK<  MeshType, B2,	K1<MeshType, B0, B1> > {};
210     template <class MeshType, class B0, class B1, class B2,class B3>																					struct K3	: public DerK<  MeshType, B3,	K2<MeshType, B0, B1, B2> > {};
211     template <class MeshType, class B0, class B1, class B2,class B3,class B4>																			struct K4	: public DerK<  MeshType, B4,	K3<MeshType, B0, B1, B2, B3> > {};
212     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5>																	struct K5	: public DerK<  MeshType, B5,	K4<MeshType, B0, B1, B2, B3, B4> > {};
213     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6>															struct K6	: public DerK<  MeshType, B6,	K5<MeshType, B0, B1, B2, B3, B4, B5> > {};
214     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6,class B7>												struct K7	: public DerK<  MeshType, B7,	K6<MeshType, B0, B1, B2, B3, B4, B5, B6> > {};
215     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6,class B7,class B8>										struct K8	: public DerK<  MeshType, B8,	K7<MeshType, B0, B1, B2, B3, B4, B5, B6, B7> > {};
216     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6,class B7,class B8,class B9>								struct K9	: public DerK<  MeshType, B9,	K8<MeshType, B0, B1, B2, B3, B4, B5, B6, B7, B8> > {};
217     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6,class B7,class B8,class B9,class B10>					struct K10	: public DerK<  MeshType, B10,	K9<MeshType, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9> > {};
218     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6,class B7,class B8,class B9,class B10,class B11>			struct K11	: public DerK<  MeshType, B11,	K10<MeshType, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B11 > > {};
219     template <class MeshType, class B0, class B1, class B2,class B3,class B4,class B5,class B6,class B7,class B8,class B9,class B10,class B11,class B12>struct K12	: public DerK<  MeshType, B12,	K11<MeshType, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B11, B12 > > {};
220 
221     template <class MeshType, class A0,
222         class B0  = DummyType<1048576>,
223         class B1  = DummyType<2048>,
224         class B2  = DummyType<1024>,
225         class B3  = DummyType<512>,
226         class B4  = DummyType<256>,
227         class B5  = DummyType<128>,
228         class B6  = DummyType<64>,
229         class B7  = DummyType<32>,
230         class B8  = DummyType<16>,
231         class B9  = DummyType<8>,
232         class B10 = DummyType<4>,
233         class B11 = DummyType<2>,
234         class B12 = DummyType<1>
235     >	struct C0		: public DerK<  MeshType, A0,    K12<MeshType, B0, B1, B2, B3, B4,B5,B6,B7,B8,B9,B10,B11,B12> > {};
236 
237     template <class MeshType, class A0, class A1>											struct C1		: public Der<  MeshType, A1,	C0<MeshType, A0> > {};
238     template <class MeshType, class A0, class A1, class A2>	 								struct C2		: public Der<  MeshType, A2,	C1<MeshType, A0, A1> > {};
239     template <class MeshType, class A0, class A1, class A2,class A3>	 					struct C3		: public Der<  MeshType, A3,	C2<MeshType, A0, A1, A2> > {};
240     template <class MeshType, class A0, class A1, class A2,class A3,class A4>				struct AttrAll	: public Der<  MeshType, A4,	C3<MeshType, A0, A1, A2, A3> > {};
241 
242 
243 
244     template <class OpenMeshType,class A0 = long, class A1 = double, class A2 = int,class A3 = short, class A4 = char >
245     class ImporterVMI: public AttrAll<OpenMeshType,A0,A1,A2,A3,A4>
246     {
247 
ReadString(std::string & out)248         static void ReadString(std::string & out){
249             unsigned int l; Read(&l,4,1);
250             char * buf = new char[l+1];
251             Read(buf,1,l);buf[l]='\0';
252             out = std::string(buf);
253             delete [] buf;
254             }
255 
ReadInt(unsigned int & i)256         static void ReadInt( unsigned int & i){ Read(&i,1,4);}
ReadFloat(float & v)257         static void ReadFloat( float & v){ Read(&v,1,sizeof(float));}
258 
259 
LoadVertexOcfMask()260          static int   LoadVertexOcfMask( ){
261             int mask  =0;
262             std::string s;
263 
264             // vertex quality
265             ReadString( s);
266             if( s == std::string("HAS_VERTEX_QUALITY_OCF")) mask |= Mask::IOM_VERTQUALITY;
267 
268             // vertex color
269             ReadString( s);
270             if( s == std::string("HAS_VERTEX_COLOR_OCF"))  mask |= Mask::IOM_VERTCOLOR;
271 
272             // vertex normal
273             ReadString( s);
274             if( s == std::string("HAS_VERTEX_NORMAL_OCF")) mask |= Mask::IOM_VERTNORMAL;
275 
276             // vertex mark
277             ReadString( s);
278             //if( s == std::string("HAS_VERTEX_MARK_OCF"))  mask |=
279 
280             // vertex texcoord
281             ReadString( s);
282             if( s == std::string("HAS_VERTEX_TEXCOORD_OCF"))  mask |= Mask::IOM_VERTTEXCOORD;
283 
284             // vertex-face adjacency
285             ReadString( s);
286             //if( s == std::string("HAS_VERTEX_VFADJACENCY_OCF")) mask |=
287 
288             // vertex curvature
289             ReadString( s);
290             //if( s == std::string("HAS_VERTEX_CURVATURE_OCF"))  mask |=
291 
292             //// vertex curvature dir
293             ReadString( s);
294             //if( s == std::string("HAS_VERTEX_CURVATUREDIR_OCF"))  mask |=
295 
296             // vertex radius
297             ReadString( s);
298             if( s == std::string("HAS_VERTEX_RADIUS_OCF"))  mask |= Mask::IOM_VERTRADIUS;
299 
300             return mask;
301        }
302 
303         template <typename MeshType, typename CONT>
304                 struct LoadVertexOcf{
LoadVertexOcfLoadVertexOcf305                         LoadVertexOcf(FILE* /*f*/,const CONT & /*vert*/){
306                                 // do nothing, it is a std::vector
307                         }
308                 };
309 
310 
311 
312         template <typename MeshType>
313         struct
314         LoadVertexOcf<MeshType,vertex::vector_ocf<typename OpenMeshType::VertexType> >{
315                         typedef typename OpenMeshType::VertexType VertexType;
316             LoadVertexOcf( FILE * /*f*/, vertex::vector_ocf<typename OpenMeshType::VertexType> & vert){
317             std::string s;
318 
319                 // vertex quality
320                 ReadString( s);
321                 if( s == std::string("HAS_VERTEX_QUALITY_OCF")) {
322                         vert.EnableQuality();
323                         Read((void*)&vert.QV[0],sizeof(typename VertexType::QualityType),vert.size() );
324                 }
325 
326                 // vertex color
327                 ReadString( s);
328                 if( s == std::string("HAS_VERTEX_COLOR_OCF")) {
329                         vert.EnableColor();
330                         Read((void*)&vert.CV[0],sizeof(typename VertexType::ColorType),vert.size() );
331                 }
332 
333                 // vertex normal
334                 ReadString( s);
335                 if( s == std::string("HAS_VERTEX_NORMAL_OCF")) {
336                         vert.EnableNormal();
337                         Read((void*)&vert.NV[0],sizeof(typename VertexType::NormalType),vert.size() );
338                 }
339 
340                  // vertex mark
341                 ReadString( s);
342                 if( s == std::string("HAS_VERTEX_MARK_OCF")) {
343                         vert.EnableMark();
344                         Read((void*)&vert.MV[0],sizeof(typename VertexType::MarkType),vert.size() );
345                 }
346 
347                 // vertex texcoord
348                 ReadString( s);
349                 if( s == std::string("HAS_VERTEX_TEXCOORD_OCF")) {
350                         vert.EnableTexCoord();
351                         Read((void*)&vert.TV[0],sizeof(typename VertexType::TexCoordType),vert.size() );
352                 }
353 
354                 // vertex-face adjacency
355                 ReadString( s);
356                 if( s == std::string("HAS_VERTEX_VFADJACENCY_OCF")) {
357                         vert.EnableVFAdjacency();
358                         Read((void*)&vert.AV[0],sizeof(typename vertex::vector_ocf<VertexType>::VFAdjType),vert.size() );
359                 }
360 
361                 // vertex curvature
362                 ReadString( s);
363                 if( s == std::string("HAS_VERTEX_CURVATURE_OCF")) {
364                         vert.EnableCurvature();
365                         Read((void*)&vert.CuV[0],sizeof(typename VertexType::CurvatureType),vert.size() );
366                 }
367 
368                 // vertex curvature dir
369                 ReadString( s);
370                 if( s == std::string("HAS_VERTEX_CURVATUREDIR_OCF")) {
371                         vert.EnableCurvatureDir();
372                         Read((void*)&vert.CuDV[0],sizeof(typename VertexType::CurvatureDirType),vert.size() );
373                 }
374 
375                 // vertex radius
376                 ReadString( s);
377                 if( s == std::string("HAS_VERTEX_RADIUS_OCF")) {
378                         vert.EnableRadius();
379                         Read((void*)&vert.RadiusV[0],sizeof(typename VertexType::RadiusType),vert.size() );
380                 }
381 
382                         }
383                 };
384 
385                 template <typename MeshType, typename CONT>
386                 struct LoadFaceOcf{
387                         LoadFaceOcf(const CONT & /* face */){
388                                 // do nothing, it is a std::vector
389                         }
390                 };
391 
392 
393                  static int  LoadFaceOcfMask( ){
394                 int mask=0;
395                     std::string s;
396 
397                 // face quality
398                     ReadString( s);
399                     if( s == std::string("HAS_FACE_QUALITY_OCF"))	mask	|=  Mask::IOM_FACEQUALITY;
400 
401                     // face color
402                     ReadString( s);
403                          if( s == std::string("HAS_FACE_COLOR_OCF"))		mask	|=   Mask::IOM_FACECOLOR;
404 
405                     // face normal
406                     ReadString( s);
407                     if( s == std::string("HAS_FACE_NORMAL_OCF"))  mask	|=  Mask::IOM_FACENORMAL;
408 
409                     //// face mark
410                     ReadString( s);
411                     //if( s == std::string("HAS_FACE_MARK_OCF")) mask	|=
412 
413                     // face wedgetexcoord
414                     ReadString( s);
415                     if( s == std::string("HAS_FACE_WEDGETEXCOORD_OCF")) mask	|= Mask::IOM_WEDGTEXCOORD;
416 
417 
418                     // face-face adjacency
419                     ReadString( s);
420 //                    if( s == std::string("HAS_FACE_FFADJACENCY_OCF")) mask	|= */
421 
422                     // vertex-face adjacency
423                     ReadString( s);
424                     //if( s == std::string("HAS_FACE_VFADJACENCY_OCF")) mask	|=
425 
426                     // face WedgeColor
427                     ReadString( s);
428                     if( s == std::string("HAS_FACE_WEDGECOLOR_OCF")) mask	|=  Mask::IOM_WEDGCOLOR;
429 
430                     // face WedgeNormal
431                     ReadString( s);
432                     if( s == std::string("HAS_FACE_WEDGENORMAL_OCF")) mask	|=  Mask::IOM_WEDGNORMAL;
433                     return mask;
434             }
435 
436 
437                 /* partial specialization for vector_ocf */
438                 template <typename MeshType>
439                                                                 struct LoadFaceOcf< MeshType, face::vector_ocf<typename OpenMeshType::FaceType> >{
440                                                 typedef typename OpenMeshType::FaceType FaceType;
441                         LoadFaceOcf( face::vector_ocf<FaceType> & face){
442                                 std::string s;
443 
444                                 // face quality
445                                 ReadString( s);
446                                 if( s == std::string("HAS_FACE_QUALITY_OCF")) {
447                                         face.EnableQuality();
448                                         Read((void*)&face.QV[0],sizeof(typename FaceType::QualityType),face.size() );
449                                 }
450 
451                                 // face color
452                                 ReadString( s);
453                                 if( s == std::string("HAS_FACE_COLOR_OCF")) {
454                                         face.EnableColor();
455                                         Read((void*)&face.CV[0],sizeof(typename FaceType::ColorType),face.size() );
456                                 }
457 
458                                 // face normal
459                                 ReadString( s);
460                                 if( s == std::string("HAS_FACE_NORMAL_OCF")) {
461                                         face.EnableNormal();
462                                         Read((void*)&face.NV[0],sizeof(typename FaceType::NormalType),face.size() );
463                                 }
464 
465                                 // face mark
466                                 ReadString( s);
467                                 if( s == std::string("HAS_FACE_MARK_OCF")) {
468                                         face.EnableMark();
469                                         Read((void*)&face.MV[0],sizeof(typename FaceType::MarkType),face.size() );
470                                 }
471 
472                                 // face wedgetexcoord
473                                 ReadString( s);
474                                 if( s == std::string("HAS_FACE_WEDGETEXCOORD_OCF")) {
475                                         face.EnableWedgeTexCoord();
476                                         Read((void*)&face.WTV[0],sizeof(typename FaceType::WedgeTexCoordType),face.size() );
477                                 }
478 
479 
480                                 // face-face adjacency
481                                 ReadString( s);
482                                 if( s == std::string("HAS_FACE_FFADJACENCY_OCF")) {
483                                         face.EnableFFAdjacency();
484                                         Read((void*)&face.AF[0],sizeof(typename  face::vector_ocf<FaceType>::AdjTypePack),face.size() );
485                                 }
486 
487                                 // vertex-face adjacency
488                                 ReadString( s);
489                                 if( s == std::string("HAS_FACE_VFADJACENCY_OCF")) {
490                                         face.EnableVFAdjacency();
491                                         Read((void*)&face.AV[0],sizeof(typename  face::vector_ocf<FaceType>::AdjTypePack),face.size() );
492                                 }
493 
494                                 // face WedgeColor
495                                 ReadString( s);
496                                 if( s == std::string("HAS_FACE_WEDGECOLOR_OCF")) {
497                                         face.EnableWedgeColor();
498                                         Read((void*)&face.WCV[0],sizeof(typename  face::vector_ocf<FaceType>::WedgeColorTypePack),face.size() );
499                                 }
500 
501                                 // face WedgeNormal
502                                 ReadString( s);
503                                 if( s == std::string("HAS_FACE_WEDGENORMAL_OCF")) {
504                                         face.EnableWedgeNormal();
505                                         Read((void*)&face.WNV[0],sizeof(typename  face::vector_ocf<FaceType>::WedgeNormalTypePack),face.size() );
506                                 }
507                         }
508                 };
509 
510     static int  FaceMaskBitFromString(std::string s){
511         if( s.find("Color",0) != std::string::npos )			return Mask::IOM_FACECOLOR;			else
512         if( s.find("BitFlags",0) != std::string::npos )			return Mask::IOM_FACEFLAGS;			else
513         if( s.find("VertexRef",0) != std::string::npos )		return Mask::IOM_FACEINDEX;			else
514         if( s.find("Normal",0) != std::string::npos )			return Mask::IOM_FACENORMAL;		else
515         if( s.find("Quality",0) != std::string::npos )			return Mask::IOM_FACEQUALITY;		else
516         if( s.find("Quality",0) != std::string::npos )			return Mask::IOM_FACEQUALITY;		else
517         if( s.find("WedgeColor",0) != std::string::npos )		return Mask::IOM_WEDGCOLOR;			else
518         if( s.find("WedgeNormal",0) != std::string::npos )		return Mask::IOM_WEDGNORMAL;		else
519         if( s.find("WedgeTexCoord",0) != std::string::npos)		return Mask::IOM_WEDGTEXCOORD;		else
520         return 0;
521     }
522     static int  VertexMaskBitFromString(std::string s){
523         if( s.find("Color",0) != std::string::npos )		return Mask::IOM_VERTCOLOR;		else
524         if( s.find("Coord",0) != std::string::npos )		return Mask::IOM_VERTCOORD;		else
525         if( s.find("BitFlags",0) != std::string::npos )		return Mask::IOM_VERTFLAGS;		else
526         if( s.find("Quality",0) != std::string::npos )		return Mask::IOM_VERTQUALITY;	else
527         if( s.find("Normal",0) != std::string::npos )		return Mask::IOM_VERTNORMAL;	else
528         if( s.find("TexCoord",0) != std::string::npos )		return Mask::IOM_VERTTEXCOORD;	else
529         if( s.find("Radius",0) != std::string::npos )		return Mask::IOM_VERTRADIUS;	else
530             return 0;
531     }
532 
533 
534         static FILE *& F(){static FILE * f; return f;}
535 
536 
537         static void * Malloc(unsigned int n){ return (n)?malloc(n):0;}
538         static void Free(void * ptr){ if(ptr) free (ptr);}
539 
540 
541         typedef typename OpenMeshType::FaceType FaceType;
542         typedef typename OpenMeshType::FaceContainer FaceContainer;
543         typedef typename OpenMeshType::FaceIterator FaceIterator;
544 
545         typedef typename OpenMeshType::VertContainer VertContainer;
546         typedef typename OpenMeshType::VertexIterator VertexIterator;
547         typedef typename OpenMeshType::VertexType VertexType;
548 
549     public:
550        enum VMIErrorCodes {
551                 VMI_NO_ERROR = 0,
552                 VMI_INCOMPATIBLE_VERTEX_TYPE,
553                 VMI_INCOMPATIBLE_FACE_TYPE,
554                 VMI_FAILED_OPEN
555        };
556 
557         /*!
558          *	Standard call for knowing the meaning of an error code
559          * \param message_code	The code returned by <CODE>Open</CODE>
560          *	\return							The string describing the error code
561          */
562         static const char* ErrorMsg(int message_code)
563         {
564             static const char* error_msg[] =
565             {
566                 "No errors",
567                 "The file has a incompatible vertex signature",
568                 "The file has a incompatible Face signature",
569                 "General failure of the file opening"
570             };
571 
572             if(message_code>4 || message_code<0)
573                 return "Unknown error";
574             else
575                 return error_msg[message_code];
576         };
577 
578         /* Read the info about the mesh. Note: in the header the bounding box is always written/readed
579            as a vcg::Box3f, even if the scalar type is not float. The bounding box of the mesh will
580            be set properly on loading.
581           */
582         static bool GetHeader(	std::vector<std::string>& fnameV,
583                                 std::vector<std::string>& fnameF,
584                                 unsigned int & vertSize,
585                                 unsigned int &faceSize,
586                                 vcg::Box3f & bbox,
587                                 int & mask){
588             std::string name;
589             unsigned int nameFsize,nameVsize,i;
590 
591             ReadString( name); ReadInt( nameFsize);
592 
593             for(i=0; i < nameFsize; ++i)
594                 {ReadString(  name);fnameF.push_back( name );mask |= FaceMaskBitFromString(name);}
595             mask |= LoadFaceOcfMask();
596 
597             ReadString( name); ReadInt( faceSize);
598             ReadString(  name); ReadInt( nameVsize);
599 
600             for(i=0; i < nameVsize; ++i)
601                 {ReadString(  name) ;fnameV.push_back( name);mask |= VertexMaskBitFromString(name);}
602             mask |= LoadVertexOcfMask();
603 
604             ReadString( name);
605             ReadInt( vertSize);
606 
607             ReadString( name);
608             float float_value;
609             for(unsigned int i =0; i < 2; ++i){ReadFloat( float_value); bbox.min[i]=float_value;}
610             for(unsigned int i =0; i < 2; ++i){ReadFloat( float_value); bbox.max[i]=float_value;}
611 
612             ReadString( name);
613             assert(strstr( name.c_str(),"end_header")!=NULL);
614             return true;
615         }
616 
617 
618         static bool GetHeader(const char * filename,std::vector<std::string>& nameV, std::vector<std::string>& nameF, unsigned int & vertSize, unsigned int &faceSize,vcg::Box3f & bbox,int & mask){
619                 F() = fopen(filename,"rb");
620                 bool res =  GetHeader(nameV, nameF, vertSize, faceSize,bbox,mask);
621                 fclose(F());
622                 return res;
623     }
624 
625     public:
626         static const char * & In_mem(){static const char *    in_mem; return in_mem;}
627         static unsigned int & In_mode(){static unsigned int  in_mode = 0; return in_mode;}
628 
629 
630         static unsigned int & pos(){static unsigned int  p = 0; return p;}
631         static int Read_sim(const void * , size_t size, size_t count ){ pos() += size * count;return size * count; }
632         static int Read_mem( void *dst , size_t size, size_t count ){ memcpy(dst,&In_mem()[pos()],size*count); pos() += size * count;return size * count; }
633 
634 
635         static int Read( void * dst,  size_t size, size_t count){
636             switch(In_mode()){
637             case 0: return Read_mem(dst, size,count );  break;
638             case 1: return fread(dst, size,count, F() ); break;
639              }
640             assert(0);
641             return 0;
642         }
643 
644 
645         static bool LoadMask(const char * f, int & mask){
646             std::vector<std::string>  nameV;
647             std::vector<std::string>  nameF;
648             unsigned int   vertSize, faceSize;
649             vcg::Box3f bbox;
650             F() = fopen(f,"rb");
651             In_mode() = 1;
652             GetHeader(nameV,nameF,vertSize, faceSize, bbox, mask);
653             return true;
654         }
655 
656         static bool LoadMaskFromMem(  const char * ptr, int & mask){
657             std::vector<std::string>  nameV;
658             std::vector<std::string>  nameF;
659             unsigned int   vertSize, faceSize;
660             vcg::Box3f bbox;
661             In_mode() = 0;
662             pos() = 0;
663             In_mem() = ptr;
664             GetHeader(nameV,nameF,vertSize, faceSize, bbox, mask);
665             return true;
666         }
667 
668         static int Open(OpenMeshType &m, const char * filename, int & mask,CallBackPos  * /*cb*/ = 0 )       {
669             In_mode() = 1;
670             F() = fopen(filename,"rb");
671             if(!F()) return VMI_FAILED_OPEN;
672             if(F()==NULL)	return 1; // 1 is the error code for cant'open, see the ErrorMsg function
673             int res = Deserialize(m,mask);
674             fclose(F());
675             return  res;
676         }
677         static int ReadFromMem(  OpenMeshType &m, int & mask,char * ptr){
678             In_mode() = 0;
679             pos() = 0;
680             In_mem() = ptr;
681             return Deserialize(m,mask);
682         }
683 
684         static int Deserialize(OpenMeshType &m, int & mask)
685         {
686             typedef typename OpenMeshType::VertexType VertexType;
687             typedef typename OpenMeshType::FaceType FaceType;
688             typename OpenMeshType::FaceIterator fi;
689             typename OpenMeshType::VertexIterator vi;
690 
691             std::vector<std::string> nameF,nameV,fnameF,fnameV;
692             unsigned int vertSize,faceSize;
693 
694             /* read the header */
695       vcg::Box3f lbbox;
696       GetHeader(fnameV, fnameF, vertSize, faceSize,lbbox,mask);
697       m.bbox.Import(lbbox);
698             /* read the mesh type */
699             OpenMeshType::FaceType::Name(nameF);
700             OpenMeshType::VertexType::Name(nameV);
701 
702             /* check if the type is the very same, otherwise return */
703             if(fnameV != nameV) return VMI_INCOMPATIBLE_VERTEX_TYPE;
704             if(fnameF != nameF) return VMI_INCOMPATIBLE_FACE_TYPE;
705 
706              void *  offsetV = 0,*offsetF = 0;
707 
708              if(vertSize!=0)
709                 /* read the address of the first vertex */
710                 Read(&offsetV,sizeof( void *),1 );
711 
712              if(faceSize!=0)
713                 /* read the address of the first face */
714                 Read(&offsetF,sizeof( void *),1 );
715 
716             /* read the object mesh */
717             Read(&m.shot,sizeof(Shot<typename OpenMeshType::ScalarType>),1 );
718             Read(&m.vn,sizeof(int),1 );
719             Read(&m.fn,sizeof(int),1 );
720             Read(&m.imark,sizeof(int),1 );
721             Read(&m.bbox,sizeof(Box3<typename OpenMeshType::ScalarType>),1 );
722             Read(&m.C(),sizeof(Color4b),1 );
723 
724 
725             /* resize the vector of vertices */
726             m.vert.resize(vertSize);
727 
728 
729             size_t read = 0;
730             /* load the vertices */
731             if(vertSize>0){
732                 read=Read((void*)& m.vert[0],sizeof(VertexType),vertSize );
733                  LoadVertexOcf<OpenMeshType,VertContainer>(F(),m.vert);
734             }
735 
736             read = 0;
737             m.face.resize(faceSize);
738             if(faceSize>0){
739                 /* load the faces */
740                 read = Read((void*)& m.face[0],sizeof(FaceType),faceSize );
741                 LoadFaceOcf<OpenMeshType,FaceContainer>(m.face);
742             }
743 
744 
745             /* load the per vertex attributes */
746             std::string _string,_trash;
747             unsigned int n,sz;
748 
749             ReadString( _trash); ReadInt( n);
750 
751             for(size_t ia = 0 ; ia < n; ++ia){
752                 ReadString(_trash); ReadString(_string);
753                 ReadString(_trash); ReadInt(sz);
754 
755                 void * data = Malloc(sz*m.vert.size());
756                 Read(data,sz,m.vert.size());
757                 AttrAll<OpenMeshType,A0,A1,A2,A3,A4>::template AddAttrib<0>(m,_string.c_str(),sz,data);
758                 Free(data);
759             }
760 
761             /* load the per face attributes */
762             ReadString(_trash); ReadInt( n);
763             for(size_t ia = 0 ; ia < n; ++ia){
764                 ReadString(_trash); ReadString( _string);
765                 ReadString(_trash); ReadInt( sz);
766                 void * data = Malloc(sz*m.face.size());
767                 Read(data,sz,m.face.size() );
768                 AttrAll<OpenMeshType,A0,A1,A2,A3,A4>::template AddAttrib<1>(m,_string.c_str(),sz,data);
769                 Free(data);
770             }
771 
772             /* load the per mesh attributes */
773             ReadString( _trash); ReadInt( n);
774             for(unsigned int ia = 0 ; ia < n; ++ia){
775                 ReadString( _trash); ReadString( _string);
776                 ReadString( _trash); ReadInt( sz);
777                 void * data = Malloc(sz);
778                 Read(data,1,sz );
779                 AttrAll<OpenMeshType,A0,A1,A2,A3,A4>::template AddAttrib<2>(m,_string.c_str(),sz,data);
780                 Free(data);
781             }
782 
783             if(!m.face.empty()){
784             if(FaceVectorHasVFAdjacency(m.face))
785                 for(vi = m.vert.begin(); vi != m.vert.end(); ++vi){
786                     (*vi).VFp() = (*vi).VFp()-(FaceType*)offsetF+ &m.face[0];
787                     (*vi).VFp() = (*vi).VFp()-(FaceType*)offsetF+ &m.face[0];
788                     (*vi).VFp() = (*vi).VFp()-(FaceType*)offsetF+ &m.face[0];
789                 }
790 
791             if(FaceVectorHasFVAdjacency(m.face))
792                 for(fi = m.face.begin(); fi != m.face.end(); ++fi){
793                     (*fi).V(0) = (*fi).V(0)-(VertexType*)offsetV+ &m.vert[0];
794                     (*fi).V(1) = (*fi).V(1)-(VertexType*)offsetV+ &m.vert[0];
795                     (*fi).V(2) = (*fi).V(2)-(VertexType*)offsetV+ &m.vert[0];
796                 }
797 
798             if(FaceVectorHasFFAdjacency(m.face))
799                 for(fi = m.face.begin(); fi != m.face.end(); ++fi){
800                     (*fi).FFp(0) = (*fi).FFp(0)-(FaceType*)offsetF+ &m.face[0];
801                     (*fi).FFp(1) = (*fi).FFp(1)-(FaceType*)offsetF+ &m.face[0];
802                     (*fi).FFp(2) = (*fi).FFp(2)-(FaceType*)offsetF+ &m.face[0];
803                 }
804 
805             }
806 
807             return VMI_NO_ERROR; // zero is the standard (!) code of success
808         }
809 
810     }; // end class
811 
812 
813 } // end Namespace tri
814 } // end Namespace io
815 } // end Namespace vcg
816 
817 #endif
818