First checkin for OpenMesh 2.0

git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
Jan Möbius
2009-02-06 13:37:46 +00:00
parent c3321ebdd9
commit 97f515985d
417 changed files with 76182 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Config
#==============================================================================
SUBDIRS = $(call find-subdirs)
PACKAGES :=
PROJ_LIBS :=
MODULES := cxxlib
#== SYSTEM PART -- DON'T TOUCH ==============================================
include $(ACGMAKE)/Rules
#==============================================================================

View File

@@ -0,0 +1,113 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=== INCLUDES ================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <algorithm>
#include <string>
#include <iterator>
#if defined(OM_CC_MIPS)
# include <ctype.h>
#else
# include <cctype>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
static inline char tolower(char c)
{
using namespace std;
return ::tolower(c);
}
//-----------------------------------------------------------------------------
bool
BaseReader::
can_u_read(const std::string& _filename) const
{
// get file extension
std::string extension;
std::string::size_type pos(_filename.rfind("."));
if (pos != std::string::npos)
{
extension = _filename.substr(pos+1, _filename.length()-pos-1);
std::transform( extension.begin(), extension.end(),
extension.begin(), tolower );
}
// locate extension in extension string
return (get_extensions().find(extension) != std::string::npos);
}
//-----------------------------------------------------------------------------
bool
BaseReader::
check_extension(const std::string& _fname, const std::string& _ext) const
{
std::string cmpExt(_ext);
std::transform( _ext.begin(), _ext.end(), cmpExt.begin(), tolower );
std::string::size_type pos(_fname.rfind("."));
if (pos != std::string::npos && !_ext.empty() )
{
std::string ext;
// extension without dot!
ext = _fname.substr(pos+1, _fname.length()-pos-1);
std::transform( ext.begin(), ext.end(), ext.begin(), tolower );
return ext == cmpExt;
}
return false;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@@ -0,0 +1,113 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager file access modules
//
//=============================================================================
#ifndef __BASEREADER_HH__
#define __BASEREADER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iostream>
#include <string>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/Utils/SingletonT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Base class for reader modules.
Reader modules access persistent data and pass them to the desired
data structure by the means of a BaseImporter derivative.
All reader modules must be derived from this class.
*/
class BaseReader
{
public:
/// Returns a brief description of the file type that can be parsed.
virtual std::string get_description() const = 0;
/** Returns a string with the accepted file extensions separated by a
whitespace and in small caps.
*/
virtual std::string get_extensions() const = 0;
/// Return magic bits used to determine file format
virtual std::string get_magic() const { return std::string(""); }
/** Reads a mesh given by a filename. Usually this method opens a stream
and passes it to stream read method. Acceptance checks by filename
extension can be placed here.
Options can be passed via _opt. After execution _opt contains the Options
that were available
*/
virtual bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt) = 0;
/// Returns true if reader can parse _filename (checks extension)
virtual bool can_u_read(const std::string& _filename) const;
protected:
// case insensitive search for _ext in _fname.
bool check_extension(const std::string& _fname,
const std::string& _ext) const;
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

472
Core/IO/reader/OBJReader.cc Normal file
View File

@@ -0,0 +1,472 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/IO/reader/OBJReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
// STL
#if defined(OM_CC_MIPS)
# include <ctype.h>
/// \bug Workaround for STLPORT 4.6: isspace seems not to be in namespace std!
#elif defined(_STLPORT_VERSION) && (_STLPORT_VERSION==0x460)
# include <cctype>
#else
# include <cctype>
using std::isspace;
#endif
#ifndef WIN32
#include <string.h>
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
_OBJReader_ __OBJReaderInstance;
_OBJReader_& OBJReader() { return __OBJReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OBJReader_::
_OBJReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
std::fstream in( _filename.c_str(), std::ios_base::in );
if (!in)
{
omerr() << "[OBJReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
{
#if defined(WIN32)
std::string::size_type dot = _filename.find_last_of("\\/");
#else
std::string::size_type dot = _filename.rfind("/");
#endif
path_ = (dot == std::string::npos)
? "./"
: std::string(_filename.substr(0,dot+1));
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read_material(std::fstream& _in)
{
std::string line;
std::string keyWrd;
std::string key;
Material mat;
float f1,f2,f3;
bool indef = false;
mat.cleanup();
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
if ( line.empty() )
continue;
std::stringstream stream(line);
stream >> keyWrd;
if( isspace(line[0]) || line[0] == '#' )
{
if (indef && !key.empty() && mat.is_valid())
{
materials_[key] = mat;
mat.cleanup();
}
}
else if (keyWrd == "newmtl") // begin new material definition
{
stream >> key;
indef = true;
}
else if (keyWrd == "Kd") // diffuse color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Kd(f1,f2,f3);
}
else if (keyWrd == "Ka") // ambient color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Ka(f1,f2,f3);
}
else if (keyWrd == "Ks") // specular color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Ks(f1,f2,f3);
}
#if 0
else if (keyWrd == "illum") // diffuse/specular shading model
{
; // just skip this
}
else if (keyWrd == "Ns") // Shininess [0..200]
{
; // just skip this
}
else if (keyWrd == "map_") // map images
{
// map_Kd, diffuse map
// map_Ks, specular map
// map_Ka, ambient map
// map_Bump, bump map
// map_d, opacity map
; // just skip this
}
#endif
else if (keyWrd == "Tr") // transparency value
{
stream >> f1;
if( !stream.fail() )
mat.set_Tr(f1);
}
else if (keyWrd == "d") // transparency value
{
stream >> f1;
if( !stream.fail() )
mat.set_Tr(f1);
}
if ( _in && indef && mat.is_valid() && !key.empty())
materials_[key] = mat;
}
return true;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read(std::fstream& _in, BaseImporter& _bi, Options& _opt)
{
omlog() << "[OBJReader] : read file\n";
std::string line;
std::string keyWrd;
float x, y, z, u, v;
BaseImporter::VHandles vhandles;
std::vector<Vec3f> normals;
std::vector<Vec2f> texcoords;
std::map<std::string,Material> materials;
std::string matname;
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
// comment
if ( line.size() == 0 || line[0] == '#' || isspace(line[0]) ) {
continue;
}
std::stringstream stream(line);
stream >> keyWrd;
// material file
if (keyWrd == "mtllib")
{
std::string matFile;
stream >> matFile;
matFile = path_ + matFile;
omlog() << "Load material file " << matFile << std::endl;
std::fstream matStream( matFile.c_str(), std::ios_base::in );
if ( matStream ){
if ( !read_material( matStream ) )
omerr() << " Warning! Could not read file properly!\n";
matStream.close();
omlog() << " " << materials_.size() << " materials loaded.\n";
}else
omerr() << " Warning! Material file '" << matFile << "' not found!\n";
}
// usemtl
else if (keyWrd == "usemtl")
{
stream >> matname;
if (materials_.find(matname)==materials_.end())
{
omerr() << "Warning! Material '" << matname
<< "' not defined in material file.\n";
matname="";
}
}
// vertex
else if (keyWrd == "v")
{
stream >> x; stream >> y; stream >> z;
if ( !stream.fail() )
_bi.add_vertex(OpenMesh::Vec3f(x,y,z));
}
// texture coord
else if (keyWrd == "vt")
{
stream >> u; stream >> v;
if ( !stream.fail() ){
texcoords.push_back(OpenMesh::Vec2f(u, v));
_opt += Options::VertexTexCoord;
}else{
omerr() << "Only single 2D texture coordinate per vertex"
<< "allowed!" << std::endl;
return false;
}
}
// normal
else if (keyWrd == "vn")
{
stream >> x; stream >> y; stream >> z;
if ( !stream.fail() ){
normals.push_back(OpenMesh::Vec3f(x,y,z));
_opt += Options::VertexNormal;
}
}
// face
else if (keyWrd == "f")
{
int component(0), nV(0);
int value;
vhandles.clear();
// read full line after detecting a face
std::string faceLine;
std::getline(stream,faceLine);
std::stringstream lineData( faceLine );
// work on the line until nothing left to read
while ( !lineData.eof() )
{
// read one block from the line ( vertex/texCoord/normal )
std::string vertex;
lineData >> vertex;
do{
//get the component (vertex/texCoord/normal)
size_t found=vertex.find("/");
// parts are seperated by '/' So if no '/' found its the last component
if( found != std::string::npos ){
// read the index value
std::stringstream tmp( vertex.substr(0,found) );
// If we get an empty string this property is undefined in the file
if ( vertex.substr(0,found).empty() ) {
// Switch to next field
vertex = vertex.substr(found+1);
// Now we are at the next component
++component;
// Skip further processing of this component
continue;
}
// Read current value
tmp >> value;
// remove the read part from the string
vertex = vertex.substr(found+1);
} else {
// last component of the vertex, read it.
std::stringstream tmp( vertex );
tmp >> value;
// Nothing to read here ( garbage at end of line )
if ( tmp.fail() ) {
continue;
}
}
// store the component ( each component is referenced by the index here! )
switch (component)
{
case 0: // vertex
if ( value < 0 ) {
// std::cerr << "Handling negativ vertex index value" << std::endl;
value = _bi.n_vertices() + value + 1;
}
vhandles.push_back(VertexHandle(value-1));
break;
case 1: // texture coord
if ( value < 0 ) {
// std::cerr << "Handling negativ texture coordinate index value)" << std::endl;
value = _bi.n_vertices() + value + 1;
}
assert(!vhandles.empty());
assert((unsigned int)(value-1) < texcoords.size());
_bi.set_texcoord(vhandles.back(), texcoords[value-1]);
break;
case 2: // normal
if ( value < 0 ) {
// std::cerr << "Handling negativ normal index value)" << std::endl;
value = _bi.n_vertices() + value + 1;
}
assert(!vhandles.empty());
assert((unsigned int)(value-1) < normals.size());
_bi.set_normal(vhandles.back(), normals[value-1]);
break;
}
// Prepare for reading next component
++component;
} while ( vertex.find("/") != std::string::npos );
component = 0;
nV++;
}
size_t n_faces = _bi.n_faces();
FaceHandle fh = _bi.add_face(vhandles);
if ( !matname.empty() && materials_[matname].has_Kd() )
{
std::vector<FaceHandle> newfaces;
for( size_t i=0; i < _bi.n_faces()-n_faces; ++i )
newfaces.push_back(FaceHandle(n_faces+i));
Material & mat = materials_[matname];
Vec3uc fc = color_cast<Vec3uc, Vec3f>(mat.Kd());
for (std::vector<FaceHandle>::iterator it = newfaces.begin();
it != newfaces.end(); ++it)
_bi.set_color( *it, fc );
_opt += Options::FaceColor;
}
}
}
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

159
Core/IO/reader/OBJReader.hh Normal file
View File

@@ -0,0 +1,159 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an reader module for OBJ files
//
//=============================================================================
#ifndef __OBJREADER_HH__
#define __OBJREADER_HH__
//=== INCLUDES ================================================================
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OBJ format reader.
*/
class _OBJReader_ : public BaseReader
{
public:
_OBJReader_();
virtual ~_OBJReader_() { }
std::string get_description() const { return "Alias/Wavefront"; }
std::string get_extensions() const { return "obj"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
private:
#ifndef DOXY_IGNORE_THIS
class Material
{
public:
Material() { cleanup(); }
void cleanup()
{
Kd_is_set_ = false;
Ka_is_set_ = false;
Ks_is_set_ = false;
Tr_is_set_ = false;
}
bool is_valid(void) const
{ return Kd_is_set_ || Ka_is_set_ || Ks_is_set_ || Tr_is_set_; }
bool has_Kd(void) { return Kd_is_set_; }
bool has_Ka(void) { return Ka_is_set_; }
bool has_Ks(void) { return Ks_is_set_; }
bool has_Tr(void) { return Tr_is_set_; }
void set_Kd( float r, float g, float b )
{ Kd_=Vec3f(r,g,b); Kd_is_set_=true; }
void set_Ka( float r, float g, float b )
{ Ka_=Vec3f(r,g,b); Ka_is_set_=true; }
void set_Ks( float r, float g, float b )
{ Ks_=Vec3f(r,g,b); Ks_is_set_=true; }
void set_Tr( float t )
{ Tr_=t; Tr_is_set_=true; }
const Vec3f& Kd( void ) const { return Kd_; }
const Vec3f& Ka( void ) const { return Ka_; }
const Vec3f& Ks( void ) const { return Ks_; }
float Tr( void ) const { return Tr_; }
private:
Vec3f Kd_; bool Kd_is_set_; // diffuse
Vec3f Ka_; bool Ka_is_set_; // ambient
Vec3f Ks_; bool Ks_is_set_; // specular
float Tr_; bool Tr_is_set_; // transperency
};
#endif
typedef std::map<std::string, Material> MaterialList;
MaterialList materials_;
bool read_material( std::fstream& _in );
private:
bool read(std::fstream& _in, BaseImporter& _bi, Options& _opt);
std::string path_;
};
//== TYPE DEFINITION ==========================================================
extern _OBJReader_ __OBJReaderInstance;
_OBJReader_& OBJReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

597
Core/IO/reader/OFFReader.cc Normal file
View File

@@ -0,0 +1,597 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#define LINE_LEN 4096
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/reader/OFFReader.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
// #include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
//STL
#include <fstream>
#include <memory>
#ifndef WIN32
#include <string.h>
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//=== INSTANCIATE =============================================================
_OFFReader_ __OFFReaderInstance;
_OFFReader_& OFFReader() { return __OFFReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OFFReader_::_OFFReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read(const std::string& _filename, BaseImporter& _bi,
Options& _opt)
{
std::fstream in(_filename.c_str(), (options_.is_binary() ? std::ios_base::binary | std::ios_base::in
: std::ios_base::in) );
if (!in)
{
omerr() << "[OFFReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const
{
// filter relevant options for reading
bool swap = _opt.check( Options::Swap );
userOptions_ = _opt;
// build options to be returned
_opt.clear();
if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) _opt += Options::VertexNormal;
if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) _opt += Options::VertexTexCoord;
if (options_.vertex_has_color() && userOptions_.vertex_has_color()) _opt += Options::VertexColor;
if (options_.face_has_color() && userOptions_.face_has_color()) _opt += Options::FaceColor;
if (options_.is_binary()) _opt += Options::Binary;
//force user-choice for the alpha value when reading binary
if ( options_.is_binary() && userOptions_.color_has_alpha() )
options_ += Options::ColorAlpha;
return (options_.is_binary() ?
read_binary(_in, _bi, swap) :
read_ascii(_in, _bi));
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read_ascii(std::fstream& _in, BaseImporter& _bi) const
{
omlog() << "[OFFReader] : read ascii file\n";
unsigned int i, j, k, l, idx;
unsigned int nV, nF, dummy;
OpenMesh::Vec3f v, n;
OpenMesh::Vec2f t;
OpenMesh::Vec3i c3;
OpenMesh::Vec3f c3f;
OpenMesh::Vec4i c4;
OpenMesh::Vec4f c4f;
BaseImporter::VHandles vhandles;
VertexHandle vh;
// read header line
std::string header;
std::getline(_in,header);
// + #Vertice, #Faces, #Edges
_in >> nV;
_in >> nF;
_in >> dummy;
_bi.reserve(nV, 3*nV, nF);
// read vertices: coord [hcoord] [normal] [color] [texcoord]
for (i=0; i<nV && !_in.eof(); ++i)
{
// Always read VERTEX
_in >> v[0]; _in >> v[1]; _in >> v[2];
vh = _bi.add_vertex(v);
//perhaps read NORMAL
if ( options_.vertex_has_normal() ){
_in >> n[0]; _in >> n[1]; _in >> n[2];
if ( userOptions_.vertex_has_normal() )
_bi.set_normal(vh, n);
}
//take the rest of the line and check how colors are defined
std::string line;
std::getline(_in,line);
int colorType = getColorType(line, options_.vertex_has_texcoord() );
std::stringstream stream( line );
//perhaps read COLOR
if ( options_.vertex_has_color() ){
std::string trash;
switch (colorType){
case 0 : break; //no color
case 1 : stream >> trash; break; //one int (isn't handled atm)
case 2 : stream >> trash; stream >> trash; break; //corrupt format (ignore)
// rgb int
case 3 : stream >> c3[0]; stream >> c3[1]; stream >> c3[2];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec3uc( c3 ) );
break;
// rgba int
case 4 : stream >> c4[0]; stream >> c4[1]; stream >> c4[2]; stream >> c4[3];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec4uc( c4 ) );
break;
// rgb floats
case 5 : stream >> c3f[0]; stream >> c3f[1]; stream >> c3f[2];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, color_cast<Vec3uc, Vec3f>(c3f) );
break;
// rgba floats
case 6 : stream >> c4f[0]; stream >> c4f[1]; stream >> c4f[2]; stream >> c4f[3];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, color_cast<Vec4uc, Vec4f>(c4f) );
break;
default:
std::cerr << "Error in file format (colorType = " << colorType << ")\n";
}
}
//perhaps read TEXTURE COORDs
if ( options_.vertex_has_texcoord() ){
stream >> t[0]; stream >> t[1];
if ( userOptions_.vertex_has_texcoord() )
_bi.set_texcoord(vh, t);
}
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
for (i=0; i<nF; ++i)
{
// nV = number of Vertices for current face
_in >> nV;
if (nV == 3)
{
vhandles.resize(3);
_in >> j;
_in >> k;
_in >> l;
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
_in >> idx;
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
//perhaps read face COLOR
if ( options_.face_has_color() ){
//take the rest of the line and check how colors are defined
std::string line;
std::getline(_in,line);
int colorType = getColorType(line, false );
std::stringstream stream( line );
std::string trash;
switch (colorType){
case 0 : break; //no color
case 1 : stream >> trash; break; //one int (isn't handled atm)
case 2 : stream >> trash; stream >> trash; break; //corrupt format (ignore)
// rgb int
case 3 : stream >> c3[0]; stream >> c3[1]; stream >> c3[2];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec3uc( c3 ) );
break;
// rgba int
case 4 : stream >> c4[0]; stream >> c4[1]; stream >> c4[2]; stream >> c4[3];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec4uc( c4 ) );
break;
// rgb floats
case 5 : stream >> c3f[0]; stream >> c3f[1]; stream >> c3f[2];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, color_cast<Vec3uc, Vec3f>(c3f) );
break;
// rgba floats
case 6 : stream >> c4f[0]; stream >> c4f[1]; stream >> c4f[2]; stream >> c4f[3];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, color_cast<Vec4uc, Vec4f>(c4f) );
break;
default:
std::cerr << "Error in file format (colorType = " << colorType << ")\n";
}
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
int _OFFReader_::getColorType(std::string& _line, bool _texCoordsAvailable) const
{
/*
0 : no Color
1 : one int (e.g colormap index)
2 : two items (error!)
3 : 3 ints
4 : 3 ints
5 : 3 floats
6 : 4 floats
*/
// Check if we have any additional information here
if ( _line.size() < 1 )
return 0;
//first remove spaces at start/end of the line
while (_line[0] == ' ')
_line = _line.substr(1);
while (_line[ _line.length()-1 ] == ' ')
_line = _line.substr(0, _line.length()-2);
//count the remaining items in the line
size_t found;
int count = 0;
found=_line.find_first_of(" ");
while (found!=std::string::npos){
count++;
found=_line.find_first_of(" ",found+1);
}
if (_line != "") count++;
if (_texCoordsAvailable) count -= 2;
if (count == 3 || count == 4){
//get first item
found = _line.find(" ");
std::string c1 = _line.substr (0,found);
if (c1.find(".") != std::string::npos){
if (count == 3)
count = 5;
else
count = 6;
}
}
return count;
}
void _OFFReader_::readValue(std::fstream& _in, float& _value) const{
float32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
void _OFFReader_::readValue(std::fstream& _in, int& _value) const{
uint32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
void _OFFReader_::readValue(std::fstream& _in, unsigned int& _value) const{
uint32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
bool
_OFFReader_::read_binary(std::fstream& _in, BaseImporter& _bi, bool /*_swap*/) const
{
omlog() << "[OFFReader] : read binary file\n";
unsigned int i, j, k, l, idx;
unsigned int nV, nF, dummy;
OpenMesh::Vec3f v, n;
OpenMesh::Vec3i c;
OpenMesh::Vec4i cA;
OpenMesh::Vec2f t;
BaseImporter::VHandles vhandles;
VertexHandle vh;
// read header line
std::string header;
std::getline(_in,header);
// + #Vertice, #Faces, #Edges
readValue(_in, nV);
readValue(_in, nF);
readValue(_in, dummy);
_bi.reserve(nV, 3*nV, nF);
// read vertices: coord [hcoord] [normal] [color] [texcoord]
for (i=0; i<nV && !_in.eof(); ++i)
{
// Always read Vertex
readValue(_in, v[0]);
readValue(_in, v[1]);
readValue(_in, v[2]);
vh = _bi.add_vertex(v);
if ( options_.vertex_has_normal() ) {
readValue(_in, n[0]);
readValue(_in, n[1]);
readValue(_in, n[2]);
if ( userOptions_.vertex_has_normal() )
_bi.set_normal(vh, n);
}
if ( options_.vertex_has_color() ) {
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cA[0]);
readValue(_in, cA[1]);
readValue(_in, cA[2]);
readValue(_in, cA[3]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec4uc( cA ) );
}else{
//without alpha
readValue(_in, c[0]);
readValue(_in, c[1]);
readValue(_in, c[2]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec3uc( c ) );
}
}
if ( options_.vertex_has_texcoord()) {
readValue(_in, t[0]);
readValue(_in, t[1]);
if ( userOptions_.vertex_has_texcoord() )
_bi.set_texcoord(vh, t);
}
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
// So far color spec is unsupported!
for (i=0; i<nF; ++i)
{
readValue(_in, nV);
if (nV == 3)
{
vhandles.resize(3);
readValue(_in, j);
readValue(_in, k);
readValue(_in, l);
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
readValue(_in, idx);
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
//face color
if ( options_.face_has_color() ) {
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cA[0]);
readValue(_in, cA[1]);
readValue(_in, cA[2]);
readValue(_in, cA[3]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh , Vec4uc( cA ) );
}else{
//without alpha
readValue(_in, c[0]);
readValue(_in, c[1]);
readValue(_in, c[2]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec3uc( c ) );
}
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool _OFFReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if (BaseReader::can_u_read(_filename))
{
std::ifstream ifs(_filename.c_str());
if (ifs.is_open() && can_u_read(ifs))
{
ifs.close();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
bool _OFFReader_::can_u_read(std::istream& _is) const
{
options_.cleanup();
// read 1st line
char line[LINE_LEN], *p;
_is.getline(line, LINE_LEN);
p = line;
int remainingChars = _is.gcount();
bool vertexDimensionTooHigh = false;
// check header: [ST][C][N][4][n]OFF BINARY
if ( ( remainingChars > 1 ) && ( p[0] == 'S' && p[1] == 'T') )
{ options_ += Options::VertexTexCoord; p += 2; remainingChars -= 2; }
if ( ( remainingChars > 0 ) && ( p[0] == 'C') )
{ options_ += Options::VertexColor;
options_ += Options::FaceColor; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && ( p[0] == 'N') )
{ options_ += Options::VertexNormal; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && (p[0] == '4' ) )
{ vertexDimensionTooHigh = true; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && ( p[0] == 'n') )
{ vertexDimensionTooHigh = true; ++p; --remainingChars; }
if ( ( remainingChars < 3 ) || (!(p[0] == 'O' && p[1] == 'F' && p[2] == 'F') ) )
return false;
p += 4;
remainingChars -= 4;
if ( ( remainingChars >= 6 ) && ( strncmp(p, "BINARY", 6) == 0 ) )
options_+= Options::Binary;
// vertex Dimensions != 3 are currently not supported
if (vertexDimensionTooHigh)
return false;
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

150
Core/IO/reader/OFFReader.hh Normal file
View File

@@ -0,0 +1,150 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __OFFREADER_HH__
#define __OFFREADER_HH__
//=== INCLUDES ================================================================
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#ifndef WIN32
#include <string.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OFF format reader. This class is singleton'ed by
SingletonT to OFFReader.
By passing Options to the read function you can manipulate the reading behavoir.
The following options can be set:
VertexNormal
VertexColor
VertexTexCoord
FaceColor
ColorAlpha [only when reading binary]
These options define if the corresponding data should be read (if available)
or if it should be omitted.
After execution of the read function. The options object contains information about
what was actually read.
e.g. if VertexNormal was true when the read function was called, but the file
did not contain vertex normals then it is false afterwards.
When reading a binary off with Color Flag in the header it is assumed that all vertices
and faces have colors in the format "int int int".
If ColorAlpha is set the format "int int int int" is assumed.
*/
class _OFFReader_ : public BaseReader
{
public:
_OFFReader_();
std::string get_description() const { return "Object File Format"; }
std::string get_extensions() const { return "off"; }
std::string get_magic() const { return "OFF"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool can_u_read(const std::string& _filename) const;
private:
bool can_u_read(std::istream& _is) const;
bool read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const;
bool read_ascii(std::fstream& _in, BaseImporter& _bi) const;
bool read_binary(std::fstream& _in, BaseImporter& _bi, bool swap) const;
void readValue(std::fstream& _in, float& _value) const;
void readValue(std::fstream& _in, int& _value) const;
void readValue(std::fstream& _in, unsigned int& _value) const;
int getColorType(std::string & _line, bool _texCoordsAvailable) const;
//available options for reading
mutable Options options_;
//options that the user wants to read
mutable Options userOptions_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OFF reader
extern _OFFReader_ __OFFReaderInstance;
_OFFReader_& OFFReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

628
Core/IO/reader/OMReader.cc Normal file
View File

@@ -0,0 +1,628 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <fstream>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OMReader singleton with MeshReader
_OMReader_ __OMReaderInstance;
_OMReader_& OMReader() { return __OMReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OMReader_::_OMReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt)
{
// check whether importer can give us an OpenMesh BaseKernel
if (!_bi.kernel()) return false;
_opt += Options::Binary; // only binary format supported!
// Open file
std::ifstream ifs( _filename.c_str(), std::ios::binary );
if (!ifs.is_open())
{
omerr() << "[OMReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
// Pass stream to read method, remember result
bool result = read(ifs, _bi, _opt);
// close input stream
ifs.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read(std::istream& _is, BaseImporter& _bi, Options& _opt ) const
{
// currently only binary file format is supported
_opt += Options::Binary;
return read_binary( _is, _bi, _opt );
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_ascii( std::istream& /* _is */, BaseImporter& /* _bi */,
Options& /* _opt */) const
{
// not supported yet!
return false;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary( std::istream& _is, BaseImporter& _bi,
Options& _opt) const
{
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
// intialize byte counter
bytes_ = 0;
bytes_ += restore( _is, header_, swap );
size_t data_bytes;
while( !_is.eof() )
{
bytes_ += restore( _is, chunk_header_, swap );
if ( _is.eof() )
break;
// Is this a named property restore the name
if ( chunk_header_.name_ )
{
OMFormat::Chunk::PropertyName pn;
bytes_ += restore( _is, property_name_, swap );
}
// Read in the property data. If it is an anonymous or unknown named
// property, then skip data.
data_bytes = bytes_;
switch( chunk_header_.entity_ )
{
case OMFormat::Chunk::Entity_Vertex:
if (!read_binary_vertex_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Face:
if (!read_binary_face_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Edge:
if (!read_binary_edge_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Halfedge:
if (!read_binary_halfedge_chunk( _is, _bi, _opt, swap ))
return false;
break;
case OMFormat::Chunk::Entity_Mesh:
if (!read_binary_mesh_chunk( _is, _bi, _opt, swap ))
return false;
break;
default:
return false;
}
data_bytes = bytes_ - data_bytes;
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if ( this->BaseReader::can_u_read( _filename ) )
{
std::ifstream ifile( _filename.c_str() );
if ( ifile && can_u_read( ifile ) )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::can_u_read(std::istream& _is) const
{
std::vector<char> evt;
evt.reserve(20);
// read first 4 characters into a buffer
while( evt.size() < 4 )
evt.push_back( static_cast<char>(_is.get()) );
// put back all read characters
std::vector<char>::reverse_iterator it = evt.rbegin();
while (it != evt.rend() )
_is.putback( *it++ );
// evaluate header information
OMFormat::Header *hdr = (OMFormat::Header*)&evt[0];
// first two characters must be 'OM'
if (hdr->magic_[0] != 'O' || hdr->magic_[1] != 'M')
return false;
// 3rd characters defines the mesh type:
switch(hdr->mesh_)
{
case 'T': // Triangle Mesh
case 'Q': // Quad Mesh
case 'P': // Polygonal Mesh
break;
default: // ?
return false;
}
// 4th characters encodes the version
return supports( hdr->version_ );
}
//-----------------------------------------------------------------------------
bool
_OMReader_::supports( const OMFormat::uint8 /* version */ ) const
{
return true;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_vertex_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Vertex );
OpenMesh::Vec3f v3f;
OpenMesh::Vec2f v2f;
OpenMesh::Vec3uc v3uc; // rgb
OMFormat::Chunk::PropertyName custom_prop;
size_t vidx=0;
switch (chunk_header_.type_)
{
case Chunk::Type_Pos:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec3f::dim()) );
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v3f, _swap );
_bi.add_vertex(v3f);
}
break;
case Chunk::Type_Normal:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec3f::dim()) );
_opt += Options::VertexNormal;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v3f, _swap );
_bi.set_normal(VertexHandle(vidx), v3f);
}
break;
case Chunk::Type_Texcoord:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec2f::dim()) );
_opt += Options::VertexTexCoord;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v2f, _swap );
_bi.set_texcoord(VertexHandle(vidx), v2f);
}
break;
case Chunk::Type_Color:
assert( OMFormat::dimensions(chunk_header_) == 3 );
_opt += Options::VertexColor;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx)
{
bytes_ += vector_restore( _is, v3uc, _swap );
_bi.set_color( VertexHandle(vidx), v3uc );
}
break;
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_vprop( property_name_ ),
header_.n_vertices_,
_swap );
vidx = header_.n_vertices_;
break;
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignored!\n";
size_t size_of = header_.n_vertices_
* OMFormat::vector_size(chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
}
// all chunk data has been read..?!
return vidx == header_.n_vertices_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_face_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Face );
size_t fidx=0;
OpenMesh::Vec3f v3f; // normal
OpenMesh::Vec3uc v3uc; // rgb
switch( chunk_header_.type_ )
{
case Chunk::Type_Topology:
{
BaseImporter::VHandles vhandles;
size_t nV = 0;
size_t vidx = 0;
switch( header_.mesh_ )
{
case 'T': nV = 3; break;
case 'Q': nV = 4; break;
}
for (; fidx < header_.n_faces_; ++fidx)
{
if ( header_.mesh_ == 'P' )
bytes_ += restore( _is, nV, Chunk::Integer_16, _swap );
vhandles.clear();
for (size_t j=0; j<nV; ++j)
{
bytes_ += restore( _is, vidx,
Chunk::Integer_Size(chunk_header_.bits_),
_swap );
vhandles.push_back(VertexHandle(vidx));
}
_bi.add_face(vhandles);
}
}
break;
case Chunk::Type_Normal:
assert( OMFormat::dimensions(chunk_header_)
== size_t(OpenMesh::Vec3f::dim()) );
_opt += Options::FaceNormal;
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx)
{
bytes_ += vector_restore( _is, v3f, _swap );
_bi.set_normal(FaceHandle(fidx), v3f);
}
break;
case Chunk::Type_Color:
assert( OMFormat::dimensions(chunk_header_) == 3 );
_opt += Options::FaceColor;
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx)
{
bytes_ += vector_restore( _is, v3uc, _swap );
_bi.set_color( FaceHandle(fidx), v3uc );
}
break;
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_fprop( property_name_ ),
header_.n_faces_,
_swap );
fidx = header_.n_faces_;
break;
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignore!\n";
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
}
return fidx == header_.n_faces_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_edge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &/*_opt */,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Edge );
size_t b=bytes_;
switch( chunk_header_.type_ )
{
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_eprop( property_name_ ),
header_.n_edges_,
_swap );
break;
default:
// skip unknown type
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_halfedge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &/* _opt */,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Halfedge );
size_t b = bytes_;
switch( chunk_header_.type_ )
{
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_hprop( property_name_ ),
2*header_.n_edges_,
_swap );
break;
default:
// skip unknown chunk
omerr() << "Unknown chunk type ignored!\n";
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
bool
_OMReader_::read_binary_mesh_chunk( std::istream &_is,
BaseImporter &_bi,
Options & /* _opt */,
bool _swap ) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Mesh );
size_t b = bytes_;
switch( chunk_header_.type_ )
{
case Chunk::Type_Custom:
bytes_ +=
restore_binary_custom_data( _is,
_bi.kernel()->_get_mprop( property_name_ ),
1,
_swap );
break;
default:
// skip unknown chunk
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore( size_of );
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
size_t
_OMReader_::restore_binary_custom_data( std::istream& _is, BaseProperty* _bp,
size_t _n_elem, bool _swap) const
{
assert( !_bp || (_bp->name() == property_name_) );
using OMFormat::Chunk;
size_t bytes = 0;
Chunk::esize_t block_size;
Chunk::PropertyName custom_prop;
bytes += binary<Chunk::esize_t>::restore( _is, block_size, _swap );
if ( _bp )
{
#if defined(OM_DEBUG)
size_t b;
#endif
size_t n_bytes = _bp->size_of( _n_elem );
if ( ((n_bytes == BaseProperty::UnknownSize) || (n_bytes == block_size)) &&
(_bp->element_size() == BaseProperty::UnknownSize ||
(_n_elem * _bp->element_size() == block_size) ) )
{
#if defined(OM_DEBUG)
bytes += (b=_bp->restore( _is, _swap ));
#else
bytes += _bp->restore( _is, _swap );
#endif
#if defined(OM_DEBUG)
assert( block_size == b );
#endif
assert( block_size == _bp->size_of() );
block_size = 0;
}
else
{
omerr() << "Warning! Property " << _bp->name() << " not loaded: "
<< "Mismatching data sizes!n";
}
}
if (block_size)
{
_is.ignore( block_size );
bytes += block_size;
}
return bytes;
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

150
Core/IO/reader/OMReader.hh Normal file
View File

@@ -0,0 +1,150 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __OMREADER_HH__
#define __OMREADER_HH__
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
// STD C++
#include <iostream>
#include <string>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OM format reader. This class is singleton'ed by
SingletonT to OMReader.
*/
class _OMReader_ : public BaseReader
{
public:
_OMReader_();
virtual ~_OMReader_() { }
std::string get_description() const { return "OpenMesh File Format"; }
std::string get_extensions() const { return "om"; }
std::string get_magic() const { return "OM"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt );
virtual bool can_u_read(const std::string& _filename) const;
virtual bool can_u_read(std::istream& _is) const;
private:
bool supports( const OMFormat::uint8 version ) const;
bool read(std::istream& _is, BaseImporter& _bi, Options& _opt ) const;
bool read_ascii(std::istream& _is, BaseImporter& _bi, Options& _opt) const;
bool read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const;
typedef OMFormat::Header Header;
typedef OMFormat::Chunk::Header ChunkHeader;
typedef OMFormat::Chunk::PropertyName PropertyName;
// initialized/updated by read_binary*/read_ascii*
mutable size_t bytes_;
mutable Header header_;
mutable ChunkHeader chunk_header_;
mutable PropertyName property_name_;
bool read_binary_vertex_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_face_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_edge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_halfedge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_mesh_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
size_t restore_binary_custom_data( std::istream& _is,
BaseProperty* _bp,
size_t _n_elem,
bool _swap) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OM reader.
extern _OMReader_ __OMReaderInstance;
_OMReader_& OMReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

683
Core/IO/reader/PLYReader.cc Normal file
View File

@@ -0,0 +1,683 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
#define LINE_LEN 4096
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/reader/PLYReader.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
//STL
#include <fstream>
#include <memory>
#ifndef WIN32
#include <string.h>
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//=== INSTANCIATE =============================================================
_PLYReader_ __PLYReaderInstance;
_PLYReader_& PLYReader() { return __PLYReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_PLYReader_::_PLYReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_PLYReader_::read(const std::string& _filename, BaseImporter& _bi,
Options& _opt)
{
std::fstream in(_filename.c_str(), (options_.is_binary() ? std::ios_base::binary | std::ios_base::in
: std::ios_base::in) );
if (!in)
{
omerr() << "[PLYReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_PLYReader_::read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const
{
// filter relevant options for reading
bool swap = _opt.check( Options::Swap );
userOptions_ = _opt;
// build options to be returned
_opt.clear();
if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) _opt += Options::VertexNormal;
if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) _opt += Options::VertexTexCoord;
if (options_.vertex_has_color() && userOptions_.vertex_has_color()) _opt += Options::VertexColor;
if (options_.face_has_color() && userOptions_.face_has_color()) _opt += Options::FaceColor;
if (options_.is_binary()) _opt += Options::Binary;
// //force user-choice for the alpha value when reading binary
// if ( options_.is_binary() && userOptions_.color_has_alpha() )
// options_ += Options::ColorAlpha;
return (options_.is_binary() ?
read_binary(_in, _bi, swap) :
read_ascii(_in, _bi));
}
//-----------------------------------------------------------------------------
bool
_PLYReader_::read_ascii(std::fstream& _in, BaseImporter& _bi) const
{
omlog() << "[PLYReader] : read ascii file\n";
// Reparse the header
if ( !can_u_read(_in) ) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
unsigned int i, j, k, l, idx;
unsigned int nV;
OpenMesh::Vec3f v;
std::string trash;
// OpenMesh::Vec2f t;
OpenMesh::Vec4i c;
float tmp;
BaseImporter::VHandles vhandles;
VertexHandle vh;
_bi.reserve(vertexCount_, 3*vertexCount_, faceCount_);
std::cerr << "Vertices : " << vertexCount_ << std::endl;
if ( vertexDimension_ != 3 ) {
omerr() << "[PLYReader] : Only vertex dimension 3 is supported." << std::endl;
return false;
}
// read vertices:
for (i=0; i< vertexCount_ && !_in.eof(); ++i)
{
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
c[0] = 0;
c[1] = 0;
c[2] = 0;
c[3] = 255;
for ( uint propertyIndex = 0 ; propertyIndex < vertexPropertyCount_; ++propertyIndex ) {
switch ( vertexPropertyMap_ [ propertyIndex].first ) {
case XCOORD:
_in >> v[0];
break;
case YCOORD:
_in >> v[1];
break;
case ZCOORD:
_in >> v[2];
break;
case COLORRED:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[0] = tmp * 255.0f;
}else
_in >> c[0];
break;
case COLORGREEN:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[1] = tmp * 255.0f;
}else
_in >> c[1];
break;
case COLORBLUE:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[2] = tmp * 255.0f;
}else
_in >> c[2];
break;
case COLORALPHA:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
_in >> tmp; c[3] = tmp * 255.0f;
}else
_in >> c[3];
break;
default :
_in >> trash;
break;
}
}
vh = _bi.add_vertex(v);
_bi.set_color( vh, Vec4uc( c ) );
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
for (i=0; i<faceCount_; ++i)
{
// nV = number of Vertices for current face
_in >> nV;
if (nV == 3)
{
vhandles.resize(3);
_in >> j;
_in >> k;
_in >> l;
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
_in >> idx;
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
void _PLYReader_::readValue(ValueType _type , std::fstream& _in, float& _value) const{
switch (_type) {
case ValueTypeFLOAT32:
case ValueTypeFLOAT:
float32_t tmp;
restore( _in , tmp, options_.check(Options::MSB) );
_value = tmp;
break;
default :
_value = 0.0;
std::cerr << "unsupported conversion type to float: " << _type << std::endl;
break;
}
}
void _PLYReader_::readValue(ValueType _type , std::fstream& _in, unsigned int& _value) const{
int32_t tmp_int32_t;
uint8_t tmp_uchar;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
restore( _in , tmp_int32_t, options_.check(Options::MSB) );
_value = tmp_int32_t;
break;
case ValueTypeUCHAR:
restore( _in , tmp_uchar, options_.check(Options::MSB) );
_value = tmp_uchar;
break;
default :
_value = 0;
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
void _PLYReader_::readValue(ValueType _type , std::fstream& _in, int& _value) const{
int32_t tmp_int32_t;
uint8_t tmp_uchar;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
restore( _in , tmp_int32_t, options_.check(Options::MSB) );
_value = tmp_int32_t;
break;
case ValueTypeUCHAR:
restore( _in , tmp_uchar, options_.check(Options::MSB) );
_value = tmp_uchar;
break;
default :
_value = 0;
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
bool
_PLYReader_::read_binary(std::fstream& _in, BaseImporter& _bi, bool /*_swap*/) const
{
omlog() << "[PLYReader] : read binary file format\n";
// Reparse the header
if ( !can_u_read(_in) ) {
omerr() << "[PLYReader] : Unable to parse header\n";
return false;
}
unsigned int i, j, k, l, idx;
unsigned int nV;
OpenMesh::Vec3f v;
BaseImporter::VHandles vhandles;
VertexHandle vh;
OpenMesh::Vec4i c;
float tmp;
_bi.reserve(vertexCount_, 3*vertexCount_, faceCount_);
// read vertices:
for (i=0; i< vertexCount_ && !_in.eof(); ++i)
{
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
c[0] = 0;
c[1] = 0;
c[2] = 0;
c[3] = 255;
for ( uint propertyIndex = 0 ; propertyIndex < vertexPropertyCount_; ++propertyIndex ) {
switch ( vertexPropertyMap_ [ propertyIndex].first ) {
case XCOORD:
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,v[0]);
break;
case YCOORD:
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,v[1]);
break;
case ZCOORD:
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,v[2]);
break;
case COLORRED:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[0] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[0]);
break;
case COLORGREEN:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[1] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[1]);
break;
case COLORBLUE:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[2] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[2]);
break;
case COLORALPHA:
if ( vertexPropertyMap_ [ propertyIndex].second == ValueTypeFLOAT32 ){
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,tmp);
c[3] = tmp * 255.0f;
}else
readValue(vertexPropertyMap_ [ propertyIndex].second,_in,c[3]);
break;
default :
break;
}
}
vh = _bi.add_vertex(v);
_bi.set_color( vh, Vec4uc( c ) );
}
for (i=0; i<faceCount_; ++i)
{
// Read number of vertices for the current face
readValue(faceIndexType_,_in,nV);
if (nV == 3)
{
vhandles.resize(3);
readValue(faceEntryType_,_in,j);
readValue(faceEntryType_,_in,k);
readValue(faceEntryType_,_in,l);
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
readValue(faceEntryType_,_in,idx);
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
}
return true;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if (BaseReader::can_u_read(_filename))
{
std::ifstream ifs(_filename.c_str());
if (ifs.is_open() && can_u_read(ifs))
{
ifs.close();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
std::string get_property_name(std::string _string1 , std::string _string2 ) {
if ( _string1 == "float32" ||
_string1 == "uint8" ||
_string1 == "uchar" ||
_string1 == "float" ||
_string1 == "int32")
return _string2;
if ( _string2 == "float32" ||
_string2 == "uint8" ||
_string2 == "uchar" ||
_string2 == "float" ||
_string2 == "int32")
return _string1;
std::cerr << "Unsupported entry type" << std::endl;
return "Unsupported";
}
//-----------------------------------------------------------------------------
_PLYReader_::ValueType get_property_type(std::string _string1 , std::string _string2 ) {
if ( _string1 == "float32" || _string2 == "float32" )
return _PLYReader_::ValueTypeFLOAT32;
else if ( _string1 == "uint8" || _string2 == "float32" )
return _PLYReader_::ValueTypeUINT8;
else if ( _string1 == "int32" || _string2 == "float32" )
return _PLYReader_::ValueTypeINT32;
else if ( _string1 == "uchar" || _string2 == "uchar" )
return _PLYReader_::ValueTypeINT32;
else if ( _string1 == "float" || _string2 == "float" )
return _PLYReader_::ValueTypeFLOAT;
return _PLYReader_::Unsupported;
}
//-----------------------------------------------------------------------------
bool _PLYReader_::can_u_read(std::istream& _is) const
{
// Clear per file options
options_.cleanup();
// clear vertex property map, will be recreated
vertexPropertyMap_.clear();
vertexPropertyCount_ = 0;
// read 1st line
std::string line;
std::getline(_is,line);
//Check if this file is really a ply format
if ( line != "PLY" && line != "ply" )
return false;
// omlog() << "PLY header found" << std::endl;
vertexCount_ = 0;
faceCount_ = 0;
vertexDimension_ = 0;
std::string keyword;
std::string fileType;
std::string elementName = "";
std::string propertyType;
std::string propertyName;
std::string listIndexType;
std::string listEntryType;
float version;
_is >> keyword;
_is >> fileType;
_is >> version;
if ( _is.bad() ) {
omerr() << "Defect PLY header detected" << std::endl;
return false;
}
if ( fileType == "ascii" ) {
options_ -= Options::Binary;
} else if ( fileType == "binary_little_endian" ){
options_ += Options::Binary;
options_ += Options::LSB;
} else if ( fileType == "binary_big_endian" ){
options_ += Options::Binary;
options_ += Options::MSB;
} else {
omerr() << "Unsupported PLY format: " << fileType << std::endl;
return false;
}
unsigned int streamPos = _is.tellg();
_is >> keyword;
while ( keyword != "end_header") {
if ( keyword == "comment" ) {
std::getline(_is,line);
omlog() << "PLY header comment : " << line << std::endl;
} else if ( keyword == "element") {
_is >> elementName;
if ( elementName == "vertex" ) {
_is >> vertexCount_;
} else if ( elementName == "face" ){
_is >> faceCount_;
} else {
omerr() << "PLY header unsupported element type: " << elementName << std::endl;
}
} else if ( keyword == "property") {
std::string tmp1;
std::string tmp2;
// Read first keyword, as it might be a list
_is >> tmp1;
if ( tmp1 == "list" ) {
if ( elementName == "vertex" ) {
omerr() << "List type not supported for vertices!" << std::endl;
} else if ( elementName == "face" ) {
_is >> listIndexType;
_is >> listEntryType;
_is >> propertyName;
if ( listIndexType == "uint8" ) {
faceIndexType_ = ValueTypeUINT8;
} else if ( listIndexType == "uchar" ) {
faceIndexType_ = ValueTypeUCHAR;
} else {
omerr() << "Unsupported Index type for face list: " << listIndexType << std::endl;
}
if ( listEntryType == "int32" ) {
faceEntryType_ = ValueTypeINT32;
} else if ( listEntryType == "int" ) {
faceEntryType_ = ValueTypeINT;
} else {
omerr() << "Unsupported Entry type for face list: " << listEntryType << std::endl;
}
}
} else {
// as this is not a list property, read second value of property
_is >> tmp2;
if ( elementName == "vertex" ) {
// Extract name and type of property
// As the order seems to be different in some files, autodetect it.
ValueType valueType = get_property_type(tmp1,tmp2);
propertyName = get_property_name(tmp1,tmp2);
std::cerr << "property " << propertyName << " Type " << valueType << std::endl;
if ( propertyName == "x" ) {
std::pair< VertexProperty, ValueType> entry(XCOORD,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
vertexDimension_++;
} else if ( propertyName == "y" ) {
std::pair< VertexProperty, ValueType> entry(YCOORD,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
vertexDimension_++;
} else if ( propertyName == "z" ) {
std::pair< VertexProperty, ValueType> entry(ZCOORD,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
vertexDimension_++;
} else if ( propertyName == "red" ) {
std::pair< VertexProperty, ValueType> entry(COLORRED,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
} else if ( propertyName == "green" ) {
std::pair< VertexProperty, ValueType> entry(COLORGREEN,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
} else if ( propertyName == "blue" ) {
std::pair< VertexProperty, ValueType> entry(COLORBLUE,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
} else if ( propertyName == "alpha" ) {
std::pair< VertexProperty, ValueType> entry(COLORALPHA,valueType);
vertexPropertyMap_[vertexPropertyCount_] = entry;
options_ += Options::VertexColor;
options_ += Options::ColorAlpha;
} else {
std::cerr << "Unsupported property : " << propertyName << std::endl;
}
vertexPropertyCount_++;
} else if ( elementName == "face" ) {
omerr() << "Properties not supported for faces " << std::endl;
}
}
} else {
omlog() << "Unsupported keyword : " << keyword << std::endl;
}
streamPos = _is.tellg();
_is >> keyword;
if ( _is.bad() ) {
omerr() << "Error while reading PLY file header" << std::endl;
return false;
}
}
// As the binary data is directy after the end_header keyword
// and the stream removes too many bytes, seek back to the right position
if ( options_.is_binary() ) {
_is.seekg(streamPos + 12);
}
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

154
Core/IO/reader/PLYReader.hh Normal file
View File

@@ -0,0 +1,154 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __PLYREADER_HH__
#define __PLYREADER_HH__
//=== INCLUDES ================================================================
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#ifndef WIN32
#include <string.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the PLY format reader. This class is singleton'ed by
SingletonT to OFFReader.
*/
class _PLYReader_ : public BaseReader
{
public:
_PLYReader_();
std::string get_description() const { return "PLY polygon file format"; }
std::string get_extensions() const { return "ply"; }
std::string get_magic() const { return "PLY"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool can_u_read(const std::string& _filename) const;
enum ValueType {
Unsupported ,
ValueTypeFLOAT32, ValueTypeFLOAT,
ValueTypeUINT8, ValueTypeINT32, ValueTypeINT ,
ValueTypeUCHAR
};
private:
bool can_u_read(std::istream& _is) const;
bool read(std::fstream& _in, BaseImporter& _bi, Options& _opt ) const;
bool read_ascii(std::fstream& _in, BaseImporter& _bi) const;
bool read_binary(std::fstream& _in, BaseImporter& _bi, bool swap) const;
float readToFloatValue(ValueType _type , std::fstream& _in) const;
void readValue(ValueType _type , std::fstream& _in, float& _value) const;
void readValue(ValueType _type , std::fstream& _in, unsigned int& _value) const;
void readValue(ValueType _type , std::fstream& _in, int& _value) const;
//available options for reading
mutable Options options_;
//options that the user wants to read
mutable Options userOptions_;
mutable unsigned int vertexCount_;
mutable unsigned int faceCount_;
mutable ValueType vertexType_;
mutable uint vertexDimension_;
mutable ValueType faceIndexType_;
mutable ValueType faceEntryType_;
enum VertexProperty {
XCOORD,YCOORD,ZCOORD,
TEXX,TEXY,
COLORRED,COLORGREEN,COLORBLUE,COLORALPHA
};
// number of vertex properties
mutable unsigned int vertexPropertyCount_;
mutable std::map< int , std::pair< VertexProperty, ValueType> > vertexPropertyMap_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the PLY reader
extern _PLYReader_ __PLYReaderInstance;
_PLYReader_& PLYReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

369
Core/IO/reader/STLReader.cc Normal file
View File

@@ -0,0 +1,369 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
// STL
#include <map>
#include <float.h>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/reader/STLReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the STLReader singleton with MeshReader
_STLReader_ __STLReaderInstance;
_STLReader_& STLReader() { return __STLReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_STLReader_::
_STLReader_()
: eps_(FLT_MIN)
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
bool result = false;
STL_Type file_type = NONE;
if ( check_extension( _filename, "stla" ) )
{
file_type = STLA;
}
else if ( check_extension( _filename, "stlb" ) )
{
file_type = STLB;
}
else if ( check_extension( _filename, "stl" ) )
{
file_type = check_stl_type(_filename);
}
switch (file_type)
{
case STLA:
{
result = read_stla(_filename, _bi);
_opt -= Options::Binary;
break;
}
case STLB:
{
result = read_stlb(_filename, _bi);
_opt += Options::Binary;
break;
}
default:
{
result = false;
break;
}
}
return result;
}
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
class CmpVec
{
public:
CmpVec(float _eps=FLT_MIN) : eps_(_eps) {}
bool operator()( const Vec3f& _v0, const Vec3f& _v1 ) const
{
if (fabs(_v0[0] - _v1[0]) <= eps_)
{
if (fabs(_v0[1] - _v1[1]) <= eps_)
{
return (_v0[2] < _v1[2] - eps_);
}
else return (_v0[1] < _v1[1] - eps_);
}
else return (_v0[0] < _v1[0] - eps_);
}
private:
float eps_;
};
#endif
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stla(const std::string& _filename, BaseImporter& _bi) const
{
omlog() << "[STLReader] : read ascii file\n";
FILE* in = fopen(_filename.c_str(), "r");
if (!in)
{
omerr() << "[STLReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
char line[100], *p;
unsigned int i;
OpenMesh::Vec3f v;
unsigned int cur_idx(0);
BaseImporter::VHandles vhandles;
CmpVec comp(eps_);
std::map<Vec3f, VertexHandle, CmpVec> vMap(comp);
std::map<Vec3f, VertexHandle, CmpVec>::iterator vMapIt;
while (in && !feof(in) && fgets(line, 100, in))
{
for (p=line; isspace(*p) && *p!='\0'; ++p) {}; // skip white-space
if ((strncmp(p, "outer", 5) == 0) || (strncmp(p, "OUTER", 5) == 0))
{
vhandles.clear();
for (i=0; i<3; ++i)
{
fgets(line, 100, in);
for (p=line; isspace(*p) && *p!='\0'; ++p) {}; // skip white-space
sscanf(p+6, "%f %f %f", &v[0], &v[1], &v[2]);
// has vector been referenced before?
if ((vMapIt=vMap.find(v)) == vMap.end())
{
// No : add vertex and remember idx/vector mapping
_bi.add_vertex(v);
vhandles.push_back(VertexHandle(cur_idx));
vMap[v] = VertexHandle(cur_idx++);
}
else
// Yes : get index from map
vhandles.push_back(vMapIt->second);
}
// Add face only if it is not degenerated
if ((vhandles[0] != vhandles[1]) &&
(vhandles[0] != vhandles[2]) &&
(vhandles[1] != vhandles[2]))
_bi.add_face(vhandles);
}
}
fclose(in);
// In general a file has data, there the number of vertices cannot be 0.
return _bi.n_vertices() != 0;
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stlb(const std::string& _filename, BaseImporter& _bi) const
{
omlog() << "[STLReader] : read binary file\n";
FILE* in = fopen(_filename.c_str(), "rb");
if (!in)
{
omerr() << "[STLReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
char dummy[100];
bool swapFlag;
unsigned int i, nT;
OpenMesh::Vec3f v;
unsigned int cur_idx(0);
BaseImporter::VHandles vhandles;
std::map<Vec3f, VertexHandle, CmpVec> vMap;
std::map<Vec3f, VertexHandle, CmpVec>::iterator vMapIt;
// check size of types
if ((sizeof(float) != 4) || (sizeof(int) != 4)) {
omerr() << "[STLReader] : wrong type size\n";
return false;
}
// determine endian mode
union { unsigned int i; unsigned char c[4]; } endian_test;
endian_test.i = 1;
swapFlag = (endian_test.c[3] == 1);
// read number of triangles
fread(dummy, 1, 80, in);
nT = read_int(in, swapFlag);
// read triangles
while (nT)
{
vhandles.clear();
// skip triangle normal
fread(dummy, 1, 12, in);
// triangle's vertices
for (i=0; i<3; ++i)
{
v[0] = read_float(in, swapFlag);
v[1] = read_float(in, swapFlag);
v[2] = read_float(in, swapFlag);
// has vector been referenced before?
if ((vMapIt=vMap.find(v)) == vMap.end())
{
// No : add vertex and remember idx/vector mapping
_bi.add_vertex(v);
vhandles.push_back(VertexHandle(cur_idx));
vMap[v] = VertexHandle(cur_idx++);
}
else
// Yes : get index from map
vhandles.push_back(vMapIt->second);
}
// Add face only if it is not degenerated
if ((vhandles[0] != vhandles[1]) &&
(vhandles[0] != vhandles[2]) &&
(vhandles[1] != vhandles[2]))
_bi.add_face(vhandles);
fread(dummy, 1, 2, in);
--nT;
}
return true;
}
//-----------------------------------------------------------------------------
_STLReader_::STL_Type
_STLReader_::
check_stl_type(const std::string& _filename) const
{
// assume it's binary stl, then file size is known from #triangles
// if size matches, it's really binary
// open file
FILE* in = fopen(_filename.c_str(), "rb");
if (!in) return NONE;
// determine endian mode
union { unsigned int i; unsigned char c[4]; } endian_test;
endian_test.i = 1;
bool swapFlag = (endian_test.c[3] == 1);
// read number of triangles
char dummy[100];
fread(dummy, 1, 80, in);
unsigned int nT = read_int(in, swapFlag);
// compute file size from nT
unsigned int binary_size = 84 + nT*50;
// get actual file size
unsigned int file_size(0);
rewind(in);
while (!feof(in))
file_size += fread(dummy, 1, 100, in);
fclose(in);
// if sizes match -> it's STLB
return (binary_size == file_size ? STLB : STLA);
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

124
Core/IO/reader/STLReader.hh Normal file
View File

@@ -0,0 +1,124 @@
/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* *
* License *
* *
* This library 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, version 2.1. *
* *
* This library 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 Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an reader module for STL files
//
//=============================================================================
#ifndef __STLREADER_HH__
#define __STLREADER_HH__
//=== INCLUDES ================================================================
#include <stdio.h>
#include <string>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#ifndef WIN32
#include <string.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the STL format reader. This class is singleton'ed by
SingletonT to STLReader.
*/
class _STLReader_ : public BaseReader
{
public:
// constructor
_STLReader_();
std::string get_description() const
{ return "Stereolithography Interface Format"; }
std::string get_extensions() const { return "stl stla stlb"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
/** Set the threshold to be used for considering two point to be equal.
Can be used to merge small gaps */
void set_epsilon(float _eps) { eps_=_eps; }
/// Returns the threshold to be used for considering two point to be equal.
float epsilon() const { return eps_; }
private:
enum STL_Type { STLA, STLB, NONE };
STL_Type check_stl_type(const std::string& _filename) const;
bool read_stla(const std::string& _filename, BaseImporter& _bi) const;
bool read_stlb(const std::string& _filename, BaseImporter& _bi) const;
private:
float eps_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the STL reader
extern _STLReader_ __STLReaderInstance;
_STLReader_& STLReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================