Subversion Repositories gelsvn

Rev

Rev 612 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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