49#if defined( OM_CC_MIPS )
61#include <OpenMesh/Core/IO/OMFormat.hh>
62#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
63#include <OpenMesh/Core/IO/writer/OMWriter.hh>
83const OMFormat::uchar _OMWriter_::magic_[3] =
"OM";
84const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(2,2);
96 const Options& _writeOptions, std::streamsize )
const
99 if (!_be.kernel())
return false;
103 if (_filename.rfind(
".om") == std::string::npos)
106 Options tmpOptions = _writeOptions;
110 std::ofstream ofs(_filename.c_str(), std::ios::binary);
115 omerr() <<
"[OMWriter] : cannot open file " << _filename << std::endl;
120 bool rc =
write(ofs, _be, tmpOptions);
137 Options tmpOptions = _writeOptions;
140 if ( !check( _be, tmpOptions ) )
142 omerr() <<
"[OMWriter]: exporter does not support wanted feature!\n";
157 return write_binary(_os, _be, tmpOptions);
164#ifndef DOXY_IGNORE_THIS
165template <
typename T>
struct Enabler
167 explicit Enabler( T& obj ) : obj_(obj)
170 ~Enabler() { obj_.enable(); }
177bool _OMWriter_::write_binary(std::ostream& _os,
BaseExporter& _be,
178 const Options& _writeOptions)
const
180 #ifndef DOXY_IGNORE_THIS
181 Enabler<mostream> enabler(omlog());
186 const bool swap_required =
189 unsigned int i, nV, nF;
195 OMFormat::Header header;
197 header.magic_[0] =
'O';
198 header.magic_[1] =
'M';
199 header.mesh_ = _be.is_triangle_mesh() ?
'T' :
'P';
200 header.version_ = version_;
201 header.n_vertices_ = int(_be.n_vertices());
202 header.n_faces_ = int(_be.n_faces());
203 header.n_edges_ = int(_be.n_edges());
205 bytes += store( _os, header, swap_required );
209 OMFormat::Chunk::Header chunk_header;
215 if (_be.n_vertices())
217 v = _be.point(VertexHandle(0));
218 chunk_header.reserved_ = 0;
219 chunk_header.name_ =
false;
220 chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
221 chunk_header.type_ = OMFormat::Chunk::Type_Pos;
222 if (_be.is_point_double())
224 chunk_header.signed_ = OMFormat::is_signed(vd[0]);
225 chunk_header.float_ = OMFormat::is_float(vd[0]);
226 chunk_header.dim_ = OMFormat::dim(vd);
227 chunk_header.bits_ = OMFormat::bits(vd[0]);
231 chunk_header.signed_ = OMFormat::is_signed(v[0]);
232 chunk_header.float_ = OMFormat::is_float(v[0]);
233 chunk_header.dim_ = OMFormat::dim(v);
234 chunk_header.bits_ = OMFormat::bits(v[0]);
237 bytes += store( _os, chunk_header, swap_required );
238 if (_be.is_point_double())
239 for (i=0, nV=header.n_vertices_; i<nV; ++i)
240 bytes += vector_store( _os, _be.pointd(VertexHandle(i)), swap_required );
242 for (i=0, nV=header.n_vertices_; i<nV; ++i)
243 bytes += vector_store( _os, _be.point(VertexHandle(i)), swap_required );
250 Vec3f n = _be.normal(VertexHandle(0));
251 Vec3d nd = _be.normald(VertexHandle(0));
253 chunk_header.name_ =
false;
254 chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
255 chunk_header.type_ = OMFormat::Chunk::Type_Normal;
256 if (_be.is_normal_double())
258 chunk_header.signed_ = OMFormat::is_signed(nd[0]);
259 chunk_header.float_ = OMFormat::is_float(nd[0]);
260 chunk_header.dim_ = OMFormat::dim(nd);
261 chunk_header.bits_ = OMFormat::bits(nd[0]);
265 chunk_header.signed_ = OMFormat::is_signed(n[0]);
266 chunk_header.float_ = OMFormat::is_float(n[0]);
267 chunk_header.dim_ = OMFormat::dim(n);
268 chunk_header.bits_ = OMFormat::bits(n[0]);
271 bytes += store( _os, chunk_header, swap_required );
272 if (_be.is_normal_double())
273 for (i=0, nV=header.n_vertices_; i<nV; ++i)
274 bytes += vector_store( _os, _be.normald(VertexHandle(i)), swap_required );
276 for (i=0, nV=header.n_vertices_; i<nV; ++i)
277 bytes += vector_store( _os, _be.normal(VertexHandle(i)), swap_required );
282 if (_be.n_vertices() && _writeOptions.check(
Options::VertexColor ) && _be.has_vertex_colors() )
284 Vec3uc c = _be.color(VertexHandle(0));
286 chunk_header.name_ =
false;
287 chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
288 chunk_header.type_ = OMFormat::Chunk::Type_Color;
289 chunk_header.signed_ = OMFormat::is_signed( c[0] );
290 chunk_header.float_ = OMFormat::is_float( c[0] );
291 chunk_header.dim_ = OMFormat::dim( c );
292 chunk_header.bits_ = OMFormat::bits( c[0] );
294 bytes += store( _os, chunk_header, swap_required );
295 for (i=0, nV=header.n_vertices_; i<nV; ++i)
296 bytes += vector_store( _os, _be.color(VertexHandle(i)), swap_required );
302 t = _be.texcoord(VertexHandle(0));
304 chunk_header.name_ =
false;
305 chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
306 chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
307 chunk_header.signed_ = OMFormat::is_signed(t[0]);
308 chunk_header.float_ = OMFormat::is_float(t[0]);
309 chunk_header.dim_ = OMFormat::dim(t);
310 chunk_header.bits_ = OMFormat::bits(t[0]);
312 bytes += store(_os, chunk_header, swap_required);
314 for (i = 0, nV = header.n_vertices_; i < nV; ++i)
315 bytes += vector_store(_os, _be.texcoord(VertexHandle(i)), swap_required);
322 chunk_header.reserved_ = 0;
323 chunk_header.name_ =
false;
324 chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
325 chunk_header.type_ = OMFormat::Chunk::Type_Topology;
326 chunk_header.signed_ =
true;
327 chunk_header.float_ =
true;
328 chunk_header.dim_ = OMFormat::Chunk::Dim_3D;
329 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
331 bytes += store( _os, chunk_header, swap_required );
332 auto nE=header.n_edges_*2;
335 auto next_id = _be.get_next_halfedge_id(HalfedgeHandle(
static_cast<int>(i)));
336 auto to_vertex_id = _be.get_to_vertex_id(HalfedgeHandle(
static_cast<int>(i)));
337 auto face_id = _be.get_face_id(HalfedgeHandle(
static_cast<int>(i)));
339 bytes += store( _os, next_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap_required );
340 bytes += store( _os, to_vertex_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap_required );
341 bytes += store( _os, face_id, OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap_required );
347 if (_OMWriter_::version_ > OMFormat::mk_version(2,1) && _be.n_edges() && _writeOptions.check(
Options::FaceTexCoord))
350 t = _be.texcoord(HalfedgeHandle(0));
352 chunk_header.name_ =
false;
353 chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
354 chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
355 chunk_header.signed_ = OMFormat::is_signed(t[0]);
356 chunk_header.float_ = OMFormat::is_float(t[0]);
357 chunk_header.dim_ = OMFormat::dim(t);
358 chunk_header.bits_ = OMFormat::bits(t[0]);
360 bytes += store(_os, chunk_header, swap_required);
363 for (i = 0, nHE = header.n_edges_*2; i < nHE; ++i)
364 bytes += vector_store(_os, _be.texcoord(HalfedgeHandle(i)), swap_required);
370 if (_be.n_vertices())
372 chunk_header.reserved_ = 0;
373 chunk_header.name_ =
false;
374 chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
375 chunk_header.type_ = OMFormat::Chunk::Type_Topology;
376 chunk_header.signed_ =
true;
377 chunk_header.float_ =
true;
378 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
379 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
381 bytes += store( _os, chunk_header, swap_required );
382 for (i=0, nV=header.n_vertices_; i<nV; ++i)
383 bytes += store( _os, _be.get_halfedge_id(VertexHandle(i)), OMFormat::Chunk::Integer_Size(chunk_header.bits_), swap_required );
391 chunk_header.name_ =
false;
392 chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
393 chunk_header.type_ = OMFormat::Chunk::Type_Topology;
394 chunk_header.signed_ =
true;
395 chunk_header.float_ =
true;
396 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
397 chunk_header.bits_ = OMFormat::needed_bits(_be.n_edges()*4);
399 bytes += store( _os, chunk_header, swap_required );
401 for (i=0, nF=header.n_faces_; i<nF; ++i)
403 auto size = OMFormat::Chunk::Integer_Size(chunk_header.bits_);
404 bytes += store( _os, _be.get_halfedge_id(FaceHandle(i)), size, swap_required);
414 const BaseProperty *bp = _be.kernel()._get_fprop(
"f:normals");
419 Vec3f n = _be.normal(FaceHandle(0));
420 Vec3d nd = _be.normald(FaceHandle(0));
422 chunk_header.name_ =
false;
423 chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
424 chunk_header.type_ = OMFormat::Chunk::Type_Normal;
426 if (_be.is_normal_double())
428 chunk_header.signed_ = OMFormat::is_signed(nd[0]);
429 chunk_header.float_ = OMFormat::is_float(nd[0]);
430 chunk_header.dim_ = OMFormat::dim(nd);
431 chunk_header.bits_ = OMFormat::bits(nd[0]);
435 chunk_header.signed_ = OMFormat::is_signed(n[0]);
436 chunk_header.float_ = OMFormat::is_float(n[0]);
437 chunk_header.dim_ = OMFormat::dim(n);
438 chunk_header.bits_ = OMFormat::bits(n[0]);
441 bytes += store( _os, chunk_header, swap_required );
443 if (_be.is_normal_double())
444 for (i=0, nF=header.n_faces_; i<nF; ++i)
445 bytes += vector_store( _os, _be.normald(FaceHandle(i)), swap_required );
447 for (i=0, nF=header.n_faces_; i<nF; ++i)
448 bytes += vector_store( _os, _be.normal(FaceHandle(i)), swap_required );
451 bytes += bp->store(_os, swap );
462 if (_be.n_faces() && _be.has_face_colors() && _writeOptions.check(
Options::FaceColor ))
466 const BaseProperty *bp = _be.kernel()._get_fprop(
"f:colors");
473 chunk_header.name_ =
false;
474 chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
475 chunk_header.type_ = OMFormat::Chunk::Type_Color;
476 chunk_header.signed_ = OMFormat::is_signed( c[0] );
477 chunk_header.float_ = OMFormat::is_float( c[0] );
478 chunk_header.dim_ = OMFormat::dim( c );
479 chunk_header.bits_ = OMFormat::bits( c[0] );
481 bytes += store( _os, chunk_header, swap_required );
483 for (i=0, nF=header.n_faces_; i<nF; ++i)
484 bytes += vector_store( _os, _be.color(FaceHandle(i)), swap_required );
486 bytes += bp->store(_os, swap);
494 if (_be.n_vertices() && _be.has_vertex_status() && _writeOptions.check(
Options::Status))
496 auto s = _be.status(VertexHandle(0));
497 chunk_header.name_ =
false;
498 chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
499 chunk_header.type_ = OMFormat::Chunk::Type_Status;
500 chunk_header.signed_ =
false;
501 chunk_header.float_ =
false;
502 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
503 chunk_header.bits_ = OMFormat::bits(s);
506 bytes += store(_os, chunk_header, swap_required);
508 for (i = 0, nV = header.n_vertices_; i < nV; ++i)
509 bytes += store(_os, _be.status(VertexHandle(i)), swap_required);
513 if (_be.n_edges() && _be.has_edge_status() && _writeOptions.check(
Options::Status))
515 auto s = _be.status(EdgeHandle(0));
516 chunk_header.name_ =
false;
517 chunk_header.entity_ = OMFormat::Chunk::Entity_Edge;
518 chunk_header.type_ = OMFormat::Chunk::Type_Status;
519 chunk_header.signed_ =
false;
520 chunk_header.float_ =
false;
521 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
522 chunk_header.bits_ = OMFormat::bits(s);
525 bytes += store(_os, chunk_header, swap_required);
527 for (i = 0, nV = header.n_edges_; i < nV; ++i)
528 bytes += store(_os, _be.status(EdgeHandle(i)), swap_required);
532 if (_be.n_edges() && _be.has_halfedge_status() && _writeOptions.check(
Options::Status))
534 auto s = _be.status(HalfedgeHandle(0));
535 chunk_header.name_ =
false;
536 chunk_header.entity_ = OMFormat::Chunk::Entity_Halfedge;
537 chunk_header.type_ = OMFormat::Chunk::Type_Status;
538 chunk_header.signed_ =
false;
539 chunk_header.float_ =
false;
540 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
541 chunk_header.bits_ = OMFormat::bits(s);
544 bytes += store(_os, chunk_header, swap_required);
546 for (i = 0, nV = header.n_edges_ * 2; i < nV; ++i)
547 bytes += store(_os, _be.status(HalfedgeHandle(i)), swap_required);
551 if (_be.n_faces() && _be.has_face_status() && _writeOptions.check(
Options::Status))
553 auto s = _be.status(FaceHandle(0));
554 chunk_header.name_ =
false;
555 chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
556 chunk_header.type_ = OMFormat::Chunk::Type_Status;
557 chunk_header.signed_ =
false;
558 chunk_header.float_ =
false;
559 chunk_header.dim_ = OMFormat::Chunk::Dim_1D;
560 chunk_header.bits_ = OMFormat::bits(s);
563 bytes += store(_os, chunk_header, swap_required);
565 for (i = 0, nV = header.n_faces_; i < nV; ++i)
566 bytes += store(_os, _be.status(FaceHandle(i)), swap_required);
573 const auto store_property = [
this, &_os, swap_required, &bytes](
576 const OMFormat::Chunk::Entity _ent)
578 for (
auto prop = _it_begin; prop != _it_end; ++prop)
580 if (!*prop || (*prop)->name().empty() ||
581 ((*prop)->name().size() > 1 && (*prop)->name()[1] ==
':'))
585 bytes += store_binary_custom_chunk(_os, **prop, _ent, swap_required);
589 store_property(_be.kernel()->vprops_begin(), _be.kernel()->vprops_end(),
590 OMFormat::Chunk::Entity_Vertex);
591 store_property(_be.kernel()->fprops_begin(), _be.kernel()->fprops_end(),
592 OMFormat::Chunk::Entity_Face);
593 store_property(_be.kernel()->eprops_begin(), _be.kernel()->eprops_end(),
594 OMFormat::Chunk::Entity_Edge);
595 store_property(_be.kernel()->hprops_begin(), _be.kernel()->hprops_end(),
596 OMFormat::Chunk::Entity_Halfedge);
597 store_property(_be.kernel()->mprops_begin(), _be.kernel()->mprops_end(),
598 OMFormat::Chunk::Entity_Mesh);
601 memset(&chunk_header, 0,
sizeof(chunk_header));
602 chunk_header.name_ =
false;
603 chunk_header.entity_ = OMFormat::Chunk::Entity_Sentinel;
604 bytes += store(_os, chunk_header, swap_required);
606 omlog() <<
"#bytes written: " << bytes << std::endl;
613size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
615 OMFormat::Chunk::Entity _entity,
624 if ( !_bp.persistent() || _bp.name().empty() )
632 OMFormat::Chunk::esize_t element_size = OMFormat::Chunk::esize_t(_bp.element_size());
633 OMFormat::Chunk::Header chdr;
637 chdr.entity_ = _entity;
638 chdr.type_ = OMFormat::Chunk::Type_Custom;
641 chdr.dim_ = OMFormat::Chunk::Dim_1D;
642 chdr.bits_ = element_size;
648 bytes += store( _os, chdr, _swap );
651 bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
654 if(_OMWriter_::version_ > OMFormat::mk_version(2,1))
656 OMFormat::Chunk::PropertyName type = OMFormat::Chunk::PropertyName(_bp.get_storage_name());
657 bytes += store(_os, type, _swap);
661 bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
667 bytes += ( b=_bp.store( _os, _swap ) );
668 assert(b == _bp.size_of());
678 size_t bytes =
sizeof( OMFormat::Header );
PropertyContainer::const_iterator const_prop_iterator
@ MSB
big endian (Motorola's 68x family, DEC Alpha, MIPS)
static Type local()
Return endian type of host system.
Set options for reader/writer modules.
@ FaceNormal
Has (r) / store (w) face normals.
@ Swap
Swap byte order in binary mode.
@ FaceColor
Has (r) / store (w) face colors.
@ FaceTexCoord
Has (r) / store (w) face texture coordinates.
@ MSB
Assume big endian byte ordering.
@ Binary
Set binary mode for r/w.
@ Status
Has (r) / store (w) status properties.
@ LSB
Assume little endian byte ordering.
@ VertexNormal
Has (r) / store (w) vertex normals.
@ VertexTexCoord
Has (r) / store (w) texture coordinates.
@ VertexColor
Has (r) / store (w) vertex colors.
@ Custom
Has (r) / store (w) custom properties marked persistent (currently PLY only supports reading and only...
bool register_module(BaseReader *_bl)
bool write(std::ostream &, BaseExporter &, const Options &_writeOptions, std::streamsize _precision=6) const override
size_t binary_size(BaseExporter &_be, const Options &_opt) const override
Returns expected size of file if binary format is supported else 0.
_OMWriter_ __OMWriterInstance
Declare the single entity of the OM writer.
_IOManager_ & IOManager()