241 lines
6.5 KiB
C++
241 lines
6.5 KiB
C++
#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<std::string> v;
|
|
std::vector<std::string> 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; i<m->meshdataanz; 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
|