/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
* *
* OpenMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenMesh is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenMesh. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include
// -------------------- STL
#if defined( OM_CC_MIPS )
#include
#include
#else
#include
#include
#endif
#include
// -------------------- OpenMesh
#include
#include
#include
#include
#include
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OMLoader singleton with MeshLoader
_OMWriter_ __OMWriterInstance;
_OMWriter_& OMWriter() { return __OMWriterInstance; }
//=== IMPLEMENTATION ==========================================================
const OMFormat::uchar _OMWriter_::magic_[3] = "OM";
const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(1,2);
_OMWriter_::
_OMWriter_()
{
IOManager().register_module(this);
}
bool
_OMWriter_::write(const std::string& _filename, BaseExporter& _be,
Options _opt, std::streamsize /*_precision*/) const
{
// check whether exporter can give us an OpenMesh BaseKernel
if (!_be.kernel()) return false;
// check for om extension in filename, we can only handle OM
if (_filename.rfind(".om") == std::string::npos)
return false;
_opt += Options::Binary; // only binary format supported
std::ofstream ofs(_filename.c_str(), std::ios::binary);
// check if file is open
if (!ofs.is_open())
{
omerr() << "[OMWriter] : cannot open file " << _filename << std::endl;
return false;
}
// call stream save method
bool rc = write(ofs, _be, _opt);
// close filestream
ofs.close();
// return success/failure notice
return rc;
}
//-----------------------------------------------------------------------------
bool
_OMWriter_::write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize /*_precision*/) const
{
// std::clog << "[OMWriter]::write( stream )\n";
// check exporter features
if ( !check( _be, _opt ) )
{
omerr() << "[OMWriter]: exporter does not support wanted feature!\n";
return false;
}
// Maybe an ascii version will be implemented in the future.
// For now, support only a binary format
if ( !_opt.check( Options::Binary ) )
_opt += Options::Binary;
// Ignore LSB/MSB bit. Always store in LSB (little endian)
_opt += Options::LSB;
_opt -= Options::MSB;
return write_binary(_os, _be, _opt);
}
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
template struct Enabler
{
Enabler( T& obj ) : obj_(obj)
{}
~Enabler() { obj_.enable(); }
T& obj_;
};
#endif
bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
Options _opt) const
{
#ifndef DOXY_IGNORE_THIS
Enabler enabler(omlog());
#endif
omlog() << "[OMWriter] : write binary file\n";
size_t bytes = 0;
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
unsigned int i, nV, nF;
Vec3f v;
Vec2f t;
std::vector vhandles;
// -------------------- write header
OMFormat::Header header;
header.magic_[0] = 'O';
header.magic_[1] = 'M';
header.mesh_ = _be.is_triangle_mesh() ? 'T' : 'P';
header.version_ = version_;
header.n_vertices_ = _be.n_vertices();
header.n_faces_ = _be.n_faces();
header.n_edges_ = _be.n_edges();
bytes += store( _os, header, swap );
// ---------------------------------------- write chunks
OMFormat::Chunk::Header chunk_header;
// -------------------- write vertex data
// ---------- write vertex position
if (_be.n_vertices())
{
v = _be.point(VertexHandle(0));
chunk_header.reserved_ = 0;
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Pos;
chunk_header.signed_ = OMFormat::is_signed(v[0]);
chunk_header.float_ = OMFormat::is_float(v[0]);
chunk_header.dim_ = OMFormat::dim(v);
chunk_header.bits_ = OMFormat::bits(v[0]);
bytes += store( _os, chunk_header, swap );
for (i=0, nV=_be.n_vertices(); istore(_os, swap );
}
else
return false;
#endif
#undef NEW_STYLE
}
// ---------- write face color
if (_be.has_face_colors() && _opt.check( Options::FaceColor ))
{
#define NEW_STYLE 0
#if NEW_STYLE
const BaseProperty *bp = _be.kernel()._get_fprop("f:colors");
if (bp)
{
#endif
Vec3uc c;
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Color;
chunk_header.signed_ = OMFormat::is_signed( c[0] );
chunk_header.float_ = OMFormat::is_float( c[0] );
chunk_header.dim_ = OMFormat::dim( c );
chunk_header.bits_ = OMFormat::bits( c[0] );
bytes += store( _os, chunk_header, swap );
#if !NEW_STYLE
for (i=0, nF=_be.n_faces(); istore(_os, swap);
}
else
return false;
#endif
}
// -------------------- write custom properties
BaseKernel::const_prop_iterator prop;
for (prop = _be.kernel()->vprops_begin();
prop != _be.kernel()->vprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Vertex, swap );
}
for (prop = _be.kernel()->fprops_begin();
prop != _be.kernel()->fprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Face, swap );
}
for (prop = _be.kernel()->eprops_begin();
prop != _be.kernel()->eprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Edge, swap );
}
for (prop = _be.kernel()->hprops_begin();
prop != _be.kernel()->hprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Halfedge, swap );
}
for (prop = _be.kernel()->mprops_begin();
prop != _be.kernel()->mprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Mesh, swap );
}
std::clog << "#bytes written: " << bytes << std::endl;
return true;
}
// ----------------------------------------------------------------------------
size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
const BaseProperty& _bp,
OMFormat::Chunk::Entity _entity,
bool _swap) const
{
omlog() << "Custom Property " << OMFormat::as_string(_entity) << " property ["
<< _bp.name() << "]" << std::endl;
// Don't store if
// 1. it is not persistent
// 2. it's name is empty
if ( !_bp.persistent() || _bp.name().empty() )
{
omlog() << " skipped\n";
return 0;
}
size_t bytes = 0;
OMFormat::Chunk::esize_t element_size = _bp.element_size();
OMFormat::Chunk::Header chdr;
// set header
chdr.name_ = true;
chdr.entity_ = _entity;
chdr.type_ = OMFormat::Chunk::Type_Custom;
chdr.signed_ = 0;
chdr.float_ = 0;
chdr.dim_ = OMFormat::Chunk::Dim_1D; // ignored
chdr.bits_ = element_size;
// write custom chunk
// 1. chunk header
bytes += store( _os, chdr, _swap );
// 2. property name
bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
// 3. block size
bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
omlog() << " n_bytes = " << _bp.size_of() << std::endl;
// 4. data
{
size_t b;
bytes += ( b=_bp.store( _os, _swap ) );
omlog() << " b = " << b << std::endl;
assert( b == _bp.size_of() );
}
return bytes;
}
// ----------------------------------------------------------------------------
size_t _OMWriter_::binary_size(BaseExporter& /* _be */, Options /* _opt */) const
{
// std::clog << "[OMWriter]: binary_size()" << std::endl;
size_t bytes = sizeof( OMFormat::Header );
// !!!TODO!!!
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================