#include "loadobj.h" namespace segl { LoadOBJ::LoadOBJ(std::string _filename) : Modelloader(_filename) { } bool LoadOBJ::load(Model *m) { // Filestreams std::ifstream file(filename.c_str()); std::ifstream matfile; std::string inbuf; // TMP-Var std::vector v; std::vector v2; int anz; unsigned int vertanz=0, polyanz=0, matanz=0, texanz=0, normanz=0; std::string materials; // Punkt2D *texdata = 0; // texdataanz = 0; // Punkt3D *normdata = 0; // normdata = 0; Material *usemat; if(!file) return false; // start counting items, read file while(getline(file, inbuf)) { anz = explode(inbuf, " ", &v); if(!anz) continue; if(v[0]=="f") polyanz++; // polygon else if(v[0]=="v") vertanz++; // vertex else if(v[0]=="mtllib") { if(anz>1) materials = trim(v[1]); // std::cout << "V1: " << v[1] << std::endl; } else if(v[0]=="vt") texanz++; // texcoord else if(v[0]=="vn") normanz++; // normal } if(materials!="") { matfile.open((rbasename(filename)+materials).c_str()); if(matfile) { while(getline(matfile, inbuf)) { anz = explode(inbuf, " ", &v); if(!anz) continue; if(v[0]=="newmtl") matanz++; } } } // std::cout << "Vert: " << vertanz << " Poly: " << polyanz << " Mat: " << matanz << " (Matfile: " << materials << ") Norm: " << normanz << std::endl; if(!vertanz || !polyanz) return false; if(m->isLoaded()) m->unload(); // Allocate memory for filecontent m->meshdataanz = vertanz; m->meshdata = new Punkt3D[vertanz]; m->polydataanz = polyanz; m->polydata = new Meshpolygon[polyanz]; if(matanz) { m->matdataanz = matanz; m->matdata = new Material[matanz]; } m->texdataanz = texanz; m->texdata = new Punkt2D[matanz]; m->normdataanz = normanz; m->normdata = new Punkt3D[normanz]; // Readout Material matfile.clear(); matfile.seekg(0); if(matanz&&matfile) { // Got milk.. eh.. material? matanz = 0; Material mat; while(getline(matfile, inbuf)) { anz = explode(inbuf, " ", &v); if(!anz) continue; if(v[0]=="newmtl") { if(matanz!=0) m->matdata[matanz-1] = mat; // Push material matanz++; mat = Material(); mat.name = trim(v[1]); } else if(v[0]=="Ka") { if(anz<4) continue; mat.ambient.set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str())); } else if(v[0]=="Kd") { if(anz<4) continue; mat.diffuse.set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str())); } else if(v[0]=="Ks") { if(anz<4) continue; mat.specular.set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str())); } } // Last material wasnt pushed if(matanz!=0) m->matdata[matanz-1] = mat; } // Readout File usemat = &(m->backupmat); // If material required but not avilable use backup file.clear(); file.seekg(0); polyanz = vertanz = normanz = texanz = 0; // Reset counters while(getline(file, inbuf)) { anz = explode(inbuf, " ", &v); if(!anz) continue; if(v[0]=="v") { if(anz<4) continue; m->meshdata[vertanz].set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str())); vertanz++; } else if(v[0]=="vn") { if(anz<4) continue; m->normdata[normanz].set(std::atof(v[1].c_str()), std::atof(v[2].c_str()), std::atof(v[3].c_str())); normanz++; } else if(v[0]=="vt") { if(anz<3) continue; m->texdata[texanz].set(std::atof(v[1].c_str()), std::atof(v[2].c_str())); texanz++; } else if(v[0]=="f") { if(anz<4) continue; unsigned int arr[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} }; for(unsigned int i=0; i<3; i++) { int zanz = explode(v[i+1], "/", &v2); // std::cout << "explode " << v[i+1] << " anz " << zanz << std::endl; if(zanz<3) { if(zanz==1) arr[i][0] = std::atoi(v2[0].c_str()); continue; } arr[i][0] = std::atoi(v2[0].c_str()); arr[i][1] = std::atoi(v2[1].c_str()); arr[i][2] = std::atoi(v2[2].c_str()); // std::cout << "Loaded: " << arr[i][0] << " " << arr[i][1] << " " << arr[i][2] << " " << std::endl; // std::cout << "From: " << v2[0] << " " << v2[1] << " " << v2[2] << " " << std::endl; } if(arr[0][0]) m->polydata[polyanz].m1.point = &(m->meshdata[arr[0][0]-1]); if(arr[0][1]) m->polydata[polyanz].m1.tex = &(m->texdata[arr[0][1]-1]); if(arr[0][2]) m->polydata[polyanz].m1.normal = &(m->normdata[arr[0][2]-1]); if(arr[1][0]) m->polydata[polyanz].m2.point = &(m->meshdata[arr[1][0]-1]); if(arr[1][1]) m->polydata[polyanz].m2.tex = &(m->texdata[arr[1][1]-1]); if(arr[1][2]) m->polydata[polyanz].m2.normal = &(m->normdata[arr[1][2]-1]); if(arr[2][0]) m->polydata[polyanz].m3.point = &(m->meshdata[arr[2][0]-1]); if(arr[2][1]) m->polydata[polyanz].m3.tex = &(m->texdata[arr[2][1]-1]); if(arr[2][2]) m->polydata[polyanz].m3.normal = &(m->normdata[arr[2][2]-1]); // std::cout << "POLY " << polyanz << std::endl; polyanz++; } else if(v[0]=="usemtl") { if(anz<2) continue; std::string fterm = trim(v[1]); for(unsigned int i=0; i < m->matdataanz; i++) { if(m->matdata[i].name==fterm) { usemat = &(m->matdata[i]); break; } } } v.clear(); } // Calculate bounding box and rad for sphere float minx=m->meshdata[0].x, maxx=m->meshdata[0].x, miny=m->meshdata[0].y, maxy=m->meshdata[0].y, minz=m->meshdata[0].z, maxz=m->meshdata[0].z; for(unsigned int i=0; imeshdataanz; i++) { m->boundingrad = std::max(m->boundingrad, abs(m->meshdata[i])); minx = std::min(minx, m->meshdata[i].x); maxx = std::max(maxx, m->meshdata[i].x); miny = std::min(miny, m->meshdata[i].y); maxy = std::max(maxy, m->meshdata[i].y); minz = std::min(minz, m->meshdata[i].z); maxz = std::max(maxz, m->meshdata[i].z); } // std::cout << "(" << minx << ", " << maxx << ") " << "(" << miny << ", " << maxy << ") " << "(" << minz << ", " << maxz << ") " << std::endl; m->boundingbox.d.set(minx, miny, minz); m->boundingbox.a.set(minx, miny, maxz); m->boundingbox.b.set(maxx, miny, maxz); m->boundingbox.c.set(maxx, miny, minz); m->boundingbox.h.set(minx, maxy, minz); m->boundingbox.e.set(minx, maxy, maxz); m->boundingbox.f.set(maxx, maxy, maxz); m->boundingbox.g.set(maxx, maxy, minz); // m->boundingrad = std::max( std::abs(minx)+std::abs(maxx), // std::max( std::abs(miny)+std::abs(maxy), // std::abs(minz)+std::abs(maxz))); m->loaded = true; // std::cout << "Loaded!" << std::endl; return true; } } // namespace segl