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