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:
17
Core/IO/reader/ACGMakefile
Normal file
17
Core/IO/reader/ACGMakefile
Normal 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
|
||||
#==============================================================================
|
||||
113
Core/IO/reader/BaseReader.cc
Normal file
113
Core/IO/reader/BaseReader.cc
Normal 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
|
||||
//=============================================================================
|
||||
113
Core/IO/reader/BaseReader.hh
Normal file
113
Core/IO/reader/BaseReader.hh
Normal 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
472
Core/IO/reader/OBJReader.cc
Normal 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
159
Core/IO/reader/OBJReader.hh
Normal 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
597
Core/IO/reader/OFFReader.cc
Normal 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
150
Core/IO/reader/OFFReader.hh
Normal 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
628
Core/IO/reader/OMReader.cc
Normal 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
150
Core/IO/reader/OMReader.hh
Normal 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
683
Core/IO/reader/PLYReader.cc
Normal 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
154
Core/IO/reader/PLYReader.hh
Normal 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
369
Core/IO/reader/STLReader.cc
Normal 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
124
Core/IO/reader/STLReader.hh
Normal 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
|
||||
//=============================================================================
|
||||
Reference in New Issue
Block a user