Subversion Repositories gelsvn

Rev

Rev 510 | Rev 601 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 510 Rev 595
Line -... Line 1...
-
 
1
/* ----------------------------------------------------------------------- *
-
 
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
1
// bdl, jab, feb 2005
3
 * Copyright (C) the authors and DTU Informatics
2
// Inspired and partly lifted from Nate Robins' Obj loader
4
 * For license and list of authors, see ../../doc/intro.pdf
-
 
5
 * ----------------------------------------------------------------------- */
3
 
6
 
4
#include "TriMesh.h"
7
#include "TriMesh.h"
5
#include <CGLA/Vec3f.h>
8
#include <CGLA/Vec3f.h>
6
#include <stdio.h>
9
#include <fstream>
7
#include <iostream>
10
#include <iostream>
8
 
11
 
9
using namespace std;
12
using namespace std;
10
using namespace CGLA;
13
using namespace CGLA;
11
 
14
 
12
namespace Geometry {
15
namespace Geometry {
13
 
16
    
14
	namespace
17
	namespace
15
	{
18
	{
16
		string get_path(const string& _filename)
19
		string get_path(const string& _filename)
17
		{
20
		{
18
			// Make sure we only have slashes and not backslashes
21
			// Make sure we only have slashes and not backslashes
19
			string filename = _filename;
22
			string filename = _filename;
20
			replace(filename.begin(),filename.end(),'\\','/');
23
			replace(filename.begin(),filename.end(),'\\','/');
21
			
24
			
22
			// Find the last occurrence of slash.
25
			// Find the last occurrence of slash.
23
			// Everything before is path.
26
			// Everything before is path.
24
			unsigned int n = filename.rfind("/");
27
			size_t n = filename.rfind("/");
25
			if(n > filename.size())
28
			if(n > filename.size())
26
				return "./";
29
				return "./";
27
			string pathname = "";
-
 
28
			pathname.assign(filename,0,n);
30
			string pathname(filename,0,n);
29
			pathname.append("/");
31
			pathname.append("/");
30
			return pathname;
32
			return pathname;
31
		}
33
		}
32
	}
34
	}
33
	class TriMeshObjLoader
35
	class TriMeshObjLoader
34
	{
36
	{
35
		TriMesh *mesh;
37
		TriMesh *mesh;
36
		std::string pathname;
38
		std::string pathname;
37
 
39
        
38
		int get_vert(int i) {
40
		int get_vert(int i) {
39
			assert(i!=0);
41
			assert(i!=0);
40
			if (i<0) {
42
			if (i<0) {
41
				return mesh->geometry.no_vertices()+i;
43
				return mesh->geometry.no_vertices()+i;
42
			} else
44
			} else
43
				return i-1;
45
				return i-1;
44
		}
46
		}
45
 
47
        
46
		int get_normal(int i) {
48
		int get_normal(int i) {
47
			if (i<0) {
49
			if (i<0) {
48
				return mesh->normals.no_vertices()+i;
50
				return mesh->normals.no_vertices()+i;
49
			} else
51
			} else
50
				return i-1;
52
				return i-1;
51
		}
53
		}
52
 
54
        
53
		int get_texcoord(int i) {
55
		int get_texcoord(int i) {
54
			if (i<0) {
56
			if (i<0) {
55
				return mesh->texcoords.no_vertices()+i;
57
				return mesh->texcoords.no_vertices()+i;
56
			} else
58
			} else
57
				return i-1;
59
				return i-1;
58
		}
60
		}
59
 
-
 
60
		void read_material_library(const string& filename, vector<Material>& materials);
-
 
61
 
61
		
62
	public:
62
	public:
63
 
63
        
64
		TriMeshObjLoader(TriMesh *_mesh): mesh(_mesh) {}
64
		TriMeshObjLoader(TriMesh *_mesh): mesh(_mesh) {}
65
		
65
		
66
		void load(const std::string& filename);
66
		void load(const std::string& filename);
67
    void load_material_library(const string& filename, vector<Material>& materials)
-
 
68
    {
67
        
69
      pathname = get_path(filename);
-
 
70
      read_material_library(filename, materials);
68
		void read_material_library(const string& filename);
71
    }
69
        
72
	};
70
	};
73
	
71
	
74
	void TriMeshObjLoader::read_material_library(const string& filename, vector<Material>& materials)
72
	void TriMeshObjLoader::read_material_library(const string& filename)
75
	{
73
	{
76
		string fn = pathname + filename;
74
		string fn = pathname + filename;
77
		FILE* file = fopen(fn.data(), "r");
75
        ifstream material_file(fn.data());
-
 
76
        
78
		if (!file) 
77
		if(material_file)
79
			{
78
        {
-
 
79
            string buf;
-
 
80
            unsigned int nummaterials=0;
80
				cerr << "Could not open " << filename << endl;
81
            while(material_file >> buf)
81
				return;
82
            {
82
			}
83
                switch(buf[0])
83
			
-
 
84
		char  buf[128];
84
                {
-
 
85
                    case 'n':
85
		unsigned int nummaterials=1;
86
                        ++nummaterials;
86
			
-
 
87
		// count the number of materials in the file 
87
                        mesh->materials.push_back(Material());
-
 
88
                        material_file >> mesh->materials[nummaterials].name;
-
 
89
                        break;
-
 
90
                    case 'N':
88
		while(fscanf(file, "%s", buf) != EOF) 
91
                        switch(buf[1])
89
			{
92
                    {
-
 
93
                        case 's':
-
 
94
                            material_file >> mesh->materials[nummaterials].shininess;
-
 
95
                            mesh->materials[nummaterials].shininess *= 128.0/1000.0;
-
 
96
                            break;
-
 
97
                        case 'i':
-
 
98
                            material_file >> mesh->materials[nummaterials].ior_in;
-
 
99
                            break;
-
 
100
                    }
-
 
101
                        break;
-
 
102
                    case 'K':
90
				switch(buf[0]) 
103
                        switch(buf[1])
91
					{
104
					{
92
					case '#':				/* comment */
105
                        case 'd':
93
						/* eat up rest of line */
106
                            material_file >> mesh->materials[nummaterials].diffuse;
94
						fgets(buf, sizeof(buf), file);
107
                            break;
95
						break;
-
 
96
					case 'n':				/* newmtl */
108
                        case 's':
97
						fgets(buf, sizeof(buf), file);
109
                            material_file >> mesh->materials[nummaterials].specular;
98
						nummaterials++;
-
 
99
						sscanf(buf, "%s %s", buf, buf);
110
                            break;
100
						break;
-
 
101
					default:
-
 
102
						/* eat up rest of line */
111
                        case 'a':
103
						fgets(buf, sizeof(buf), file);
112
                            material_file >> mesh->materials[nummaterials].ambient;
104
						break;
113
                            break;
105
					}
114
					}
106
			}
-
 
107
		rewind(file);
-
 
108
		
-
 
109
		/* allocate memory for the materials */
-
 
110
		materials.resize(nummaterials);
-
 
111
 
-
 
112
		/* now, read in the data */
-
 
113
		nummaterials = 0;
-
 
114
		while(fscanf(file, "%s", buf) != EOF) {
-
 
115
			switch(buf[0]) {
-
 
116
			case '#':				/* comment */
-
 
117
				/* eat up rest of line */
115
                        break;
118
				fgets(buf, sizeof(buf), file);
-
 
119
				break;
-
 
120
			case 'n':				/* newmtl */
-
 
121
				fgets(buf, sizeof(buf), file);
-
 
122
				sscanf(buf, "%s %s", buf, buf);
-
 
123
				nummaterials++;
-
 
124
				materials[nummaterials].name = buf;
-
 
125
				break;
-
 
126
			case 'N':
-
 
127
        switch(buf[1])
-
 
128
          {
-
 
129
          case 's':
116
                    case 'T':
130
				    fscanf(file, "%f", &materials[nummaterials].shininess);
117
                        material_file >> mesh->materials[nummaterials].transmission;
131
				    /* wavefront shininess is from [0, 1000], so scale for OpenGL */
-
 
132
				    materials[nummaterials].shininess /= 1000.0;
-
 
133
				    materials[nummaterials].shininess *= 128.0;
-
 
134
            break;
118
                        break;
135
          case 'i':
119
                    case 'i':
136
				    fscanf(file, "%f", &materials[nummaterials].ior);
120
                        material_file >> mesh->materials[nummaterials].illum;
137
            break;
121
                        break;
138
					default:
-
 
139
						/* eat up rest of line */
-
 
140
						fgets(buf, sizeof(buf), file);
-
 
141
						break;
-
 
142
          }
-
 
143
				break;
-
 
144
			case 'K': 
-
 
145
				switch(buf[1]) 
-
 
146
					{
-
 
147
					case 'd':
-
 
148
						fscanf(file, "%f %f %f",
-
 
149
									 &materials[nummaterials].diffuse[0],
-
 
150
									 &materials[nummaterials].diffuse[1],
-
 
151
									 &materials[nummaterials].diffuse[2]);
-
 
152
						break;
-
 
153
					case 's':
-
 
154
						fscanf(file, "%f %f %f",
-
 
155
									 &materials[nummaterials].specular[0],
122
                    case 'm': // Map ... all maps are treated equally.
156
									 &materials[nummaterials].specular[1],
123
                        material_file >> mesh->materials[nummaterials].tex_name;
157
									 &materials[nummaterials].specular[2]);
124
                        mesh->materials[nummaterials].has_texture = true;
158
						break;
-
 
159
					case 'a':
-
 
160
						fscanf(file, "%f %f %f",
-
 
161
									 &materials[nummaterials].ambient[0],
-
 
162
									 &materials[nummaterials].ambient[1],
-
 
163
									 &materials[nummaterials].ambient[2]);
125
                        mesh->materials[nummaterials].tex_path = pathname;
164
						break;
-
 
165
					default:
-
 
166
						/* eat up rest of line */
126
                        break;
167
						fgets(buf, sizeof(buf), file);
-
 
168
						break;
-
 
169
					}
-
 
170
				break;
-
 
171
      case 'T':
127
                    case '#':
172
				fscanf(file, "%f %f %f",
128
                    default:
173
               &materials[nummaterials].transmission[0],
129
                        material_file.ignore(1024, '\n');
174
               &materials[nummaterials].transmission[1],
130
                        break;
175
               &materials[nummaterials].transmission[2]);
131
                        
176
        break;
132
                }
177
      case 'i':
133
            }
178
				fscanf(file, "%d", &materials[nummaterials].illum);
-
 
179
        break;
134
        }
180
			case 'm': // Map ... all maps are treated equally.
-
 
181
				{
-
 
182
					fscanf(file,"%s",buf);
-
 
183
					materials[nummaterials].tex_path = pathname;
-
 
184
					materials[nummaterials].tex_name = string(buf);
-
 
185
          materials[nummaterials].has_texture = true;
-
 
186
				}
135
    }
187
				break;
-
 
188
			default:
-
 
189
				/* eat up rest of line */
-
 
190
				fgets(buf, sizeof(buf), file);
-
 
191
				break;
-
 
192
			}
136
    
193
		}
137
    
194
    fclose(file);
-
 
195
	}
-
 
196
 
-
 
197
 
-
 
198
	void TriMeshObjLoader::load(const std::string& filename) 
138
	void TriMeshObjLoader::load(const std::string& filename)
199
	{
139
	{
200
		pathname = get_path(filename);
140
		pathname = get_path(filename);
201
		FILE *fp = fopen(filename.data(), "r");
141
        ifstream obj_file(filename.data());
202
		if (fp==0) {
142
        if(obj_file)
203
			cerr << "File " << filename << " does not exist" << endl;
143
        {
204
      exit(0);
144
            mesh->materials.resize(1);
205
		}
145
            string buf;
206
		mesh->materials.resize(1);
146
            int current_material=0;
207
		
147
            while(obj_file >> buf)
208
		char buf[256];
148
            {
209
		Vec3f v_geo;
149
                cout << buf[0] << endl;
210
		Vec3f v_normals;
150
                switch(buf[0])
211
		Vec3f v_texcoords;
151
                {
212
 
152
                    case 'v': // v, vn, vt
213
		Vec3i f_geo;
153
                    {
214
		Vec3i f_normals;
154
                        if(buf == "v")
215
		Vec3i f_texcoords;
155
                        {
216
		int current_material=0;
156
                            Vec3f v_geo;
217
		int v,n,t;
157
                            obj_file >> v_geo;
218
		while(fscanf(fp, "%s", buf) != EOF) 
158
                            mesh->geometry.add_vertex(v_geo);
219
			{
159
                        }
220
				switch(buf[0]) 
160
                        else if(buf == "vn")
221
					{
161
                        {
222
					case '#': // A comment
162
                            Vec3f v_norm;
223
						fgets(buf, sizeof(buf), fp);
163
                            obj_file >> v_norm;
224
						break;
164
                            mesh->normals.add_vertex(v_norm);
225
					case 'm':
165
                        }
226
						fgets(buf, sizeof(buf), fp);
166
                        else if(buf == "vt")
227
						sscanf(buf, "%s %s", buf, buf);
167
                        {
228
						read_material_library(buf, mesh->materials);
168
                            Vec3f v_tex;
229
						break;
169
                            obj_file >> v_tex[0] >> v_tex[1];
230
					case 'u':
170
                            v_tex[2]=1;
231
						fgets(buf, sizeof(buf), fp);
171
                            mesh->texcoords.add_vertex(v_tex);
232
						sscanf(buf, "%s %s", buf, buf);
172
                        }
233
						current_material = mesh->find_material(buf);
173
                    }
234
						break;
174
                        break;
235
					case 'v': // v, vn, vt
175
                    case 'f':
236
						switch(buf[1]) 
176
                    {
237
							{
177
                        char line[1024];
238
							case '\0': // vertex
178
                        
239
								fscanf(fp, "%f %f %f", &v_geo[0], &v_geo[1], &v_geo[2]);
179
                        vector<int> v_indices;
240
								mesh->geometry.add_vertex(v_geo);
180
                        vector<int> t_indices;
241
								break;
181
                        vector<int> n_indices;
242
							case 'n': // normal
182
                        
243
								fscanf(fp, "%f %f %f", &v_normals[0], &v_normals[1], &v_normals[2]);
183
                        obj_file.getline(line, 1022);
244
								mesh->normals.add_vertex(v_normals);
184
                        char* pch = strtok(line, " \t");
245
								break;
185
                        while(pch != 0)
246
							case 't': // texcoord
186
                        {
247
								fscanf(fp, "%f %f", &v_texcoords[0], &v_texcoords[1]);
187
                            int v,t,n;
248
								v_texcoords[2]=1;
188
                            if(sscanf(pch, "%d/%d/%d", &v, &t, &n)==3)
249
								mesh->texcoords.add_vertex(v_texcoords);
189
                            {
250
								break;
190
                                v_indices.push_back(get_vert(v));
251
							}
191
                                t_indices.push_back(get_texcoord(t));
252
						break;
192
                                n_indices.push_back(get_normal(n));
253
					case 'f':
193
                            }
254
						v = n = t = 0;
194
                            else if(sscanf(pch, "%d//%d", &v, &n)==2)
255
						fscanf(fp, "%s", buf);
195
                            {
256
						// can be one of %d, %d//%d, %d/%d, %d/%d/%d 
196
                                v_indices.push_back(get_vert(v));
257
						if(sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3)
197
                                n_indices.push_back(get_normal(n));
258
							{ // v/t/n
198
                            }
259
								
199
                            else if(sscanf(pch, "%d/%d", &v, &t)==2)
260
								f_geo[0]=get_vert(v); 
200
                            {
261
								f_texcoords[0]=get_texcoord(t);
201
                                v_indices.push_back(get_vert(v));
262
								f_normals[0]=get_normal(n);
202
                                t_indices.push_back(get_texcoord(t));
263
 
203
                            }
264
								fscanf(fp, "%d/%d/%d", &v, &t, &n); 
204
                            else if(sscanf(pch, "%d", &v)==1)
265
								f_geo[1]=get_vert(v); 
205
                                v_indices.push_back(get_vert(v));
266
								f_texcoords[1]=get_texcoord(t);
206
                            pch = strtok(0, " \t");
267
								f_normals[1]=get_normal(n);
207
                        }
268
 
208
                        if(v_indices.size()>=3)
269
								fscanf(fp, "%d/%d/%d", &v, &t, &n); 
209
                            for(int i=0;i<=(v_indices.size()-3);++i)
270
								f_geo[2]=get_vert(v); 
210
                            {
271
								f_texcoords[2]=get_texcoord(t);
211
                                int idx = mesh->geometry.add_face(Vec3i(v_indices[0], v_indices[i+1], v_indices[i+2]));
272
								f_normals[2]=get_normal(n);
212
                                if(t_indices.size())
273
 
213
                                    mesh->texcoords.add_face(Vec3i(t_indices[0], t_indices[i+1], t_indices[i+2]), idx);
274
								int idx = mesh->geometry.add_face(f_geo);
214
                                if(n_indices.size())
275
								mesh->normals.add_face(f_normals, idx);
215
                                    mesh->normals.add_face(Vec3i(n_indices[0], n_indices[i+1], n_indices[i+2]), idx);
276
								mesh->texcoords.add_face(f_texcoords, idx);
216
                                mesh->mat_idx.push_back(current_material);
277
								mesh->mat_idx.push_back(current_material);
217
                            }
278
 
218
                    }
279
								// Load a general polygon and convert to triangles
219
                        break;
280
								while(fscanf(fp, "%d/%d/%d", &v, &t, &n)==3) 
220
                    case 'm':
281
									{
221
                        obj_file >> buf;
282
										f_geo[1]=f_geo[2];
222
                        read_material_library(buf);
283
										f_normals[1]=f_normals[2];
223
                        break;
284
										f_texcoords[1]=f_texcoords[2];
224
                    case 'u':
285
 
225
                        obj_file >> buf;
286
										f_geo[2]=get_vert(v);
226
                        current_material = mesh->find_material(buf);
287
										f_normals[2]=get_normal(n);
227
                        break;
288
										f_texcoords[2]=get_texcoord(t);
228
                    case '#':
289
 
229
                    default:
290
										int idx = mesh->geometry.add_face(f_geo);
230
                        obj_file.ignore(1024, '\n');
291
										mesh->normals.add_face(f_normals, idx);
231
                        break;
292
										mesh->texcoords.add_face(f_texcoords, idx);
232
                        
293
										mesh->mat_idx.push_back(current_material);
233
                }
294
									}
234
            }
295
							} 
235
        }
296
						else if (sscanf(buf, "%d//%d", &v, &n)==2)
236
    }
297
							{// v//n 
237
    
298
								f_geo[0]=get_vert(v);
238
	void obj_load(const string& filename, TriMesh &mesh)
299
								f_normals[0]=get_normal(n);
-
 
300
 
-
 
301
								fscanf(fp, "%d//%d", &v, &n); 
-
 
302
								f_geo[1]=get_vert(v);
-
 
303
								f_normals[1]=get_normal(n);
-
 
304
								
-
 
305
								fscanf(fp, "%d//%d", &v, &n); 
-
 
306
								f_geo[2]=get_vert(v);
-
 
307
								f_normals[2]=get_normal(n);
-
 
308
								
-
 
309
								int idx = mesh->geometry.add_face(f_geo);
-
 
310
								mesh->normals.add_face(f_normals, idx);
-
 
311
								mesh->mat_idx.push_back(current_material);
-
 
312
								
-
 
313
								// Load a general polygon and convert to triangles
-
 
314
								while(fscanf(fp, "%d//%d", &v, &n)==2) 
-
 
315
									{
-
 
316
										f_geo[1]=f_geo[2];
-
 
317
										f_normals[1]=f_normals[2];
-
 
318
										f_geo[2]=get_vert(v);
-
 
319
										int idx = mesh->geometry.add_face(f_geo);
-
 
320
										mesh->normals.add_face(f_normals, idx);
-
 
321
										mesh->mat_idx.push_back(current_material);
-
 
322
									}
-
 
323
							} 
-
 
324
						else if (sscanf(buf, "%d/%d", &v, &t) == 2)
-
 
325
							{ // v/t 
-
 
326
								f_geo[0]=get_vert(v);
-
 
327
								f_texcoords[0]=get_texcoord(t);
-
 
328
 
-
 
329
								fscanf(fp, "%d/%d", &v, &t); 
-
 
330
								f_geo[1]=get_vert(v);
-
 
331
								f_texcoords[1]=get_texcoord(t);
-
 
332
 
-
 
333
								fscanf(fp, "%d/%d", &v, &t); 
-
 
334
								f_geo[2]=get_vert(v);
-
 
335
								f_texcoords[2]=get_texcoord(t);
-
 
336
 
-
 
337
								int idx = mesh->geometry.add_face(f_geo);
-
 
338
								mesh->texcoords.add_face(f_texcoords, idx);
-
 
339
								mesh->mat_idx.push_back(current_material);
-
 
340
						
-
 
341
								// Load a general polygon and convert to triangles
-
 
342
								while(fscanf(fp, "%d/%d", &v, &t)==2) 
-
 
343
									{
-
 
344
										f_geo[1]=f_geo[2];
-
 
345
										f_texcoords[1]=f_texcoords[2];
-
 
346
								
-
 
347
										f_geo[2]=get_vert(v);
-
 
348
										f_texcoords[2]=get_texcoord(t);
-
 
349
 
-
 
350
										int idx = mesh->geometry.add_face(f_geo);
-
 
351
										mesh->texcoords.add_face(f_texcoords, idx);
-
 
352
										mesh->mat_idx.push_back(current_material);
-
 
353
									}
-
 
354
							} 
-
 
355
						else if (sscanf(buf, "%d", &v)==1)
-
 
356
							{ // v 
-
 
357
								f_geo[0]=get_vert(v);
-
 
358
								
-
 
359
								fscanf(fp, "%d", &v);
-
 
360
								f_geo[1]=get_vert(v);
-
 
361
								
-
 
362
								fscanf(fp, "%d", &v);
-
 
363
								f_geo[2]=get_vert(v);
-
 
364
								
-
 
365
								mesh->geometry.add_face(f_geo);
-
 
366
								mesh->mat_idx.push_back(current_material);
-
 
367
 
-
 
368
								// Load a general polygon and convert to triangles
-
 
369
								while(fscanf(fp, "%d", &v)==1) 
-
 
370
									{
-
 
371
										f_geo[1]=f_geo[2];
-
 
372
										f_geo[2]=get_vert(v);
-
 
373
										mesh->geometry.add_face(f_geo);
-
 
374
										mesh->mat_idx.push_back(current_material);
-
 
375
									}
-
 
376
							}
-
 
377
						break;
-
 
378
					default:
-
 
379
						fgets(buf, sizeof(buf), fp);
-
 
380
						break;
-
 
381
					}
-
 
382
			}
-
 
383
    fclose(fp);
-
 
384
	}
-
 
385
 
-
 
386
 
-
 
387
	void obj_load(const string& filename, TriMesh& mesh)
-
 
388
	{
239
	{
389
		TriMeshObjLoader loader(&mesh);
240
		TriMeshObjLoader loader(&mesh);
390
		loader.load(filename);
241
		loader.load(filename);
391
	}
242
	}
392
 
243
    
-
 
244
    /// Load materials from an MRL file
393
  void mtl_load(const string& filename, vector<Material>& materials)
245
    void mtl_load(const std::string& filename, std::vector<Material>& materials)
394
  {
246
    {
-
 
247
        TriMesh m;
395
    TriMeshObjLoader loader(0);
248
		TriMeshObjLoader loader(&m);
396
    loader.load_material_library(filename, materials);
249
		loader.read_material_library(filename);
-
 
250
        materials = m.materials;
397
  }
251
    }
-
 
252
    
-
 
253
    
398
}
254
}