Subversion Repositories gelsvn

Rev

Rev 605 | Rev 612 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
595 jab 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
79 jab 6
 
7
#include "TriMesh.h"
601 jab 8
#include "../CGLA/Vec3f.h"
595 jab 9
#include <fstream>
79 jab 10
#include <iostream>
11
 
12
using namespace std;
13
using namespace CGLA;
14
 
15
namespace Geometry {
595 jab 16
 
79 jab 17
	namespace
18
	{
19
		string get_path(const string& _filename)
20
		{
21
			// Make sure we only have slashes and not backslashes
22
			string filename = _filename;
23
			replace(filename.begin(),filename.end(),'\\','/');
24
 
25
			// Find the last occurrence of slash.
26
			// Everything before is path.
595 jab 27
			size_t n = filename.rfind("/");
79 jab 28
			if(n > filename.size())
29
				return "./";
595 jab 30
			string pathname(filename,0,n);
79 jab 31
			pathname.append("/");
32
			return pathname;
33
		}
34
	}
35
	class TriMeshObjLoader
36
	{
37
		TriMesh *mesh;
38
		std::string pathname;
595 jab 39
 
79 jab 40
		int get_vert(int i) {
41
			assert(i!=0);
42
			if (i<0) {
43
				return mesh->geometry.no_vertices()+i;
44
			} else
45
				return i-1;
46
		}
595 jab 47
 
79 jab 48
		int get_normal(int i) {
49
			if (i<0) {
50
				return mesh->normals.no_vertices()+i;
51
			} else
52
				return i-1;
53
		}
595 jab 54
 
79 jab 55
		int get_texcoord(int i) {
56
			if (i<0) {
57
				return mesh->texcoords.no_vertices()+i;
58
			} else
59
				return i-1;
60
		}
606 jrf 61
 
62
    void read_material_library(const string& filename, vector<Material>& materials);
63
 
79 jab 64
	public:
595 jab 65
 
79 jab 66
		TriMeshObjLoader(TriMesh *_mesh): mesh(_mesh) {}
67
 
68
		void load(const std::string& filename);
595 jab 69
 
606 jrf 70
    void load_material_library(const string& filename, vector<Material>& materials)
71
    {
72
      pathname = get_path(filename);
73
      read_material_library(filename, materials);
74
    }        
79 jab 75
	};
76
 
606 jrf 77
	void TriMeshObjLoader::read_material_library(const string& filename, vector<Material>& materials)
79 jab 78
	{
606 jrf 79
    string fn = pathname + filename;
80
    ifstream material_file(fn.data());  
81
    if(!material_file)
82
    {
83
      cerr << "Could not open " << filename << endl;
84
      return;
85
    }
86
 
87
    string buf;
88
    unsigned int nummaterials=0;
89
    while(material_file >> buf)
90
    {
91
      switch(buf[0])
92
      {
93
      case 'n':
94
        ++nummaterials;
95
        mesh->materials.push_back(Material());
96
        material_file >> materials[nummaterials].name;
97
        break;
98
      case 'N':
99
        switch(buf[1])
595 jab 100
        {
606 jrf 101
        case 's':
102
          material_file >> materials[nummaterials].shininess;
103
          materials[nummaterials].shininess *= 128.0f/1000.0f;
104
          break;
105
        case 'i':
106
          material_file >> materials[nummaterials].ior;
107
          break;
595 jab 108
        }
606 jrf 109
        break;
110
      case 'K':
111
        switch(buf[1])
112
        {
113
        case 'd':
114
          material_file >> materials[nummaterials].diffuse[0]
115
                        >> materials[nummaterials].diffuse[1]
116
                        >> materials[nummaterials].diffuse[2];
117
          break;
118
        case 's':
119
          material_file >> materials[nummaterials].specular[0]
120
                        >> materials[nummaterials].specular[1]
121
                        >> materials[nummaterials].specular[2];
122
          break;
123
        case 'a':
124
          material_file >> materials[nummaterials].ambient[0]
125
                        >> materials[nummaterials].ambient[1]
126
                        >> materials[nummaterials].ambient[2];
127
          break;
128
        }
129
        break;
130
      case 'T':
131
        material_file >> materials[nummaterials].transmission[0]
132
                      >> materials[nummaterials].transmission[1]
133
                      >> materials[nummaterials].transmission[2];
134
        break;
135
      case 'i':
136
        material_file >> materials[nummaterials].illum;
137
        break;
138
      case 'm': // Map ... all maps are treated equally.
139
        material_file >> materials[nummaterials].tex_name;
140
        materials[nummaterials].has_texture = true;
141
        materials[nummaterials].tex_path = pathname;
142
        break;
143
      case '#':
144
      default:
145
        material_file.ignore(1024, '\n');
146
        break;
147
      }
595 jab 148
    }
606 jrf 149
  }
595 jab 150
 
606 jrf 151
  void TriMeshObjLoader::load(const std::string& filename)
152
  {
153
    pathname = get_path(filename);
154
    ifstream obj_file(filename.data());
155
    if(!obj_file)
156
    {
157
			cerr << "File " << filename << " does not exist" << endl;
158
      exit(0);
159
    }
160
 
161
    mesh->materials.resize(1);
162
    string buf;
163
    int current_material=0;
164
    while(obj_file >> buf)
165
    {
166
      switch(buf[0])
167
      {
168
      case 'v': // v, vn, vt
595 jab 169
        {
606 jrf 170
          if(buf == "v")
171
          {
172
            Vec3f v_geo;
173
            obj_file >> v_geo;
174
            mesh->geometry.add_vertex(v_geo);
175
          }
176
          else if(buf == "vn")
177
          {
178
            Vec3f v_norm;
179
            obj_file >> v_norm;
180
            mesh->normals.add_vertex(v_norm);
181
          }
182
          else if(buf == "vt")
183
          {
184
            Vec3f v_tex;
185
            obj_file >> v_tex[0] >> v_tex[1];
186
            v_tex[2]=1;
187
            mesh->texcoords.add_vertex(v_tex);
188
          }
189
        }
190
        break;
191
      case 'f':
192
        {
193
          char line[1024];
595 jab 194
 
606 jrf 195
          vector<int> v_indices;
196
          vector<int> t_indices;
197
          vector<int> n_indices;
595 jab 198
 
606 jrf 199
          obj_file.getline(line, 1022);
200
          char* pch = strtok(line, " \t");
201
          while(pch != 0)
202
          {
203
            int v,t,n;
204
            if(sscanf(pch, "%d/%d/%d", &v, &t, &n)==3)
205
            {
206
              v_indices.push_back(get_vert(v));
207
              t_indices.push_back(get_texcoord(t));
208
              n_indices.push_back(get_normal(n));
595 jab 209
            }
606 jrf 210
            else if(sscanf(pch, "%d//%d", &v, &n)==2)
211
            {
212
              v_indices.push_back(get_vert(v));
213
              n_indices.push_back(get_normal(n));
214
            }
215
            else if(sscanf(pch, "%d/%d", &v, &t)==2)
216
            {
217
              v_indices.push_back(get_vert(v));
218
              t_indices.push_back(get_texcoord(t));
219
            }
220
            else if(sscanf(pch, "%d", &v)==1)
221
              v_indices.push_back(get_vert(v));
222
            pch = strtok(0, " \t");
223
          }
224
          if(v_indices.size()>=3)
225
            for(size_t i=0;i<=(v_indices.size()-3);++i)
226
            {
227
              int idx = mesh->geometry.add_face(Vec3i(v_indices[0], v_indices[i+1], v_indices[i+2]));
228
              if(t_indices.size())
229
              mesh->texcoords.add_face(Vec3i(t_indices[0], t_indices[i+1], t_indices[i+2]), idx);
230
              if(n_indices.size())
231
              mesh->normals.add_face(Vec3i(n_indices[0], n_indices[i+1], n_indices[i+2]), idx);
232
              mesh->mat_idx.push_back(current_material);
233
            }
595 jab 234
        }
606 jrf 235
        break;
236
      case 'm':
237
        obj_file >> buf;
238
        read_material_library(buf, mesh->materials);
239
        break;
240
      case 'u':
241
        obj_file >> buf;
242
        current_material = mesh->find_material(buf);
243
        break;
244
      case '#':
245
      default:
246
        obj_file.ignore(1024, '\n');
247
        break;                        
248
      }
595 jab 249
    }
606 jrf 250
  }
595 jab 251
 
252
	void obj_load(const string& filename, TriMesh &mesh)
79 jab 253
	{
254
		TriMeshObjLoader loader(&mesh);
255
		loader.load(filename);
256
	}
595 jab 257
 
606 jrf 258
  /// Load materials from an MTL file
259
  void mtl_load(const std::string& filename, std::vector<Material>& materials)
260
  {
261
    TriMeshObjLoader loader(0);
262
    loader.load_material_library(filename, materials);
263
  }    
79 jab 264
}