Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_IO_MESH_OBJ_READ_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_COMMON_IO_MESH_OBJ_READ_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <boost/algorithm/string.hpp>
00013 #include <boost/lexical_cast.hpp>
00014
00015 #include <cassert>
00016 #include <string>
00017 #include <sstream>
00018 #include <fstream>
00019 #include <iostream>
00020 #include <vector>
00021 #include <map>
00022
00023 namespace OpenTissue
00024 {
00025 namespace mesh
00026 {
00027
00028 namespace detail
00029 {
00038 template<typename material_container>
00039 bool read_obj_materials(std::string const & filename,material_container & materials)
00040 {
00041 typedef typename material_container::value_type material_type;
00042 typedef float real_type;
00043 materials.clear();
00044
00045 std::ifstream file(filename);
00046
00047 if(!file.is_open())
00048 return false;
00049
00050 std::string line,type;
00051 std::string material_name;
00052
00053 while(!file.eof())
00054 {
00055 getline(file,line);
00056 std::stringstream stream(line.c_str());
00057 stream >> type;
00058
00059 if(line[0] == '#')
00060 {
00061 continue;
00062 }
00063 else if(type == "newmtl")
00064 {
00065
00066
00067
00068 stream >> material_name;
00069 continue;
00070 }
00071 else if(type == "Ka")
00072 {
00073 real_type Ka0,Ka1,Ka2;
00074 stream >> Ka0;
00075 stream >> Ka1;
00076 stream >> Ka2;
00077 }
00078 else if(type == "Kd")
00079 {
00080 real_type Kd0,Kd1,Kd2;
00081 stream >> Kd0;
00082 stream >> Kd1;
00083 stream >> Kd2;
00084 }
00085 else if(type == "Ks")
00086 {
00087 real_type Ks0,Ks1,Ks2;
00088 stream >> Ks0;
00089 stream >> Ks1;
00090 stream >> Ks2;
00091 }
00092 else if(type == "Tr" || type == "d")
00093 {
00094 real_type Tr;
00095 stream >> Tr;
00096 }
00097 else if(type == "Ns")
00098 {
00099 real_type Ns;
00100 stream >> Ns;
00101 }
00102 else
00103 {
00104 std::cout << "read_obj_materials(): skipping "<< type << std::endl;
00105 }
00106 }
00107
00108
00109
00110
00111
00112 file.close();
00113 std::cout << "read_obj_materials() : "
00114 << filename
00115 << " materials = "
00116 << materials.size()
00117 << std::endl;
00118 return true;
00119 }
00120
00121 }
00122
00138 template<typename mesh_type>
00139 bool obj_read(
00140 std::string const & filename
00141 , mesh_type & mesh
00142 , bool keep_shared_vertices = true )
00143 {
00144 typedef typename mesh_type::math_types math_types;
00145 typedef typename math_types::value_traits value_traits;
00146 typedef typename math_types::vector3_type vector3_type;
00147 typedef typename math_types::real_type real_type;
00148 typedef typename mesh_type::vertex_handle vertex_handle;
00149 typedef typename mesh_type::vertex_iterator vertex_iterator;
00150 typedef typename mesh_type::face_handle face_handle;
00151 typedef typename mesh_type::index_type index_type;
00152 typedef math::Vector3<unsigned int> index_vector;
00153 typedef std::map<index_vector, vertex_handle> lut_type;
00154 typedef std::vector<vector3_type> vector3_container;
00155
00156 mesh.clear();
00157
00158 std::ifstream file(filename.c_str());
00159
00160 if(!file.is_open())
00161 {
00162 std::cerr << "obj_read - Could not load file: " << filename << std::endl;
00163 return false;
00164 }
00165
00166
00167
00168
00169
00170 std::string line,type;
00171
00172 vector3_container texture_coords;
00173 vector3_container normals;
00174 vector3_container positions;
00175 lut_type lut;
00176
00177 while(!file.eof())
00178 {
00179 if(getline(file,line)==0)
00180 break;
00181
00182
00183 std::stringstream stream(line);
00184
00185 stream >> type;
00186
00187 if(line[0] == '#')
00188 {
00189 continue;
00190 }
00191 else if(type == "g")
00192 {
00193 std::string group_name;
00194 stream >> group_name;
00195
00196 continue;
00197 }
00198 else if(type == "usemtl")
00199 {
00200 std::string material_name;
00201 stream >> material_name;
00202
00203 continue;
00204 }
00205 else if(type == "mtllib")
00206 {
00207 std::string material_filename;
00208 stream >> material_filename;
00209
00210 continue;
00211 }
00212 else if(type == "v")
00213 {
00214 vector3_type p;
00215 stream >> p(0);
00216 stream >> p(1);
00217 stream >> p(2);
00218 positions.push_back(p);
00219 }
00220 else if(type == "vt")
00221 {
00222 vector3_type tex;
00223 stream >> tex(0);
00224 if(!stream.eof())
00225 stream >> tex(1);
00226 if(!stream.eof())
00227 stream >> tex(2);
00228 texture_coords.push_back(tex);
00229 }
00230 else if(type == "vn")
00231 {
00232 vector3_type n;
00233 stream >> n(0);
00234 stream >> n(1);
00235 stream >> n(2);
00236 normals.push_back(n);
00237 }
00238 else if(type == "f")
00239 {
00240
00241
00242 std::list<vertex_handle> handles;
00243 while(!stream.eof())
00244 {
00245 std::string component;
00246 stream >> component;
00247
00248 if (component.empty())
00249 break;
00250
00251 std::vector<std::string> split_vector;
00252 boost::algorithm::split(split_vector, component, boost::algorithm::is_any_of("/"),boost::algorithm::token_compress_on);
00253
00254 assert(!split_vector.empty() || !"obj_read() : Internal error, no indices on face");
00255
00256 std::size_t cnt = split_vector.size();
00257 std::vector<unsigned int> indices;
00258
00259 for( std::vector<std::string>::iterator value = split_vector.begin(); value!=split_vector.end(); ++value)
00260 indices.push_back(boost::lexical_cast<unsigned int>(*value));
00261
00262 index_vector key;
00263 key.clear();
00264 if( cnt >= 1 )
00265 key(0) = indices[0];
00266 if( cnt >= 2 && !keep_shared_vertices)
00267 key(1) = indices[1];
00268 if( cnt >= 3 && !keep_shared_vertices)
00269 key(2) = indices[2];
00270
00271 typename lut_type::iterator lookup = lut.find(key);
00272 if( lookup==lut.end() )
00273 lut[key] = mesh.add_vertex( );
00274
00275 assert(!lut[key].is_null() || !"obj_read(): Could not find vertex");
00276
00277 handles.push_back( lut[key] );
00278 vertex_iterator v = mesh.get_vertex_iterator( lut[key] );
00279
00280 if( cnt >= 1 )
00281 v->m_coord = positions[ indices[0] - 1];
00282
00283 if( cnt >= 2 && !texture_coords.empty())
00284 {
00285 v->m_u = texture_coords[ indices[1] - 1 ](0);
00286 v->m_v = texture_coords[ indices[1] - 1 ](1);
00287 }
00288 else if( cnt >= 2 && !normals.empty())
00289 {
00290 v->m_normal = normals[ indices[1] - 1 ];
00291 }
00292 if( cnt >= 3 )
00293 v->m_normal = normals[ indices[2] - 1 ];
00294
00295
00296
00297
00298 }
00299 face_handle h = mesh.add_face(handles.begin(),handles.end());
00300
00301 assert(!h.is_null() || !"obj_read() : Internal error, could not create face");
00302
00303
00304 }
00305 else
00306 {
00307
00308 }
00309 }
00310 file.close();
00311 #ifndef NDEBUG
00312 std::cout << "obj_read() : "
00313 << filename
00314 << " nodes = "
00315 << mesh.size_vertices()
00316 << " faces = "
00317 << mesh.size_faces()
00318 << std::endl;
00319 #endif
00320 return true;
00321 }
00322
00323 }
00324 }
00325
00326
00327 #endif