Changed OpenMesh directory structure
git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@106 fdac6126-5c0c-442c-9429-916003d36597
This commit is contained in:
597
src/OpenMesh/Core/IO/reader/OFFReader.cc
Normal file
597
src/OpenMesh/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
|
||||
//=============================================================================
|
||||
Reference in New Issue
Block a user