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