Merge branch 'obj-fix-wrong-indices' into 'master'
Fixed broken indices for some cases of OBJ parsing by using two passes (Continuing fixing / discussion from https://graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/merge_requests/51) This merge request is fixing an issue that came up as a follow-up of the following merge request: https://graphics.rwth-aachen.de:9000/OpenMesh/OpenMesh/merge_requests/51 The problem it fixes occurs for some kinds of OBJ data, where vertices and face data are stored interleaved and, at the same time, the mesh contains some non-manifold geometry. As non-manifold geometry triggers the on-the-fly creation of new vertices during parsing, the indices from the OBJ file do not match any more and the result gets messed up. The straightforward solution applied on this branch is to parse to whole OBJ file in two passes, first the vertices and then the material data and faces. This way, possible extra vertices will always be added to the back, not interfering with indices from the OBJ file I tested the performance on a 1.1 GB OBJ file. The loading time on my machine increased from ~59 seconds to ~65 seconds, so I believe the performance overhead could probably be considered acceptable. Looking forward to your feedback! See merge request !84
This commit is contained in:
@@ -279,37 +279,29 @@ read_material(std::fstream& _in)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
_OBJReader_::
|
||||
read(std::istream& _in, BaseImporter& _bi, Options& _opt)
|
||||
read_vertices(std::istream& _in, BaseImporter& _bi, Options& _opt,
|
||||
std::vector<Vec3f> & normals,
|
||||
std::vector<Vec3f> & colors,
|
||||
std::vector<Vec3f> & texcoords3d,
|
||||
std::vector<Vec2f> & texcoords,
|
||||
std::vector<VertexHandle> & vertexHandles,
|
||||
Options & fileOptions)
|
||||
{
|
||||
float x, y, z, u, v, w;
|
||||
float r, g, b;
|
||||
|
||||
std::string line;
|
||||
std::string keyWrd;
|
||||
|
||||
float x, y, z, u, v, w;
|
||||
float r, g, b;
|
||||
BaseImporter::VHandles vhandles;
|
||||
std::vector<Vec3f> normals;
|
||||
std::vector<Vec3f> colors;
|
||||
std::vector<Vec3f> texcoords3d, face_texcoords3d;
|
||||
std::vector<Vec2f> texcoords, face_texcoords;
|
||||
std::vector<VertexHandle> vertexHandles;
|
||||
|
||||
std::string matname;
|
||||
|
||||
std::stringstream stream, lineData, tmp;
|
||||
std::stringstream stream;
|
||||
|
||||
|
||||
// Options supplied by the user
|
||||
Options userOptions = _opt;
|
||||
|
||||
// Options collected via file parsing
|
||||
Options fileOptions;
|
||||
|
||||
const Options & userOptions = _opt;
|
||||
|
||||
while( _in && !_in.eof() )
|
||||
{
|
||||
@@ -332,56 +324,8 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt)
|
||||
|
||||
stream >> keyWrd;
|
||||
|
||||
// material file
|
||||
if (keyWrd == "mtllib")
|
||||
{
|
||||
std::string matFile;
|
||||
|
||||
// Get the rest of the line, removing leading or trailing spaces
|
||||
// This will define the filename of the texture
|
||||
std::getline(stream,matFile);
|
||||
trimString(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();
|
||||
|
||||
}else
|
||||
omerr() << " Warning! Material file '" << matFile << "' not found!\n";
|
||||
|
||||
//omlog() << " " << materials_.size() << " materials loaded.\n";
|
||||
|
||||
for ( MaterialList::iterator material = materials_.begin(); material != materials_.end(); ++material )
|
||||
{
|
||||
// Save the texture information in a property
|
||||
if ( (*material).second.has_map_Kd() )
|
||||
_bi.add_texture_information( (*material).second.map_Kd_index() , (*material).second.map_Kd() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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")
|
||||
if (keyWrd == "v")
|
||||
{
|
||||
stream >> x; stream >> y; stream >> z;
|
||||
|
||||
@@ -453,9 +397,123 @@ read(std::istream& _in, BaseImporter& _bi, Options& _opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
_OBJReader_::
|
||||
read(std::istream& _in, BaseImporter& _bi, Options& _opt)
|
||||
{
|
||||
std::string line;
|
||||
std::string keyWrd;
|
||||
|
||||
std::vector<Vec3f> normals;
|
||||
std::vector<Vec3f> colors;
|
||||
std::vector<Vec3f> texcoords3d;
|
||||
std::vector<Vec2f> texcoords;
|
||||
std::vector<VertexHandle> vertexHandles;
|
||||
|
||||
BaseImporter::VHandles vhandles;
|
||||
std::vector<Vec3f> face_texcoords3d;
|
||||
std::vector<Vec2f> face_texcoords;
|
||||
|
||||
std::string matname;
|
||||
|
||||
std::stringstream stream, lineData, tmp;
|
||||
|
||||
|
||||
// face
|
||||
// Options supplied by the user
|
||||
Options userOptions = _opt;
|
||||
|
||||
// Options collected via file parsing
|
||||
Options fileOptions;
|
||||
|
||||
// pass 1: read vertices
|
||||
if ( !read_vertices(_in, _bi, _opt,
|
||||
normals, colors, texcoords3d, texcoords,
|
||||
vertexHandles, fileOptions) ){
|
||||
return false;
|
||||
}
|
||||
|
||||
// reset stream for second pass
|
||||
_in.clear();
|
||||
_in.seekg(0, std::ios::beg);
|
||||
|
||||
// pass 2: read vertices
|
||||
while( _in && !_in.eof() )
|
||||
{
|
||||
std::getline(_in,line);
|
||||
if ( _in.bad() ){
|
||||
omerr() << " Warning! Could not read file properly!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trim Both leading and trailing spaces
|
||||
trimString(line);
|
||||
|
||||
// comment
|
||||
if ( line.size() == 0 || line[0] == '#' || isspace(line[0]) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
stream.str(line);
|
||||
stream.clear();
|
||||
|
||||
stream >> keyWrd;
|
||||
|
||||
// material file
|
||||
if (keyWrd == "mtllib")
|
||||
{
|
||||
std::string matFile;
|
||||
|
||||
// Get the rest of the line, removing leading or trailing spaces
|
||||
// This will define the filename of the texture
|
||||
std::getline(stream,matFile);
|
||||
trimString(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();
|
||||
|
||||
}else
|
||||
omerr() << " Warning! Material file '" << matFile << "' not found!\n";
|
||||
|
||||
//omlog() << " " << materials_.size() << " materials loaded.\n";
|
||||
|
||||
for ( MaterialList::iterator material = materials_.begin(); material != materials_.end(); ++material )
|
||||
{
|
||||
// Save the texture information in a property
|
||||
if ( (*material).second.has_map_Kd() )
|
||||
_bi.add_texture_information( (*material).second.map_Kd_index() , (*material).second.map_Kd() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// usemtl
|
||||
else if (keyWrd == "usemtl")
|
||||
{
|
||||
stream >> matname;
|
||||
if (materials_.find(matname)==materials_.end())
|
||||
{
|
||||
omerr() << "Warning! Material '" << matname
|
||||
<< "' not defined in material file.\n";
|
||||
matname="";
|
||||
}
|
||||
}
|
||||
|
||||
// faces
|
||||
else if (keyWrd == "f")
|
||||
{
|
||||
int component(0), nV(0);
|
||||
|
||||
@@ -170,8 +170,17 @@ private:
|
||||
|
||||
bool read_material( std::fstream& _in );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
bool read_vertices(std::istream& _in, BaseImporter& _bi, Options& _opt,
|
||||
std::vector<Vec3f> & normals,
|
||||
std::vector<Vec3f> & colors,
|
||||
std::vector<Vec3f> & texcoords3d,
|
||||
std::vector<Vec2f> & texcoords,
|
||||
std::vector<VertexHandle> & vertexHandles,
|
||||
Options & fileOptions);
|
||||
|
||||
std::string path_;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user