OpenMesh

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OMFormat.hh
1 /*===========================================================================*\
2 * *
3 * OpenMesh *
4 * Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
5 * www.openmesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenMesh. *
9 * *
10 * OpenMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenMesh is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenMesh. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33 \*===========================================================================*/
34
35 /*===========================================================================*\
36 * *
37 * $Revision: 831 $ *
38 * $Date: 2013-06-05 10:23:24 +0200 (Mi, 05. Jun 2013) $ *
39 * *
40 \*===========================================================================*/
41
42
43 #ifndef OPENMESH_IO_OMFORMAT_HH
44 #define OPENMESH_IO_OMFORMAT_HH
45
46
47 //=== INCLUDES ================================================================
48
49 #include <OpenMesh/Core/System/config.h>
50 #include <OpenMesh/Core/System/omstream.hh>
51 #include <OpenMesh/Core/IO/SR_store.hh>
52 #include <OpenMesh/Core/Utils/GenProg.hh>
53 #include <OpenMesh/Core/Utils/Endian.hh>
54 #include <OpenMesh/Core/Utils/vector_traits.hh>
55 // --------------------
56 #include <iostream>
57 #if defined(OM_CC_GCC) && (OM_GCC_VERSION < 30000)
58 # include <OpenMesh/Tools/Utils/NumLimitsT.hh>
59 # define OM_MISSING_HEADER_LIMITS 1
60 #else
61 # include <limits>
62 #endif
63
64
65 //== NAMESPACES ==============================================================
66
67 #ifndef DOXY_IGNORE_THIS
68 namespace OpenMesh {
69 namespace IO {
70 namespace OMFormat {
71
72
73 //=== IMPLEMENTATION ==========================================================
74
75
79
80 //-----------------------------------------------------------------------------
81
82 // <:Header>
83 // <:Comment>
84 // Chunk 0
85 // <:ChunkHeader>
86 // <:Comment>
87 // data
88 // Chunk 1
89 // <:ChunkHeader>
90 // <:Comment>
91 // data
92 // .
93 // .
94 // .
95 // Chunk N
96
97 //
98 // NOTICE!
99 //
100 // The usage of data types who differ in size
101 // on different pc architectures (32/64 bit) and/or
102 // operating systems, e.g. (unsigned) long, size_t,
103 // is not recommended because of inconsistencies
104 // in case of cross writing and reading.
105 //
106 // Basic types that are supported are:
107
108
109 typedef unsigned char uchar;
110 typedef uint8_t uint8;
111 typedef uint16_t uint16;
112 typedef uint32_t uint32;
113 typedef uint64_t uint64;
114 typedef int8_t int8;
115 typedef int16_t int16;
116 typedef int32_t int32;
117 typedef int64_t int64;
118 typedef float32_t float32;
119 typedef float64_t float64;
120
121 struct Header
122 {
123 uchar magic_[2]; // OM
124 uchar mesh_; // [T]riangles, [Q]uads, [P]olygonals
125 uint8 version_;
126 uint32 n_vertices_;
127 uint32 n_faces_;
128 uint32 n_edges_;
129
130 size_t store( std::ostream& _os, bool _swap ) const
131 {
132 _os.write( (char*)this, 4); // magic_, mesh_, version_
133 size_t bytes = 4;
134 bytes += binary<uint32_t>::store( _os, n_vertices_, _swap );
135 bytes += binary<uint32_t>::store( _os, n_faces_, _swap );
136 bytes += binary<uint32_t>::store( _os, n_edges_, _swap );
137 return bytes;
138 }
139
140 size_t restore( std::istream& _is, bool _swap )
141 {
142 if (_is.read( (char*)this, 4 ).eof())
143 return 0;
144
145 size_t bytes = 4;
146 bytes += binary<uint32_t>::restore( _is, n_vertices_, _swap );
147 bytes += binary<uint32_t>::restore( _is, n_faces_, _swap );
148 bytes += binary<uint32_t>::restore( _is, n_edges_, _swap );
149 return bytes;
150 }
151
152 };
153
154 struct Chunk
155 {
156 // Hardcoded this size to an uint32 to make the system 32/64 bit compatible.
157 // Needs further investigation!
158 typedef uint32 esize_t; // element size, used for custom properties
159
160 enum Type {
161 Type_Pos = 0x00,
162 Type_Normal = 0x01,
163 Type_Texcoord = 0x02,
164 Type_Status = 0x03,
165 Type_Color = 0x04,
166 Type_Custom = 0x06,
167 Type_Topology = 0x07
168 };
169
170 enum Entity {
171 Entity_Vertex = 0x00,
172 Entity_Mesh = 0x01,
173 Entity_Face = 0x02,
174 Entity_Edge = 0x04,
175 Entity_Halfedge = 0x06
176 };
177
178 enum Dim {
179 Dim_1D = 0x00,
180 Dim_2D = 0x01,
181 Dim_3D = 0x02,
182 Dim_4D = 0x03,
183 Dim_5D = 0x04,
184 Dim_6D = 0x05,
185 Dim_7D = 0x06,
186 Dim_8D = 0x07
187 };
188
189 enum Integer_Size {
190 Integer_8 = 0x00, // 1 byte for (unsigned) char
191 Integer_16 = 0x01, // 2 bytes for short
192 Integer_32 = 0x02, // 4 bytes for long
193 Integer_64 = 0x03 // 8 bytes for long long
194 };
195
196 enum Float_Size {
197 Float_32 = 0x00, // 4 bytes for float
198 Float_64 = 0x01, // 8 bytes for double
199 Float_128 = 0x02 // 16 bytes for long double (an assumption!)
200 };
201
202 static const int SIZE_RESERVED = 1; // 1
203 static const int SIZE_NAME = 1; // 2
204 static const int SIZE_ENTITY = 3; // 5
205 static const int SIZE_TYPE = 4; // 9
206
207 static const int SIZE_SIGNED = 1; // 10
208 static const int SIZE_FLOAT = 1; // 11
209 static const int SIZE_DIM = 3; // 14
210 static const int SIZE_BITS = 2; // 16
211
212 static const int OFF_RESERVED = 0; // 0
213 static const int OFF_NAME = SIZE_RESERVED + OFF_RESERVED; // 2
214 static const int OFF_ENTITY = SIZE_NAME + OFF_NAME; // 3
215 static const int OFF_TYPE = SIZE_ENTITY + OFF_ENTITY; // 5
216 static const int OFF_SIGNED = SIZE_TYPE + OFF_TYPE; // 9
217 static const int OFF_FLOAT = SIZE_SIGNED + OFF_SIGNED; // 10
218 static const int OFF_DIM = SIZE_FLOAT + OFF_FLOAT; // 11
219 static const int OFF_BITS = SIZE_DIM + OFF_DIM; // 14
220
221 // !Attention! When changing the bit size, the operators
222 // << (uint16, Header) and << (Header, uint16) must be changed as well
223 //
224 // Entries signed_, float_, dim_, bits_ are not used when type_
225 // equals Type_Custom
226 //
227 struct Header // 16 bits long
228 {
229 unsigned reserved_: SIZE_RESERVED;
230 unsigned name_ : SIZE_NAME; // 1 named property, 0 anonymous
231 unsigned entity_ : SIZE_ENTITY; // 0 vertex, 1 mesh, 2 edge,
232 // 4 halfedge, 6 face
233 unsigned type_ : SIZE_TYPE; // 0 pos, 1 normal, 2 texcoord,
234 // 3 status, 4 color 6 custom 7 topology
235 unsigned signed_ : SIZE_SIGNED; // bool
236 unsigned float_ : SIZE_FLOAT; // bool
237 unsigned dim_ : SIZE_DIM; // 0 1D, 1 2D, 2 3D, .., 7 8D
238 unsigned bits_ : SIZE_BITS; // {8, 16, 32, 64} | {32, 64, 128}
239 // (integer) (float)
240 unsigned unused_ : 16; // fill up to 32 bits
241 }; // struct Header
242
243
244 class PropertyName : public std::string
245 {
246 public:
247
248 static const size_t size_max = 256;
249
250 PropertyName( ) { }
251
252 PropertyName( const std::string& _name ) { *this = _name; }
253
254 bool is_valid() const { return is_valid( size() ); }
255
256 static bool is_valid( size_t _s ) { return _s <= size_max; }
257
258 PropertyName& operator = ( const std::string& _rhs )
259 {
260 assert( is_valid( _rhs.size() ) );
261
262 if ( is_valid( _rhs.size() ) )
263 std::string::operator = ( _rhs );
264 else
265 {
266 omerr() << "Warning! Property name too long. Will be shortened!\n";
267 this->std::string::operator = ( _rhs.substr(0, size_max) );
268 }
269
270 return *this;
271 }
272
273 };
274
275 }; // Chunk
276
277 // ------------------------------------------------------------ Helper
278
279 // -------------------- get size information
280
282 inline size_t header_size(void) { return sizeof(Header); }
283
284
286 inline size_t chunk_header_size( void ) { return sizeof(uint16); }
287
288
290 inline size_t scalar_size( const Chunk::Header& _hdr )
291 {
292 return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_);
293 }
294
295
297 inline size_t dimensions(const Chunk::Header& _chdr) { return _chdr.dim_+1; }
298
299
301 inline size_t vector_size( const Chunk::Header& _chdr )
302 {
303 return dimensions(_chdr)*scalar_size(_chdr);
304 }
305
306
308 inline size_t chunk_data_size( Header& _hdr, Chunk::Header& _chunk_hdr )
309 {
310 size_t C = 0;
311
312 switch( _chunk_hdr.entity_ )
313 {
314 case Chunk::Entity_Vertex: C = _hdr.n_vertices_; break;
315 case Chunk::Entity_Face: C = _hdr.n_faces_; break;
316 case Chunk::Entity_Halfedge: C = _hdr.n_edges_; // no break!
317 case Chunk::Entity_Edge: C += _hdr.n_edges_; break;
318 case Chunk::Entity_Mesh: C = 1; break;
319 default:
320 std::cerr << "Invalid value in _chunk_hdr.entity_\n";
321 assert( false );
322 break;
323 }
324
325 return C * vector_size( _chunk_hdr );
326 }
327
328 inline size_t chunk_size( Header& _hdr, Chunk::Header& _chunk_hdr )
329 {
330 return chunk_header_size() + chunk_data_size( _hdr, _chunk_hdr );
331 }
332
333 // -------------------- convert from Chunk::Header to storage type
334
335 uint16& operator << (uint16& val, const Chunk::Header& hdr);
336 Chunk::Header& operator << (Chunk::Header& hdr, const uint16 val);
337
338
339 // -------------------- type information
340
341 template <typename T> bool is_float(const T&)
342 {
343 #if defined(OM_MISSING_HEADER_LIMITS)
344 return !Utils::NumLimitsT<T>::is_integer();
345 #else
346 return !std::numeric_limits<T>::is_integer;
347 #endif
348 }
349
350 template <typename T> bool is_integer(const T)
351 {
352 #if defined(OM_MISSING_HEADER_LIMITS)
353 return Utils::NumLimitsT<T>::is_integer();
354 #else
355 return std::numeric_limits<T>::is_integer;
356 #endif
357 }
358
359 template <typename T> bool is_signed(const T&)
360 {
361 #if defined(OM_MISSING_HEADER_LIMITS)
362 return Utils::NumLimitsT<T>::is_signed();
363 #else
364 return std::numeric_limits<T>::is_signed;
365 #endif
366 }
367
368 // -------------------- conversions (format type <- type/value)
369
370 template <typename VecType>
371 inline
372 Chunk::Dim dim( VecType )
373 {
374 assert( vector_traits< VecType >::size() < 9 );
375 return static_cast<Chunk::Dim>(vector_traits< VecType >::size() - 1);
376 }
377
378 template <typename VecType>
379 inline
380 Chunk::Dim dim( const Chunk::Header& _hdr )
381 {
382 return static_cast<Chunk::Dim>( _hdr.dim_ );
383 }
384
385 // calc minimum (power-of-2) number of bits needed
386 Chunk::Integer_Size needed_bits( size_t s );
387
388 // Convert size of type to Integer_Size
389 #ifdef NDEBUG
390 template <typename T> Chunk::Integer_Size integer_size(const T&)
391 #else
392 template <typename T> Chunk::Integer_Size integer_size(const T& d)
393 #endif
394 {
395 assert( is_integer(d) );
396
397 switch( sizeof(T) )
398 {
399 case 1: return OMFormat::Chunk::Integer_8;
400 case 2: return OMFormat::Chunk::Integer_16;
401 case 4: return OMFormat::Chunk::Integer_32;
402 case 8: return OMFormat::Chunk::Integer_64;
403 default:
404 std::cerr << "Invalid value in integer_size\n";
405 assert( false );
406 break;
407 }
408 return Chunk::Integer_Size(0);
409 }
410
411
412 // Convert size of type to FLoat_Size
413 #ifdef NDEBUG
414 template <typename T> Chunk::Float_Size float_size(const T&)
415 #else
416 template <typename T> Chunk::Float_Size float_size(const T& d)
417 #endif
418 {
419 assert( is_float(d) );
420
421 switch( sizeof(T) )
422 {
423 case 4: return OMFormat::Chunk::Float_32;
424 case 8: return OMFormat::Chunk::Float_64;
425 case 16: return OMFormat::Chunk::Float_128;
426 default:
427 std::cerr << "Invalid value in float_size\n";
428 assert( false );
429 break;
430 }
431 return Chunk::Float_Size(0);
432 }
433
434 // Return the storage type (Chunk::Header::bits_)
435 template <typename T>
436 inline
437 unsigned int bits(const T& val)
438 {
439 return is_integer(val)
440 ? (static_cast<unsigned int>(integer_size(val)))
441 : (static_cast<unsigned int>(float_size(val)));
442 }
443
444 // -------------------- create/read version
445
446 inline uint8 mk_version(const uint16 major, const uint16 minor)
447 { return (major & 0x07) << 5 | (minor & 0x1f); }
448
449
450 inline uint16 major_version(const uint8 version)
451 { return (version >> 5) & 0x07; }
452
453
454 inline uint16 minor_version(const uint8 version)
455 { return (version & 0x001f); }
456
457
458 // ---------------------------------------- convenience functions
459
460 const char *as_string(Chunk::Type t);
461 const char *as_string(Chunk::Entity e);
462 const char *as_string(Chunk::Dim d);
463 const char *as_string(Chunk::Integer_Size d);
464 const char *as_string(Chunk::Float_Size d);
465
466 std::ostream& operator << ( std::ostream& _os, const Header& _h );
467 std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
468
470 } // namespace OMFormat
471
472 // -------------------- (re-)store header
473
474 template <> inline
475 size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
476 { return _hdr.store( _os, _swap ); }
477
478 template <> inline
479 size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
480 { return _hdr.restore( _is, _swap ); }
481
482
483 // -------------------- (re-)store chunk header
484
485 template <> inline
486 size_t
487 store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
488 {
489 OMFormat::uint16 val; val << _hdr;
490 return binary<uint16_t>::store( _os, val, _swap );
491 }
492
493 template <> inline
494 size_t
495 restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
496 {
497 OMFormat::uint16 val;
498 size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
499
500 _hdr << val;
501
502 return bytes;
503 }
504
505 // -------------------- (re-)store integer with wanted number of bits (bytes)
506
507 typedef GenProg::True t_signed;
508 typedef GenProg::False t_unsigned;
509
510 // helper to store a an integer
511 template< typename T >
512 size_t
513 store( std::ostream& _os,
514 const T& _val,
515 OMFormat::Chunk::Integer_Size _b,
516 bool _swap,
517 t_signed);
518
519 // helper to store a an unsigned integer
520 template< typename T >
521 size_t
522 store( std::ostream& _os,
523 const T& _val,
524 OMFormat::Chunk::Integer_Size _b,
525 bool _swap,
526 t_unsigned);
527
529 template< typename T >
530 inline
531 size_t
532 store( std::ostream& _os,
533 const T& _val,
534 OMFormat::Chunk::Integer_Size _b,
535 bool _swap)
536 {
537 assert( OMFormat::is_integer( _val ) );
538
539 if ( OMFormat::is_signed( _val ) )
540 return store( _os, _val, _b, _swap, t_signed() );
541 return store( _os, _val, _b, _swap, t_unsigned() );
542 }
543
544 // helper to store a an integer
545 template< typename T > inline
546 size_t restore( std::istream& _is,
547 T& _val,
548 OMFormat::Chunk::Integer_Size _b,
549 bool _swap,
550 t_signed);
551
552 // helper to store a an unsigned integer
553 template< typename T > inline
554 size_t restore( std::istream& _is,
555 T& _val,
556 OMFormat::Chunk::Integer_Size _b,
557 bool _swap,
558 t_unsigned);
559
561 template< typename T >
562 inline
563 size_t
564 restore( std::istream& _is,
565 T& _val,
566 OMFormat::Chunk::Integer_Size _b,
567 bool _swap)
568 {
569 assert( OMFormat::is_integer( _val ) );
570
571 if ( OMFormat::is_signed( _val ) )
572 return restore( _is, _val, _b, _swap, t_signed() );
573 return restore( _is, _val, _b, _swap, t_unsigned() );
574 }
575
576
577 //
578 // ---------------------------------------- storing vectors
579 template <typename VecT> inline
580 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
581 bool _swap )
582 {
583 size_t bytes = store( _os, _vec[0], _swap );
584 bytes += store( _os, _vec[1], _swap );
585 return bytes;
586 }
587
588 template <typename VecT> inline
589 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
590 bool _swap )
591 {
592 size_t bytes = store( _os, _vec[0], _swap );
593 bytes += store( _os, _vec[1], _swap );
594 bytes += store( _os, _vec[2], _swap );
595 return bytes;
596 }
597
598 template <typename VecT> inline
599 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
600 bool _swap )
601 {
602 size_t bytes = store( _os, _vec[0], _swap );
603 bytes += store( _os, _vec[1], _swap );
604 bytes += store( _os, _vec[2], _swap );
605 bytes += store( _os, _vec[3], _swap );
606 return bytes;
607 }
608
609 template <typename VecT> inline
610 size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
611 bool _swap )
612 {
613 return store( _os, _vec[0], _swap );
614 }
615
617 template <typename VecT> inline
618 size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
619 {
620 return store( _os, _vec,
621 GenProg::Int2Type< vector_traits<VecT>::size_ >(),
622 _swap );
623 }
624
625 // ---------------------------------------- restoring vectors
626 template <typename VecT>
627 inline
628 size_t
629 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
630 bool _swap )
631 {
632 size_t bytes = restore( _is, _vec[0], _swap );
633 bytes += restore( _is, _vec[1], _swap );
634 return bytes;
635 }
636
637 template <typename VecT>
638 inline
639 size_t
640 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
641 bool _swap )
642 {
643 typedef typename vector_traits<VecT>::value_type scalar_type;
644 size_t bytes;
645
646 bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
647 bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
648 bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
649 return bytes;
650 }
651
652 template <typename VecT>
653 inline
654 size_t
655 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
656 bool _swap )
657 {
658 typedef typename vector_traits<VecT>::value_type scalar_type;
659 size_t bytes;
660
661 bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
662 bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
663 bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
664 bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
665 return bytes;
666 }
667
668 template <typename VecT>
669 inline
670 size_t
671 restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
672 bool _swap )
673 {
674 return restore( _is, _vec[0], _swap );
675 }
676
678 template <typename VecT>
679 inline
680 size_t
681 vector_restore( std::istream& _is, VecT& _vec, bool _swap )
682 {
683 return restore( _is, _vec,
684 GenProg::Int2Type< vector_traits<VecT>::size_ >(),
685 _swap );
686 }
687
688
689 // ---------------------------------------- storing property names
690
691 template <>
692 inline
693 size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
694 bool _swap )
695 {
696 store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap ); // 1 byte
697 if ( _pn.size() )
698 _os.write( _pn.c_str(), _pn.size() ); // size bytes
699 return _pn.size() + 1;
700 }
701
702 template <>
703 inline
704 size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
705 bool _swap )
706 {
707 size_t size;
708
709 restore( _is, size, OMFormat::Chunk::Integer_8, _swap); // 1 byte
710
711 assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
712
713 if ( size > 0 )
714 {
715 char buf[256];
716 _is.read( buf, size ); // size bytes
717 buf[size] = '\0';
718 _pn.resize(size);
719 _pn = buf;
720 }
721 return size+1;
722 }
723
724 //=============================================================================
725 } // namespace IO
726 } // namespace OpenMesh
727 #endif
728 //=============================================================================
729 #if defined(OM_MISSING_HEADER_LIMITS)
730 # undef OM_MISSING_HEADER_LIMITS
731 #endif
732 //=============================================================================
733 #if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
734 # define OPENMESH_IO_OMFORMAT_TEMPLATES
735 # include "OMFormatT.cc"
736 #endif
737 //=============================================================================
738 #endif
739 //=============================================================================