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.hh>
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 template <typename T> Chunk::Integer_Size integer_size(const T& d)
00370 {
00371 assert( is_integer(d) );
00372
00373 switch( sizeof(T) )
00374 {
00375 case 1: return OMFormat::Chunk::Integer_8;
00376 case 2: return OMFormat::Chunk::Integer_16;
00377 case 4: return OMFormat::Chunk::Integer_32;
00378 case 8: return OMFormat::Chunk::Integer_64;
00379 }
00380 return Chunk::Integer_Size(0);
00381 }
00382
00383
00384
00385 template <typename T> Chunk::Float_Size float_size(const T& d)
00386 {
00387 assert( is_float(d) );
00388
00389 switch( sizeof(T) )
00390 {
00391 case 4: return OMFormat::Chunk::Float_32;
00392 case 8: return OMFormat::Chunk::Float_64;
00393 case 16: return OMFormat::Chunk::Float_128;
00394 }
00395 return Chunk::Float_Size(0);
00396 }
00397
00398
00399
00400 inline uint8 mk_version(const uint16 major, const uint16 minor)
00401 { return (major & 0x07) << 5 | (minor & 0x1f); }
00402
00403
00404 inline uint16 major_version(const uint8 version)
00405 { return (version >> 5) & 0x07; }
00406
00407
00408 inline uint16 minor_version(const uint8 version)
00409 { return (version & 0x001f); }
00410
00411
00412
00413
00414 const char *as_string(Chunk::Type t);
00415 const char *as_string(Chunk::Entity e);
00416 const char *as_string(Chunk::Dim d);
00417 const char *as_string(Chunk::Integer_Size d);
00418 const char *as_string(Chunk::Float_Size d);
00419
00420 std::ostream& operator << ( std::ostream& _os, const Header& _h );
00421 std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
00422
00424 }
00425
00426
00427
00428 template <> inline
00429 size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
00430 { return _hdr.store( _os, _swap ); }
00431
00432 template <> inline
00433 size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
00434 { return _hdr.restore( _is, _swap ); }
00435
00436
00437
00438
00439 template <> inline
00440 size_t
00441 store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
00442 {
00443 OMFormat::uint16 val; val << _hdr;
00444 return binary<uint16_t>::store( _os, val, _swap );
00445 }
00446
00447 template <> inline
00448 size_t
00449 restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
00450 {
00451 OMFormat::uint16 val;
00452 size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
00453
00454 _hdr << val;
00455
00456 return bytes;
00457 }
00458
00459
00460
00461 typedef GenProg::True t_signed;
00462 typedef GenProg::False t_unsigned;
00463
00464
00466 template< typename T >
00467 inline
00468 size_t
00469 store( std::ostream& _os,
00470 const T& _val,
00471 OMFormat::Chunk::Integer_Size _b,
00472 bool _swap)
00473 {
00474 assert( OMFormat::is_integer( _val ) );
00475
00476 if ( OMFormat::is_signed( _val ) )
00477 return store( _os, _val, _b, _swap, t_signed() );
00478 return store( _os, _val, _b, _swap, t_unsigned() );
00479 }
00480
00481
00482
00483 template< typename T >
00484 size_t
00485 store( std::ostream& _os,
00486 const T& _val,
00487 OMFormat::Chunk::Integer_Size _b,
00488 bool _swap,
00489 t_signed);
00490
00491
00492 template< typename T >
00493 size_t
00494 store( std::ostream& _os,
00495 const T& _val,
00496 OMFormat::Chunk::Integer_Size _b,
00497 bool _swap,
00498 t_unsigned);
00499
00500
00502 template< typename T >
00503 inline
00504 size_t
00505 restore( std::istream& _is,
00506 T& _val,
00507 OMFormat::Chunk::Integer_Size _b,
00508 bool _swap)
00509 {
00510 assert( OMFormat::is_integer( _val ) );
00511
00512 if ( OMFormat::is_signed( _val ) )
00513 return restore( _is, _val, _b, _swap, t_signed() );
00514 return restore( _is, _val, _b, _swap, t_unsigned() );
00515 }
00516
00517
00518
00519 template< typename T > inline
00520 size_t restore( std::istream& _is,
00521 T& _val,
00522 OMFormat::Chunk::Integer_Size _b,
00523 bool _swap,
00524 t_signed);
00525
00526
00527 template< typename T > inline
00528 size_t restore( std::istream& _is,
00529 T& _val,
00530 OMFormat::Chunk::Integer_Size _b,
00531 bool _swap,
00532 t_unsigned);
00533
00534
00535
00537 template <typename VecT> inline
00538 size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
00539 {
00540 return store( _os, _vec,
00541 GenProg::Int2Type< vector_traits<VecT>::size_ >(),
00542 _swap );
00543 }
00544
00545 template <typename VecT> inline
00546 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
00547 bool _swap )
00548 {
00549 return store( _os, _vec[0], _swap );
00550 }
00551
00552 template <typename VecT> inline
00553 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
00554 bool _swap )
00555 {
00556 size_t bytes = store( _os, _vec[0], _swap );
00557 bytes += store( _os, _vec[1], _swap );
00558 return bytes;
00559 }
00560
00561 template <typename VecT> inline
00562 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
00563 bool _swap )
00564 {
00565 size_t bytes = store( _os, _vec[0], _swap );
00566 bytes += store( _os, _vec[1], _swap );
00567 bytes += store( _os, _vec[2], _swap );
00568 return bytes;
00569 }
00570
00571 template <typename VecT> inline
00572 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
00573 bool _swap )
00574 {
00575 size_t bytes = store( _os, _vec[0], _swap );
00576 bytes += store( _os, _vec[1], _swap );
00577 bytes += store( _os, _vec[2], _swap );
00578 bytes += store( _os, _vec[3], _swap );
00579 return bytes;
00580 }
00581
00582
00583
00585 template <typename VecT>
00586 inline
00587 size_t
00588 vector_restore( std::istream& _is, VecT& _vec, bool _swap )
00589 {
00590 return restore( _is, _vec,
00591 GenProg::Int2Type< vector_traits<VecT>::size_ >(),
00592 _swap );
00593 }
00594
00595
00596 template <typename VecT>
00597 inline
00598 size_t
00599 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
00600 bool _swap )
00601 {
00602 return restore( _is, _vec[0], _swap );
00603 }
00604
00605 template <typename VecT>
00606 inline
00607 size_t
00608 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
00609 bool _swap )
00610 {
00611 size_t bytes = restore( _is, _vec[0], _swap );
00612 bytes += restore( _is, _vec[1], _swap );
00613 return bytes;
00614 }
00615
00616 template <typename VecT>
00617 inline
00618 size_t
00619 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
00620 bool _swap )
00621 {
00622 typedef typename vector_traits<VecT>::value_type scalar_type;
00623 size_t bytes;
00624
00625 bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
00626 bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
00627 bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
00628 return bytes;
00629 }
00630
00631 template <typename VecT>
00632 inline
00633 size_t
00634 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
00635 bool _swap )
00636 {
00637 typedef typename vector_traits<VecT>::value_type scalar_type;
00638 size_t bytes;
00639
00640 bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
00641 bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
00642 bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
00643 bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
00644 return bytes;
00645 }
00646
00647
00648
00649 template <>
00650 inline
00651 size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
00652 bool _swap )
00653 {
00654 store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap );
00655 if ( _pn.size() )
00656 _os.write( _pn.c_str(), _pn.size() );
00657 return _pn.size() + 1;
00658 }
00659
00660 template <>
00661 inline
00662 size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
00663 bool _swap )
00664 {
00665 size_t size;
00666
00667 restore( _is, size, OMFormat::Chunk::Integer_8, _swap);
00668
00669 assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
00670
00671 if ( size > 0 )
00672 {
00673 char buf[256];
00674 _is.read( buf, size );
00675 buf[size] = '\0';
00676 _pn.resize(size);
00677 _pn = buf;
00678 }
00679 return size+1;
00680 }
00681
00682
00683 }
00684 }
00685 #endif
00686
00687 #if defined(OM_MISSING_HEADER_LIMITS)
00688 # undef OM_MISSING_HEADER_LIMITS
00689 #endif
00690
00691 #if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
00692 # define OPENMESH_IO_OMFORMAT_TEMPLATES
00693 # include "OMFormat.cc"
00694 #endif
00695
00696 #endif
00697