2009-02-06 13:37:46 +00:00
|
|
|
/*===========================================================================*\
|
|
|
|
|
* *
|
|
|
|
|
* OpenMesh *
|
2014-02-05 09:01:07 +00:00
|
|
|
* Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen *
|
2009-02-06 13:37:46 +00:00
|
|
|
* www.openmesh.org *
|
|
|
|
|
* *
|
2009-11-17 13:54:16 +00:00
|
|
|
*---------------------------------------------------------------------------*
|
2009-06-04 08:46:29 +00:00
|
|
|
* This file is part of OpenMesh. *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-11-17 13:54:16 +00:00
|
|
|
* OpenMesh is free software: you can redistribute it and/or modify *
|
2009-06-04 08:46:29 +00:00
|
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
|
|
|
* published by the Free Software Foundation, either version 3 of *
|
|
|
|
|
* the License, or (at your option) any later version with the *
|
|
|
|
|
* following exceptions: *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* If other files instantiate templates or use macros *
|
|
|
|
|
* or inline functions from this file, or you compile this file and *
|
|
|
|
|
* link it with other files to produce an executable, this file does *
|
|
|
|
|
* not by itself cause the resulting executable to be covered by the *
|
|
|
|
|
* GNU Lesser General Public License. This exception does not however *
|
|
|
|
|
* invalidate any other reasons why the executable file might be *
|
|
|
|
|
* covered by the GNU Lesser General Public License. *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* OpenMesh is distributed in the hope that it will be useful, *
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
|
* GNU Lesser General Public License for more details. *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* You should have received a copy of the GNU LesserGeneral Public *
|
|
|
|
|
* License along with OpenMesh. If not, *
|
|
|
|
|
* see <http://www.gnu.org/licenses/>. *
|
|
|
|
|
* *
|
2009-11-17 13:54:16 +00:00
|
|
|
\*===========================================================================*/
|
2009-06-04 08:46:29 +00:00
|
|
|
|
|
|
|
|
/*===========================================================================*\
|
2009-11-17 13:54:16 +00:00
|
|
|
* *
|
2009-06-04 08:46:29 +00:00
|
|
|
* $Revision$ *
|
|
|
|
|
* $Date$ *
|
2009-02-06 13:37:46 +00:00
|
|
|
* *
|
|
|
|
|
\*===========================================================================*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//== 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 ==========================================================
|
|
|
|
|
|
2009-04-22 11:59:15 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
void trimString( std::string& _string) {
|
|
|
|
|
// Trim Both leading and trailing spaces
|
|
|
|
|
|
2009-05-11 12:00:25 +00:00
|
|
|
size_t start = _string.find_first_not_of(" \t\r\n");
|
|
|
|
|
size_t end = _string.find_last_not_of(" \t\r\n");
|
2009-04-22 11:59:15 +00:00
|
|
|
|
|
|
|
|
if(( std::string::npos == start ) || ( std::string::npos == end))
|
|
|
|
|
_string = "";
|
|
|
|
|
else
|
|
|
|
|
_string = _string.substr( start, end-start+1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
_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 );
|
|
|
|
|
|
2009-11-17 13:54:16 +00:00
|
|
|
if (!in.is_open() || !in.good())
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
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;
|
2009-04-22 11:59:15 +00:00
|
|
|
std::string textureName;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
std::string key;
|
|
|
|
|
Material mat;
|
|
|
|
|
float f1,f2,f3;
|
|
|
|
|
bool indef = false;
|
2009-04-22 11:59:15 +00:00
|
|
|
int textureId = 1;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
|
2009-08-31 07:35:20 +00:00
|
|
|
materials_.clear();
|
2009-02-06 13:37:46 +00:00
|
|
|
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;
|
|
|
|
|
|
2010-02-23 12:15:05 +00:00
|
|
|
if( ( isspace(line[0]) && line[0] != '\t' ) || line[0] == '#' )
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
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_Ks, specular map
|
|
|
|
|
// map_Ka, ambient map
|
|
|
|
|
// map_Bump, bump map
|
|
|
|
|
// map_d, opacity map
|
|
|
|
|
; // just skip this
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-04-22 11:59:15 +00:00
|
|
|
else if (keyWrd == "map_Kd" ) {
|
2009-05-11 12:00:25 +00:00
|
|
|
// Get the rest of the line, removing leading or trailing spaces
|
|
|
|
|
// This will define the filename of the texture
|
2009-04-22 11:59:15 +00:00
|
|
|
std::getline(stream,textureName);
|
|
|
|
|
trimString(textureName);
|
2009-05-11 12:00:25 +00:00
|
|
|
if ( ! textureName.empty() )
|
|
|
|
|
mat.set_map_Kd( textureName, textureId++ );
|
2009-04-22 11:59:15 +00:00
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
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_::
|
2009-11-17 13:54:16 +00:00
|
|
|
read(std::istream& _in, BaseImporter& _bi, Options& _opt)
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
omlog() << "[OBJReader] : read file\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string line;
|
|
|
|
|
std::string keyWrd;
|
|
|
|
|
|
2011-12-01 16:16:29 +00:00
|
|
|
float x, y, z, u, v;
|
|
|
|
|
int r, g, b;
|
|
|
|
|
BaseImporter::VHandles vhandles;
|
|
|
|
|
std::vector<Vec3f> normals;
|
|
|
|
|
std::vector<Vec3uc> colors;
|
|
|
|
|
std::vector<Vec2f> texcoords;
|
|
|
|
|
std::vector<Vec2f> face_texcoords;
|
|
|
|
|
std::vector<VertexHandle> vertexHandles;
|
2009-03-20 12:33:38 +00:00
|
|
|
|
2011-12-01 16:23:29 +00:00
|
|
|
std::string matname;
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
// Options supplied by the user
|
|
|
|
|
Options userOptions = _opt;
|
|
|
|
|
|
|
|
|
|
// Options collected via file parsing
|
|
|
|
|
Options fileOptions;
|
|
|
|
|
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
while( _in && !_in.eof() )
|
|
|
|
|
{
|
|
|
|
|
std::getline(_in,line);
|
|
|
|
|
if ( _in.bad() ){
|
|
|
|
|
omerr() << " Warning! Could not read file properly!\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-17 12:35:44 +00:00
|
|
|
// Trim Both leading and trailing spaces
|
2009-04-22 11:59:15 +00:00
|
|
|
trimString(line);
|
2009-04-17 12:35:44 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// 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;
|
|
|
|
|
|
2009-05-12 14:58:21 +00:00
|
|
|
// 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);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
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";
|
2009-04-22 11:59:15 +00:00
|
|
|
|
|
|
|
|
omlog() << " " << materials_.size() << " materials loaded.\n";
|
|
|
|
|
|
2012-01-12 09:15:18 +00:00
|
|
|
for ( MaterialList::iterator material = materials_.begin(); material != materials_.end(); ++material )
|
2009-04-22 11:59:15 +00:00
|
|
|
{
|
2009-05-12 14:58:21 +00:00
|
|
|
// 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() );
|
2009-04-22 11:59:15 +00:00
|
|
|
}
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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() )
|
2011-12-01 16:16:29 +00:00
|
|
|
{
|
|
|
|
|
vertexHandles.push_back(_bi.add_vertex(OpenMesh::Vec3f(x,y,z)));
|
2011-12-01 16:23:29 +00:00
|
|
|
stream >> r; stream >> g; stream >> b;
|
2011-12-01 16:16:29 +00:00
|
|
|
|
2011-12-01 16:23:29 +00:00
|
|
|
if ( !stream.fail() )
|
|
|
|
|
{
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( userOptions.vertex_has_color() ) {
|
|
|
|
|
fileOptions += Options::VertexColor;
|
|
|
|
|
colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b));
|
|
|
|
|
}
|
2011-12-01 16:23:29 +00:00
|
|
|
}
|
2011-12-01 16:16:29 +00:00
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// texture coord
|
|
|
|
|
else if (keyWrd == "vt")
|
|
|
|
|
{
|
|
|
|
|
stream >> u; stream >> v;
|
|
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( !stream.fail() ){
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( userOptions.vertex_has_texcoord() || userOptions.face_has_texcoord() ) {
|
|
|
|
|
texcoords.push_back(OpenMesh::Vec2f(u, v));
|
|
|
|
|
|
|
|
|
|
// Can be used for both!
|
|
|
|
|
fileOptions += Options::VertexTexCoord;
|
|
|
|
|
fileOptions += Options::FaceTexCoord;
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
|
|
|
|
|
omerr() << "Only single 2D texture coordinate per vertex"
|
|
|
|
|
<< "allowed!" << std::endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-01 16:16:29 +00:00
|
|
|
// color per vertex
|
|
|
|
|
else if (keyWrd == "vc")
|
|
|
|
|
{
|
|
|
|
|
stream >> r; stream >> g; stream >> b;
|
|
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( !stream.fail() ){
|
|
|
|
|
if ( userOptions.vertex_has_color() ) {
|
|
|
|
|
colors.push_back(OpenMesh::Vec3uc((unsigned char)r,(unsigned char)g,(unsigned char)b));
|
|
|
|
|
fileOptions += Options::VertexColor;
|
|
|
|
|
}
|
2011-12-01 16:16:29 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
// normal
|
|
|
|
|
else if (keyWrd == "vn")
|
|
|
|
|
{
|
|
|
|
|
stream >> x; stream >> y; stream >> z;
|
|
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( !stream.fail() ) {
|
|
|
|
|
if (userOptions.vertex_has_normal() ){
|
|
|
|
|
normals.push_back(OpenMesh::Vec3f(x,y,z));
|
|
|
|
|
fileOptions += Options::VertexNormal;
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// face
|
|
|
|
|
else if (keyWrd == "f")
|
|
|
|
|
{
|
|
|
|
|
int component(0), nV(0);
|
|
|
|
|
int value;
|
|
|
|
|
|
|
|
|
|
vhandles.clear();
|
2009-03-20 12:33:38 +00:00
|
|
|
face_texcoords.clear();
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
// read full line after detecting a face
|
|
|
|
|
std::string faceLine;
|
|
|
|
|
std::getline(stream,faceLine);
|
|
|
|
|
std::stringstream lineData( faceLine );
|
|
|
|
|
|
2012-06-18 13:14:58 +00:00
|
|
|
FaceHandle fh;
|
|
|
|
|
BaseImporter::VHandles faceVertices;
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// 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;
|
|
|
|
|
|
2009-02-17 11:00:58 +00:00
|
|
|
// Clear vertex after finished reading the line
|
|
|
|
|
vertex="";
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
// 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 ) {
|
2009-05-13 06:05:43 +00:00
|
|
|
// Calculation of index :
|
|
|
|
|
// -1 is the last vertex in the list
|
|
|
|
|
// As obj counts from 1 and not zero add +1
|
2013-07-23 13:32:21 +00:00
|
|
|
value = int(_bi.n_vertices() + value + 1);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2009-05-13 06:05:43 +00:00
|
|
|
// Obj counts from 1 and not zero .. array counts from zero therefore -1
|
2009-02-06 13:37:46 +00:00
|
|
|
vhandles.push_back(VertexHandle(value-1));
|
2012-06-18 13:14:58 +00:00
|
|
|
faceVertices.push_back(VertexHandle(value-1));
|
2012-10-08 09:45:20 +00:00
|
|
|
if (fileOptions.vertex_has_color() )
|
2011-12-01 16:23:29 +00:00
|
|
|
_bi.set_color(vhandles.back(), colors[value-1]);
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
2011-12-01 16:16:29 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
case 1: // texture coord
|
|
|
|
|
if ( value < 0 ) {
|
2009-05-13 06:05:43 +00:00
|
|
|
// Calculation of index :
|
|
|
|
|
// -1 is the last vertex in the list
|
|
|
|
|
// As obj counts from 1 and not zero add +1
|
2013-07-23 13:32:21 +00:00
|
|
|
value = int(texcoords.size()) + value + 1;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
assert(!vhandles.empty());
|
2012-10-08 09:45:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( fileOptions.vertex_has_texcoord() && userOptions.vertex_has_texcoord() ) {
|
|
|
|
|
|
|
|
|
|
if (!texcoords.empty() && (unsigned int) (value - 1) < texcoords.size()) {
|
|
|
|
|
// Obj counts from 1 and not zero .. array counts from zero therefore -1
|
|
|
|
|
_bi.set_texcoord(vhandles.back(), texcoords[value - 1]);
|
|
|
|
|
} else {
|
|
|
|
|
omerr() << "Error setting Texture coordinates" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fileOptions.face_has_texcoord() && userOptions.face_has_texcoord() ) {
|
|
|
|
|
|
|
|
|
|
if (!texcoords.empty() && (unsigned int) (value - 1) < texcoords.size()) {
|
|
|
|
|
face_texcoords.push_back( texcoords[value-1] );
|
|
|
|
|
} else {
|
|
|
|
|
omerr() << "Error setting Texture coordinates" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-17 14:23:37 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 2: // normal
|
|
|
|
|
if ( value < 0 ) {
|
2009-05-13 06:05:43 +00:00
|
|
|
// Calculation of index :
|
|
|
|
|
// -1 is the last vertex in the list
|
|
|
|
|
// As obj counts from 1 and not zero add +1
|
2013-07-23 13:32:21 +00:00
|
|
|
value = int(normals.size()) + value + 1;
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2012-10-08 09:45:20 +00:00
|
|
|
|
2009-05-13 06:05:43 +00:00
|
|
|
// Obj counts from 1 and not zero .. array counts from zero therefore -1
|
2012-10-08 09:45:20 +00:00
|
|
|
if (fileOptions.vertex_has_normal() ) {
|
|
|
|
|
assert(!vhandles.empty());
|
|
|
|
|
assert((unsigned int)(value-1) < normals.size());
|
|
|
|
|
_bi.set_normal(vhandles.back(), normals[value-1]);
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prepare for reading next component
|
|
|
|
|
++component;
|
|
|
|
|
|
2009-02-17 11:00:58 +00:00
|
|
|
// Read until line does not contain any other info
|
|
|
|
|
} while ( !vertex.empty() );
|
2009-02-06 13:37:46 +00:00
|
|
|
|
|
|
|
|
component = 0;
|
|
|
|
|
nV++;
|
|
|
|
|
|
2012-06-18 13:14:58 +00:00
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2013-04-25 11:03:53 +00:00
|
|
|
// note that add_face can possibly triangulate the faces, which is why we have to
|
|
|
|
|
// store the current number of faces first
|
2009-02-06 13:37:46 +00:00
|
|
|
size_t n_faces = _bi.n_faces();
|
2013-04-25 11:03:53 +00:00
|
|
|
fh = _bi.add_face(faceVertices);
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if (!vhandles.empty() && fh.is_valid() )
|
|
|
|
|
_bi.add_face_texcoords(fh, vhandles[0], face_texcoords);
|
2009-03-20 12:33:38 +00:00
|
|
|
|
2009-04-22 11:59:15 +00:00
|
|
|
if ( !matname.empty() )
|
2009-02-06 13:37:46 +00:00
|
|
|
{
|
|
|
|
|
std::vector<FaceHandle> newfaces;
|
|
|
|
|
|
|
|
|
|
for( size_t i=0; i < _bi.n_faces()-n_faces; ++i )
|
2013-07-23 13:32:21 +00:00
|
|
|
newfaces.push_back(FaceHandle(int(n_faces+i)));
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2009-04-22 11:59:15 +00:00
|
|
|
Material& mat = materials_[matname];
|
|
|
|
|
|
|
|
|
|
if ( mat.has_Kd() ) {
|
|
|
|
|
Vec3uc fc = color_cast<Vec3uc, Vec3f>(mat.Kd());
|
|
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( userOptions.face_has_color()) {
|
|
|
|
|
|
|
|
|
|
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
|
|
|
|
|
_bi.set_color(*it, fc);
|
2009-04-22 11:59:15 +00:00
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
fileOptions += Options::FaceColor;
|
|
|
|
|
}
|
2009-04-22 11:59:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set the texture index in the face index property
|
|
|
|
|
if ( mat.has_map_Kd() ) {
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if (userOptions.face_has_texcoord()) {
|
|
|
|
|
|
|
|
|
|
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
|
|
|
|
|
_bi.set_face_texindex(*it, mat.map_Kd_index());
|
|
|
|
|
|
|
|
|
|
fileOptions += Options::FaceTexCoord;
|
|
|
|
|
|
|
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2009-04-22 11:59:15 +00:00
|
|
|
} else {
|
2012-10-08 09:45:20 +00:00
|
|
|
|
2009-04-22 11:59:15 +00:00
|
|
|
// If we don't have the info, set it to no texture
|
2012-10-08 09:45:20 +00:00
|
|
|
if (userOptions.face_has_texcoord()) {
|
|
|
|
|
|
|
|
|
|
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
|
|
|
|
|
_bi.set_face_texindex(*it, 0);
|
|
|
|
|
|
|
|
|
|
}
|
2009-04-22 11:59:15 +00:00
|
|
|
}
|
2009-02-06 13:37:46 +00:00
|
|
|
|
2009-04-22 11:59:15 +00:00
|
|
|
} else {
|
|
|
|
|
std::vector<FaceHandle> newfaces;
|
|
|
|
|
|
|
|
|
|
for( size_t i=0; i < _bi.n_faces()-n_faces; ++i )
|
2013-07-23 13:32:21 +00:00
|
|
|
newfaces.push_back(FaceHandle(int(n_faces+i)));
|
2009-04-22 11:59:15 +00:00
|
|
|
|
|
|
|
|
// Set the texture index to zero as we don't have any information
|
2012-10-08 09:45:20 +00:00
|
|
|
if ( userOptions.face_has_texcoord() )
|
|
|
|
|
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
|
|
|
|
|
_bi.set_face_texindex(*it, 0);
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2009-04-22 11:59:15 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
2009-04-22 11:59:15 +00:00
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
}
|
|
|
|
|
|
2011-12-01 16:23:29 +00:00
|
|
|
// If we do not have any faces,
|
|
|
|
|
// assume this is a point cloud and read the normals and colors directly
|
2012-10-08 09:45:20 +00:00
|
|
|
if (_bi.n_faces() == 0)
|
2011-12-01 16:23:29 +00:00
|
|
|
{
|
2012-10-08 09:45:20 +00:00
|
|
|
int i = 0;
|
2011-12-01 16:23:29 +00:00
|
|
|
// add normal per vertex
|
|
|
|
|
|
2012-10-08 09:45:20 +00:00
|
|
|
if (normals.size() == _bi.n_vertices()) {
|
|
|
|
|
if ( fileOptions.vertex_has_normal() && userOptions.vertex_has_normal() ) {
|
|
|
|
|
for (std::vector<VertexHandle>::iterator it = vertexHandles.begin(); it != vertexHandles.end(); ++it, i++)
|
|
|
|
|
_bi.set_normal(*it, normals[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-01 16:23:29 +00:00
|
|
|
|
|
|
|
|
// add color per vertex
|
2012-10-08 09:45:20 +00:00
|
|
|
i = 0;
|
|
|
|
|
if (colors.size() >= _bi.n_vertices())
|
|
|
|
|
if (fileOptions.vertex_has_color() && userOptions.vertex_has_color()) {
|
|
|
|
|
for (std::vector<VertexHandle>::iterator it = vertexHandles.begin(); it != vertexHandles.end(); ++it, i++)
|
|
|
|
|
_bi.set_color(*it, colors[i]);
|
2011-12-01 16:23:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 09:49:14 +00:00
|
|
|
// Return, what we actually read
|
|
|
|
|
_opt = fileOptions;
|
|
|
|
|
|
2009-02-06 13:37:46 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
} // namespace IO
|
|
|
|
|
} // namespace OpenMesh
|
|
|
|
|
//=============================================================================
|