4 #include "ObjMaterialReader.h"
15 #include <C2/util/container_cast.h>
16 #include <C2/util/string_util.h>
18 #include <LibGeo/Mesh/BaseMesh.h>
19 #include <LibGeo/Path.h>
20 #include <LibGeo/Utility/StringRef.h>
32 inline float ReadNextFloat(istream& ist)
36 return (float)atof(s.c_str());
39 inline void ReadVec(istream& ist, lm::vec2f& v)
41 v.x = ReadNextFloat(ist);
42 v.y = ReadNextFloat(ist);
45 inline void ReadVec(istream& ist, lm::vec3f& v)
47 v.x = ReadNextFloat(ist);
48 v.y = ReadNextFloat(ist);
49 v.z = ReadNextFloat(ist);
53 //
\83t
\83@
\83C
\83\8b\93Ç
\8d\9e
54 bool ObjMeshReader::Load( ObjMesh& mesh , const string& filename )
56 InitializeWorkBuffer();
58 m_LoadWorkDirPath = Path::GetParentDirPath(filename);
60 ifstream ifs( filename.c_str() );
66 if( !LoadObjMain( mesh , ifs , true ) )
77 //!
\83X
\83g
\83\8a\81[
\83\80\82©
\82ç
\82Ì
\93Ç
\82Ý
\8d\9e\82Ý
78 //!
\83}
\83e
\83\8a\83A
\83\8b\83t
\83@
\83C
\83\8b\82Í
\93Ç
\82Ý
\8d\9e\82Ü
\82È
\82¢
79 bool ObjMeshReader::LoadStream( ObjMesh& mesh , istream& ist )
81 return LoadObjMain( mesh , ist , false );
84 bool ObjMeshReader::LoadObjMain( ObjMesh& mesh , istream& ist , bool LoadMaterialFile )
100 ReadVertLine( ist , mesh.m_Verts );
102 else if( s[1] == 't' )
104 ReadUVLine( ist , mesh.m_UVs );
106 else if( s[1] == 'n' )
108 ReadNormLine( ist , mesh.m_Normals );
113 ReadFaceLine( ist , mesh );
117 ReadObjectSplitLine( ist , mesh );
121 ReadGroupSplitLine( ist , mesh );
123 else if( s == "usemtl" )
125 ReadMaterialSelectLine( ist , mesh );
127 else if( s == "mtllib" )
129 if( LoadMaterialFile )
131 ReadMaterialGroup( ist , mesh );
135 ReadToNextLine( ist );
140 ReadPolylineLine( ist , mesh.m_Polylines );
144 ReadToNextLine( ist );
148 if (!mesh.m_Objects.empty())
149 SetLastObjectVertNum(mesh);
154 void ObjMeshReader::InitializeWorkBuffer(void)
157 m_PrimaryMatIdx = -1;
159 m_GroupIdxMap.clear();
160 m_PrimaryGroupIdx = 0;
162 m_LoadWorkDirPath.clear();
165 void ObjMeshReader::ReadVertLine( istream& ist , vector<lm::vec3f>& verts )
169 verts.push_back(vert);
172 void ObjMeshReader::ReadNormLine( istream& ist , vector<lm::vec3f>& normals )
176 normals.push_back(norm);
179 void ObjMeshReader::ReadUVLine( istream& ist , vector<lm::vec2f>& uvs )
183 istringstream iss( s.c_str() );
190 void ToRefAry(std::string& s, std::vector<util::StringRef>& vs)
194 bool IsInWord = false;
195 char* str_begin = NULL;
196 for(size_t i = 0; i < s.size(); ++i)
200 bool IsNoChar = ((*c) == ' ' || (*c) == '\t' || (*c) == '\n');
205 vs.push_back(util::StringRef(str_begin, c));
221 char* str_last = &s[s.size()-1];
223 vs.push_back(util::StringRef(str_begin, str_last));
227 void ObjMeshReader::ReadFaceLine( istream& ist , ObjMesh& mesh )
229 vector<ObjFace>& faces = mesh.m_Faces;
231 faces.push_back(ObjFace());
232 ObjFace& face = faces.back();
238 std::vector<util::StringRef> vs;
241 for (size_t i = 0; i < vs.size(); ++i)
243 size_t slen = vs[i].GetLength();
244 char* s = vs[i].GetBegin();
245 if( !(s[0] >= '1' && s[0] <= '9') && s[0] != '-' )
251 for (size_t j = 0; j < slen; j++)
255 str_top[cnt_val] = &s[j+1];
262 int idx = atoi( str_top[0] );
264 idx = (int)mesh.m_Verts.size() + idx + 1;
266 face.m_IdxV.Add(mesh.m_FaceBuf.m_FaceIdxV, idx - 1);
269 if( cnt_val >= 2 && str_top[1][0] != '\0' )
271 int idx = atoi( str_top[1] );
273 idx = (int)mesh.m_UVs.size() + idx + 1;
275 face.m_IdxUV.Add(mesh.m_FaceBuf.m_FaceIdxUV, idx - 1);
280 int idx = atoi( str_top[2] );
282 idx = (int)mesh.m_Normals.size() + idx + 1;
284 face.m_IdxN.Add(mesh.m_FaceBuf.m_FaceIdxN, idx - 1);
288 face.m_GroupIdx = m_PrimaryGroupIdx;
289 face.m_MatNameIdx = m_PrimaryMatIdx;
292 void ObjMeshReader::ReadPolylineLine( std::istream& ist , std::vector<ObjPolyline>& lines )
294 lines.push_back(ObjPolyline());
295 ObjPolyline& line = lines.back();
302 if(!CheckAndModifyContinueToNextLine(s))
314 std::vector<util::StringRef> vs;
317 line.m_IdxV.resize(vs.size());
318 for(size_t i = 0; i < vs.size(); ++i)
320 char* s = vs[i].GetBegin();
321 char* e = vs[i].GetEnd();
323 line.m_IdxV[i] = atoi( s ) - 1;
326 line.m_GroupIdx = m_PrimaryGroupIdx;
329 bool ObjMeshReader::CheckAndModifyContinueToNextLine(std::string& s) const
331 size_t last_char = 0;
332 for(size_t i = s.size(); i > 0; --i)
335 if(c == ' ' || c == '\t')
345 if(s[last_char] != '\\')
352 void ObjMeshReader::ReadObjectSplitLine( std::istream& ist , ObjMesh& mesh )
354 if (!mesh.m_Objects.empty())
355 SetLastObjectVertNum(mesh);
357 SubObject new_object;
358 new_object.m_VertRange.Offset = (int)mesh.m_Verts.size();
359 new_object.m_NormRange.Offset = (int)mesh.m_Normals.size();
360 new_object.m_UVRange.Offset = (int)mesh.m_UVs.size();
361 new_object.m_FaceRange.Offset = (int)mesh.m_Faces.size();
363 GetLineWithTrimed( ist , new_object.m_Name );
365 mesh.m_Objects.push_back( new_object );
368 void ObjMeshReader::ReadGroupSplitLine( istream& ist , ObjMesh& mesh )
371 GetLineWithTrimed( ist , grp_name );
373 map<string, int>::iterator found = m_GroupIdxMap.find(grp_name);
374 if( found != m_GroupIdxMap.end() )
376 m_PrimaryGroupIdx = found->second;
380 int new_idx = static_cast<int>( mesh.m_Groups.size() );
381 mesh.m_Groups.push_back( ObjGroupInfo() );
382 mesh.m_Groups.back().m_Name = grp_name;
384 m_GroupIdxMap.insert( pair<string, int>( grp_name , new_idx ) );
385 m_PrimaryGroupIdx = new_idx;
389 void ObjMeshReader::ReadMaterialSelectLine( istream& ist , ObjMesh& mesh )
392 GetLineWithTrimed( ist , mat_name );
394 map<string, int>::iterator found = m_MatIdxMap.find(mat_name);
395 if( found != m_MatIdxMap.end() )
397 m_PrimaryMatIdx = found->second;
401 int new_idx = static_cast<int>( m_MatIdxMap.size() );
402 m_MatIdxMap[mat_name] = new_idx;
403 m_PrimaryMatIdx = new_idx;
405 mesh.m_MaterialNames.push_back( mat_name );
409 void ObjMeshReader::ReadMaterialGroup( istream& ist , ObjMesh& mesh )
412 GetLineWithTrimed( ist , mat_filename );
414 ObjMaterialGroup materials;
415 ObjMaterialReader reader(m_LoadWorkDirPath);
416 if(!reader.ReadMaterialFile(mat_filename, materials))
419 mesh.m_MaterialGroups.push_back( materials );
423 bool ObjMeshWriter::Save( const ObjMesh& mesh , const string& filename ) const
425 ofstream ofs( filename.c_str() );
429 return SaveObjMain( mesh , ofs );
432 bool ObjMeshWriter::SaveStream( const ObjMesh& mesh , ostream& ost ) const
434 return SaveObjMain( mesh , ost );
437 bool ObjMeshWriter::SaveObjMain( const ObjMesh& mesh , ostream& ost ) const
439 //
\92¸
\93_
\83o
\83b
\83t
\83@
440 for (const lm::vec3f& v : mesh.m_Verts)
442 ost << "v " << v.x << " " << v.y << " " << v.z << endl;
445 // UV
\83o
\83b
\83t
\83@
446 for(size_t i = 0; i < mesh.m_UVs.size(); ++i)
448 const lm::vec2f& uv = mesh.m_UVs[i];
449 ost << "vt " << uv.x << " " << uv.y << endl;
452 //
\96@
\90ü
\83o
\83b
\83t
\83@
453 for(size_t i = 0; i < mesh.m_Normals.size(); ++i)
455 const lm::vec3f& normal = mesh.m_Normals[i];
456 ost << "vn " << normal.x << " " << normal.y << " " << normal.z << endl;
459 for(size_t i = 0 ; i < mesh.m_Faces.size(); ++i)
461 const ObjFace& face = mesh.m_Faces[i];
462 if (face.m_IdxV.IsEmpty())
465 bool has_uv = !face.m_IdxUV.IsEmpty();
466 bool has_n = !face.m_IdxN.IsEmpty();
469 for (size_t j = 0; j < face.m_IdxV.m_Count; ++i)
473 vid = mesh.m_FaceBuf.m_FaceIdxV[face.m_IdxV.m_Offset + j];
476 uvid = mesh.m_FaceBuf.m_FaceIdxUV[face.m_IdxUV.m_Offset + j];
479 nid = mesh.m_FaceBuf.m_FaceIdxN[face.m_IdxN.m_Offset + j];
481 if( !has_uv && !has_n )
484 ost << " " << vid+1 << "/" << uvid+1;
486 ost << " " << vid+1 << "//" << nid+1;
488 ost << " " << vid+1 << "/" << uvid+1 << "/" << nid+1;
497 void ObjMeshReader::SetLastObjectVertNum(ObjMesh& mesh)
499 SubObject& last_obj = mesh.m_Objects.back();
500 last_obj.m_VertRange.NumElems = (int)mesh.m_Verts.size() - last_obj.m_VertRange.Offset;
501 last_obj.m_NormRange.NumElems = (int)mesh.m_Normals.size() - last_obj.m_NormRange.Offset;
502 last_obj.m_UVRange.NumElems = (int)mesh.m_UVs.size() - last_obj.m_UVRange.Offset;
503 last_obj.m_FaceRange.NumElems = (int)mesh.m_Faces.size() - last_obj.m_FaceRange.Offset;