Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

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