/*===========================================================================*\ * * * OpenMesh * * Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * * * * OpenMesh 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, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * 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. * * * * 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. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenMesh. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Date$ * * * \*===========================================================================*/ #define LINE_LEN 4096 //== INCLUDES ================================================================= // OpenMesh #include #include #include #include #include #include // #include #include //STL #include #include #include #include #ifndef WIN32 #include #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::ifstream ifile(_filename.c_str(), (options_.is_binary() ? std::ios::binary | std::ios::in : std::ios::in) ); if (!ifile.is_open() || !ifile.good()) { omerr() << "[OFFReader] : cannot not open file " << _filename << std::endl; return false; } assert(ifile); bool result = read(ifile, _bi, _opt); ifile.close(); return result; } //----------------------------------------------------------------------------- bool _OFFReader_::read(std::istream& _in, BaseImporter& _bi, Options& _opt ) { if (!_in.good()) { omerr() << "[OMReader] : cannot not use stream " << std::endl; return false; } // 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::istream& _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> 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(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(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 .. [color spec] for (i=0; i> 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> 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(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(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::istream& _in, float& _value) const{ float32_t tmp; restore( _in , tmp, false ); //assuming LSB byte order _value = tmp; } void _OFFReader_::readValue(std::istream& _in, int& _value) const{ uint32_t tmp; restore( _in , tmp, false ); //assuming LSB byte order _value = tmp; } void _OFFReader_::readValue(std::istream& _in, unsigned int& _value) const{ uint32_t tmp; restore( _in , tmp, false ); //assuming LSB byte order _value = tmp; } bool _OFFReader_::read_binary(std::istream& _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 .. [color spec] // So far color spec is unsupported! for (i=0; i 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 //=============================================================================