00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef OPENMESH_IO_OMFORMAT_HH
00044 #define OPENMESH_IO_OMFORMAT_HH
00045
00046
00047
00048
00049 #include <OpenMesh/Core/System/config.h>
00050 #include <OpenMesh/Core/System/omstream.hh>
00051 #include <OpenMesh/Core/IO/SR_store.hh>
00052 #include <OpenMesh/Core/Utils/GenProg.hh>
00053 #include <OpenMesh/Core/Utils/Endian.hh>
00054 #include <OpenMesh/Core/Utils/vector_traits.hh>
00055
00056 #include <iostream>
00057 #if defined(OM_CC_GCC) && (OM_GCC_VERSION < 30000)
00058 # include <OpenMesh/Tools/Utils/NumLimitsT.hh>
00059 # define OM_MISSING_HEADER_LIMITS 1
00060 #else
00061 # include <limits>
00062 #endif
00063
00064
00065
00066
00067 #ifndef DOXY_IGNORE_THIS
00068 namespace OpenMesh {
00069 namespace IO {
00070 namespace OMFormat {
00071
00072
00073
00074
00075
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 typedef unsigned char uchar;
00110 typedef uint8_t uint8;
00111 typedef uint16_t uint16;
00112 typedef uint32_t uint32;
00113 typedef uint64_t uint64;
00114 typedef int8_t int8;
00115 typedef int16_t int16;
00116 typedef int32_t int32;
00117 typedef int64_t int64;
00118 typedef float32_t float32;
00119 typedef float64_t float64;
00120
00121 struct Header
00122 {
00123 uchar magic_[2];
00124 uchar mesh_;
00125 uint8 version_;
00126 uint32 n_vertices_;
00127 uint32 n_faces_;
00128 uint32 n_edges_;
00129
00130 size_t store( std::ostream& _os, bool _swap ) const
00131 {
00132 _os.write( (char*)this, 4);
00133 size_t bytes = 4;
00134 bytes += binary<uint32_t>::store( _os, n_vertices_, _swap );
00135 bytes += binary<uint32_t>::store( _os, n_faces_, _swap );
00136 bytes += binary<uint32_t>::store( _os, n_edges_, _swap );
00137 return bytes;
00138 }
00139
00140 size_t restore( std::istream& _is, bool _swap )
00141 {
00142 if (_is.read( (char*)this, 4 ).eof())
00143 return 0;
00144
00145 size_t bytes = 4;
00146 bytes += binary<uint32_t>::restore( _is, n_vertices_, _swap );
00147 bytes += binary<uint32_t>::restore( _is, n_faces_, _swap );
00148 bytes += binary<uint32_t>::restore( _is, n_edges_, _swap );
00149 return bytes;
00150 }
00151
00152 };
00153
00154 struct Chunk
00155 {
00156
00157
00158 typedef uint32 esize_t;
00159
00160 enum Type {
00161 Type_Pos = 0x00,
00162 Type_Normal = 0x01,
00163 Type_Texcoord = 0x02,
00164 Type_Status = 0x03,
00165 Type_Color = 0x04,
00166 Type_Custom = 0x06,
00167 Type_Topology = 0x07
00168 };
00169
00170 enum Entity {
00171 Entity_Vertex = 0x00,
00172 Entity_Mesh = 0x01,
00173 Entity_Face = 0x02,
00174 Entity_Edge = 0x04,
00175 Entity_Halfedge = 0x06
00176 };
00177
00178 enum Dim {
00179 Dim_1D = 0x00,
00180 Dim_2D = 0x01,
00181 Dim_3D = 0x02,
00182 Dim_4D = 0x03,
00183 Dim_5D = 0x04,
00184 Dim_6D = 0x05,
00185 Dim_7D = 0x06,
00186 Dim_8D = 0x07
00187 };
00188
00189 enum Integer_Size {
00190 Integer_8 = 0x00,
00191 Integer_16 = 0x01,
00192 Integer_32 = 0x02,
00193 Integer_64 = 0x03
00194 };
00195
00196 enum Float_Size {
00197 Float_32 = 0x00,
00198 Float_64 = 0x01,
00199 Float_128 = 0x02
00200 };
00201
00202 static const int SIZE_RESERVED = 1;
00203 static const int SIZE_NAME = 1;
00204 static const int SIZE_ENTITY = 3;
00205 static const int SIZE_TYPE = 4;
00206
00207 static const int SIZE_SIGNED = 1;
00208 static const int SIZE_FLOAT = 1;
00209 static const int SIZE_DIM = 3;
00210 static const int SIZE_BITS = 2;
00211
00212 static const int OFF_RESERVED = 0;
00213 static const int OFF_NAME = SIZE_RESERVED + OFF_RESERVED;
00214 static const int OFF_ENTITY = SIZE_NAME + OFF_NAME;
00215 static const int OFF_TYPE = SIZE_ENTITY + OFF_ENTITY;
00216 static const int OFF_SIGNED = SIZE_TYPE + OFF_TYPE;
00217 static const int OFF_FLOAT = SIZE_SIGNED + OFF_SIGNED;
00218 static const int OFF_DIM = SIZE_FLOAT + OFF_FLOAT;
00219 static const int OFF_BITS = SIZE_DIM + OFF_DIM;
00220
00221
00222
00223
00224
00225
00226
00227 struct Header
00228 {
00229 unsigned reserved_: SIZE_RESERVED;
00230 unsigned name_ : SIZE_NAME;
00231 unsigned entity_ : SIZE_ENTITY;
00232
00233 unsigned type_ : SIZE_TYPE;
00234
00235 unsigned signed_ : SIZE_SIGNED;
00236 unsigned float_ : SIZE_FLOAT;
00237 unsigned dim_ : SIZE_DIM;
00238 unsigned bits_ : SIZE_BITS;
00239
00240 unsigned unused_ : 16;
00241 };
00242
00243
00244 class PropertyName : public std::string
00245 {
00246 public:
00247
00248 static const size_t size_max = 256;
00249
00250 PropertyName( ) { }
00251
00252 PropertyName( const std::string& _name ) { *this = _name; }
00253
00254 bool is_valid() const { return is_valid( size() ); }
00255
00256 static bool is_valid( size_t _s ) { return _s <= size_max; }
00257
00258 PropertyName& operator = ( const std::string& _rhs )
00259 {
00260 assert( is_valid( _rhs.size() ) );
00261
00262 if ( is_valid( _rhs.size() ) )
00263 std::string::operator = ( _rhs );
00264 else
00265 {
00266 omerr() << "Warning! Property name too long. Will be shortened!\n";
00267 this->std::string::operator = ( _rhs.substr(0, size_max) );
00268 }
00269
00270 return *this;
00271 }
00272
00273 };
00274
00275 };
00276
00277
00278
00279
00280
00282 inline size_t header_size(void) { return sizeof(Header); }
00283
00284
00286 inline size_t chunk_header_size( void ) { return sizeof(uint16); }
00287
00288
00290 inline size_t scalar_size( const Chunk::Header& _hdr )
00291 {
00292 return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_);
00293 }
00294
00295
00297 inline size_t dimensions(const Chunk::Header& _chdr) { return _chdr.dim_+1; }
00298
00299
00301 inline size_t vector_size( const Chunk::Header& _chdr )
00302 {
00303 return dimensions(_chdr)*scalar_size(_chdr);
00304 }
00305
00306
00308 inline size_t chunk_data_size( Header& _hdr, Chunk::Header& _chunk_hdr )
00309 {
00310 size_t C = 0;
00311
00312 switch( _chunk_hdr.entity_ )
00313 {
00314 case Chunk::Entity_Vertex: C = _hdr.n_vertices_; break;
00315 case Chunk::Entity_Face: C = _hdr.n_faces_; break;
00316 case Chunk::Entity_Halfedge: C = _hdr.n_edges_;
00317 case Chunk::Entity_Edge: C += _hdr.n_edges_; break;
00318 case Chunk::Entity_Mesh: C = 1; break;
00319 default:
00320 std::cerr << "Invalid value in _chunk_hdr.entity_\n";
00321 assert( false );
00322 }
00323
00324 return C * vector_size( _chunk_hdr );
00325 }
00326
00327 inline size_t chunk_size( Header& _hdr, Chunk::Header& _chunk_hdr )
00328 {
00329 return chunk_header_size() + chunk_data_size( _hdr, _chunk_hdr );
00330 }
00331
00332
00333
00334 uint16& operator << (uint16& val, const Chunk::Header& hdr);
00335 Chunk::Header& operator << (Chunk::Header& hdr, const uint16 val);
00336
00337
00338
00339
00340 template <typename T> bool is_float(const T&)
00341 {
00342 #if defined(OM_MISSING_HEADER_LIMITS)
00343 return !Utils::NumLimitsT<T>::is_integer();
00344 #else
00345 return !std::numeric_limits<T>::is_integer;
00346 #endif
00347 }
00348
00349 template <typename T> bool is_integer(const T)
00350 {
00351 #if defined(OM_MISSING_HEADER_LIMITS)
00352 return Utils::NumLimitsT<T>::is_integer();
00353 #else
00354 return std::numeric_limits<T>::is_integer;
00355 #endif
00356 }
00357
00358 template <typename T> bool is_signed(const T&)
00359 {
00360 #if defined(OM_MISSING_HEADER_LIMITS)
00361 return Utils::NumLimitsT<T>::is_signed();
00362 #else
00363 return std::numeric_limits<T>::is_signed;
00364 #endif
00365 }
00366
00367
00368
00369 template <typename VecType>
00370 inline
00371 Chunk::Dim dim( VecType )
00372 {
00373 assert( vector_traits< VecType >::size() < 9 );
00374 return static_cast<Chunk::Dim>(vector_traits< VecType >::size() - 1);
00375 }
00376
00377 template <typename VecType>
00378 inline
00379 Chunk::Dim dim( const Chunk::Header& _hdr )
00380 {
00381 return static_cast<Chunk::Dim>( _hdr.dim_ );
00382 }
00383
00384
00385 Chunk::Integer_Size needed_bits( size_t s );
00386
00387
00388
00389 template <typename T>
00390 inline
00391 unsigned int bits(const T& val)
00392 {
00393 return is_integer(val)
00394 ? (static_cast<unsigned int>(integer_size(val)))
00395 : (static_cast<unsigned int>(float_size(val)));
00396 }
00397
00398
00399 #ifdef NDEBUG
00400 template <typename T> Chunk::Integer_Size integer_size(const T&)
00401 #else
00402 template <typename T> Chunk::Integer_Size integer_size(const T& d)
00403 #endif
00404 {
00405 assert( is_integer(d) );
00406
00407 switch( sizeof(T) )
00408 {
00409 case 1: return OMFormat::Chunk::Integer_8;
00410 case 2: return OMFormat::Chunk::Integer_16;
00411 case 4: return OMFormat::Chunk::Integer_32;
00412 case 8: return OMFormat::Chunk::Integer_64;
00413 }
00414 return Chunk::Integer_Size(0);
00415 }
00416
00417
00418
00419 #ifdef NDEBUG
00420 template <typename T> Chunk::Float_Size float_size(const T&)
00421 #else
00422 template <typename T> Chunk::Float_Size float_size(const T& d)
00423 #endif
00424 {
00425 assert( is_float(d) );
00426
00427 switch( sizeof(T) )
00428 {
00429 case 4: return OMFormat::Chunk::Float_32;
00430 case 8: return OMFormat::Chunk::Float_64;
00431 case 16: return OMFormat::Chunk::Float_128;
00432 }
00433 return Chunk::Float_Size(0);
00434 }
00435
00436
00437
00438 inline uint8 mk_version(const uint16 major, const uint16 minor)
00439 { return (major & 0x07) << 5 | (minor & 0x1f); }
00440
00441
00442 inline uint16 major_version(const uint8 version)
00443 { return (version >> 5) & 0x07; }
00444
00445
00446 inline uint16 minor_version(const uint8 version)
00447 { return (version & 0x001f); }
00448
00449
00450
00451
00452 const char *as_string(Chunk::Type t);
00453 const char *as_string(Chunk::Entity e);
00454 const char *as_string(Chunk::Dim d);
00455 const char *as_string(Chunk::Integer_Size d);
00456 const char *as_string(Chunk::Float_Size d);
00457
00458 std::ostream& operator << ( std::ostream& _os, const Header& _h );
00459 std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
00460
00462 }
00463
00464
00465
00466 template <> inline
00467 size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
00468 { return _hdr.store( _os, _swap ); }
00469
00470 template <> inline
00471 size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
00472 { return _hdr.restore( _is, _swap ); }
00473
00474
00475
00476
00477 template <> inline
00478 size_t
00479 store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
00480 {
00481 OMFormat::uint16 val; val << _hdr;
00482 return binary<uint16_t>::store( _os, val, _swap );
00483 }
00484
00485 template <> inline
00486 size_t
00487 restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
00488 {
00489 OMFormat::uint16 val;
00490 size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
00491
00492 _hdr << val;
00493
00494 return bytes;
00495 }
00496
00497
00498
00499 typedef GenProg::True t_signed;
00500 typedef GenProg::False t_unsigned;
00501
00502
00503 template< typename T >
00504 size_t
00505 store( std::ostream& _os,
00506 const T& _val,
00507 OMFormat::Chunk::Integer_Size _b,
00508 bool _swap,
00509 t_signed);
00510
00511
00512 template< typename T >
00513 size_t
00514 store( std::ostream& _os,
00515 const T& _val,
00516 OMFormat::Chunk::Integer_Size _b,
00517 bool _swap,
00518 t_unsigned);
00519
00521 template< typename T >
00522 inline
00523 size_t
00524 store( std::ostream& _os,
00525 const T& _val,
00526 OMFormat::Chunk::Integer_Size _b,
00527 bool _swap)
00528 {
00529 assert( OMFormat::is_integer( _val ) );
00530
00531 if ( OMFormat::is_signed( _val ) )
00532 return store( _os, _val, _b, _swap, t_signed() );
00533 return store( _os, _val, _b, _swap, t_unsigned() );
00534 }
00535
00536
00537 template< typename T > inline
00538 size_t restore( std::istream& _is,
00539 T& _val,
00540 OMFormat::Chunk::Integer_Size _b,
00541 bool _swap,
00542 t_signed);
00543
00544
00545 template< typename T > inline
00546 size_t restore( std::istream& _is,
00547 T& _val,
00548 OMFormat::Chunk::Integer_Size _b,
00549 bool _swap,
00550 t_unsigned);
00551
00553 template< typename T >
00554 inline
00555 size_t
00556 restore( std::istream& _is,
00557 T& _val,
00558 OMFormat::Chunk::Integer_Size _b,
00559 bool _swap)
00560 {
00561 assert( OMFormat::is_integer( _val ) );
00562
00563 if ( OMFormat::is_signed( _val ) )
00564 return restore( _is, _val, _b, _swap, t_signed() );
00565 return restore( _is, _val, _b, _swap, t_unsigned() );
00566 }
00567
00568
00569
00570
00571 template <typename VecT> inline
00572 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
00573 bool _swap )
00574 {
00575 size_t bytes = store( _os, _vec[0], _swap );
00576 bytes += store( _os, _vec[1], _swap );
00577 return bytes;
00578 }
00579
00580 template <typename VecT> inline
00581 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
00582 bool _swap )
00583 {
00584 size_t bytes = store( _os, _vec[0], _swap );
00585 bytes += store( _os, _vec[1], _swap );
00586 bytes += store( _os, _vec[2], _swap );
00587 return bytes;
00588 }
00589
00590 template <typename VecT> inline
00591 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
00592 bool _swap )
00593 {
00594 size_t bytes = store( _os, _vec[0], _swap );
00595 bytes += store( _os, _vec[1], _swap );
00596 bytes += store( _os, _vec[2], _swap );
00597 bytes += store( _os, _vec[3], _swap );
00598 return bytes;
00599 }
00600
00601 template <typename VecT> inline
00602 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
00603 bool _swap )
00604 {
00605 return store( _os, _vec[0], _swap );
00606 }
00607
00609 template <typename VecT> inline
00610 size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
00611 {
00612 return store( _os, _vec,
00613 GenProg::Int2Type< vector_traits<VecT>::size_ >(),
00614 _swap );
00615 }
00616
00617
00618 template <typename VecT>
00619 inline
00620 size_t
00621 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
00622 bool _swap )
00623 {
00624 size_t bytes = restore( _is, _vec[0], _swap );
00625 bytes += restore( _is, _vec[1], _swap );
00626 return bytes;
00627 }
00628
00629 template <typename VecT>
00630 inline
00631 size_t
00632 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
00633 bool _swap )
00634 {
00635 typedef typename vector_traits<VecT>::value_type scalar_type;
00636 size_t bytes;
00637
00638 bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
00639 bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
00640 bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
00641 return bytes;
00642 }
00643
00644 template <typename VecT>
00645 inline
00646 size_t
00647 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
00648 bool _swap )
00649 {
00650 typedef typename vector_traits<VecT>::value_type scalar_type;
00651 size_t bytes;
00652
00653 bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
00654 bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
00655 bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
00656 bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
00657 return bytes;
00658 }
00659
00660 template <typename VecT>
00661 inline
00662 size_t
00663 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
00664 bool _swap )
00665 {
00666 return restore( _is, _vec[0], _swap );
00667 }
00668
00670 template <typename VecT>
00671 inline
00672 size_t
00673 vector_restore( std::istream& _is, VecT& _vec, bool _swap )
00674 {
00675 return restore( _is, _vec,
00676 GenProg::Int2Type< vector_traits<VecT>::size_ >(),
00677 _swap );
00678 }
00679
00680
00681
00682
00683 template <>
00684 inline
00685 size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
00686 bool _swap )
00687 {
00688 store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap );
00689 if ( _pn.size() )
00690 _os.write( _pn.c_str(), _pn.size() );
00691 return _pn.size() + 1;
00692 }
00693
00694 template <>
00695 inline
00696 size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
00697 bool _swap )
00698 {
00699 size_t size;
00700
00701 restore( _is, size, OMFormat::Chunk::Integer_8, _swap);
00702
00703 assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
00704
00705 if ( size > 0 )
00706 {
00707 char buf[256];
00708 _is.read( buf, size );
00709 buf[size] = '\0';
00710 _pn.resize(size);
00711 _pn = buf;
00712 }
00713 return size+1;
00714 }
00715
00716
00717 }
00718 }
00719 #endif
00720
00721 #if defined(OM_MISSING_HEADER_LIMITS)
00722 # undef OM_MISSING_HEADER_LIMITS
00723 #endif
00724
00725 #if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
00726 # define OPENMESH_IO_OMFORMAT_TEMPLATES
00727 # include "OMFormatT.cc"
00728 #endif
00729
00730 #endif
00731