Rev 595 | Rev 605 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* ----------------------------------------------------------------------- *
* This file is part of GEL, http://www.imm.dtu.dk/GEL
* Copyright (C) the authors and DTU Informatics
* For license and list of authors, see ../../doc/intro.pdf
* ----------------------------------------------------------------------- */
#include "TriMesh.h"
#include "../CGLA/Vec3f.h"
#include <fstream>
#include <iostream>
using namespace std;
using namespace CGLA;
namespace Geometry {
namespace
{
string get_path(const string& _filename)
{
// Make sure we only have slashes and not backslashes
string filename = _filename;
replace(filename.begin(),filename.end(),'\\','/');
// Find the last occurrence of slash.
// Everything before is path.
size_t n = filename.rfind("/");
if(n > filename.size())
return "./";
string pathname(filename,0,n);
pathname.append("/");
return pathname;
}
}
class TriMeshObjLoader
{
TriMesh *mesh;
std::string pathname;
int get_vert(int i) {
assert(i!=0);
if (i<0) {
return mesh->geometry.no_vertices()+i;
} else
return i-1;
}
int get_normal(int i) {
if (i<0) {
return mesh->normals.no_vertices()+i;
} else
return i-1;
}
int get_texcoord(int i) {
if (i<0) {
return mesh->texcoords.no_vertices()+i;
} else
return i-1;
}
public:
TriMeshObjLoader(TriMesh *_mesh): mesh(_mesh) {}
void load(const std::string& filename);
void read_material_library(const string& filename);
};
void TriMeshObjLoader::read_material_library(const string& filename)
{
string fn = pathname + filename;
ifstream material_file(fn.data());
if(material_file)
{
string buf;
unsigned int nummaterials=0;
while(material_file >> buf)
{
switch(buf[0])
{
case 'n':
++nummaterials;
mesh->materials.push_back(Material());
material_file >> mesh->materials[nummaterials].name;
break;
case 'N':
switch(buf[1])
{
case 's':
material_file >> mesh->materials[nummaterials].shininess;
mesh->materials[nummaterials].shininess *= 128.0/1000.0;
break;
case 'i':
material_file >> mesh->materials[nummaterials].ior_in;
break;
}
break;
case 'K':
switch(buf[1])
{
case 'd':
material_file >> mesh->materials[nummaterials].diffuse;
break;
case 's':
material_file >> mesh->materials[nummaterials].specular;
break;
case 'a':
material_file >> mesh->materials[nummaterials].ambient;
break;
}
break;
case 'T':
material_file >> mesh->materials[nummaterials].transmission;
break;
case 'i':
material_file >> mesh->materials[nummaterials].illum;
break;
case 'm': // Map ... all maps are treated equally.
material_file >> mesh->materials[nummaterials].tex_name;
mesh->materials[nummaterials].has_texture = true;
mesh->materials[nummaterials].tex_path = pathname;
break;
case '#':
default:
material_file.ignore(1024, '\n');
break;
}
}
}
}
void TriMeshObjLoader::load(const std::string& filename)
{
pathname = get_path(filename);
ifstream obj_file(filename.data());
if(obj_file)
{
mesh->materials.resize(1);
string buf;
int current_material=0;
while(obj_file >> buf)
{
cout << buf[0] << endl;
switch(buf[0])
{
case 'v': // v, vn, vt
{
if(buf == "v")
{
Vec3f v_geo;
obj_file >> v_geo;
mesh->geometry.add_vertex(v_geo);
}
else if(buf == "vn")
{
Vec3f v_norm;
obj_file >> v_norm;
mesh->normals.add_vertex(v_norm);
}
else if(buf == "vt")
{
Vec3f v_tex;
obj_file >> v_tex[0] >> v_tex[1];
v_tex[2]=1;
mesh->texcoords.add_vertex(v_tex);
}
}
break;
case 'f':
{
char line[1024];
vector<int> v_indices;
vector<int> t_indices;
vector<int> n_indices;
obj_file.getline(line, 1022);
char* pch = strtok(line, " \t");
while(pch != 0)
{
int v,t,n;
if(sscanf(pch, "%d/%d/%d", &v, &t, &n)==3)
{
v_indices.push_back(get_vert(v));
t_indices.push_back(get_texcoord(t));
n_indices.push_back(get_normal(n));
}
else if(sscanf(pch, "%d//%d", &v, &n)==2)
{
v_indices.push_back(get_vert(v));
n_indices.push_back(get_normal(n));
}
else if(sscanf(pch, "%d/%d", &v, &t)==2)
{
v_indices.push_back(get_vert(v));
t_indices.push_back(get_texcoord(t));
}
else if(sscanf(pch, "%d", &v)==1)
v_indices.push_back(get_vert(v));
pch = strtok(0, " \t");
}
if(v_indices.size()>=3)
for(int i=0;i<=(v_indices.size()-3);++i)
{
int idx = mesh->geometry.add_face(Vec3i(v_indices[0], v_indices[i+1], v_indices[i+2]));
if(t_indices.size())
mesh->texcoords.add_face(Vec3i(t_indices[0], t_indices[i+1], t_indices[i+2]), idx);
if(n_indices.size())
mesh->normals.add_face(Vec3i(n_indices[0], n_indices[i+1], n_indices[i+2]), idx);
mesh->mat_idx.push_back(current_material);
}
}
break;
case 'm':
obj_file >> buf;
read_material_library(buf);
break;
case 'u':
obj_file >> buf;
current_material = mesh->find_material(buf);
break;
case '#':
default:
obj_file.ignore(1024, '\n');
break;
}
}
}
}
void obj_load(const string& filename, TriMesh &mesh)
{
TriMeshObjLoader loader(&mesh);
loader.load(filename);
}
/// Load materials from an MRL file
void mtl_load(const std::string& filename, std::vector<Material>& materials)
{
TriMesh m;
TriMeshObjLoader loader(&m);
loader.read_material_library(filename);
materials = m.materials;
}
}