Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
79 jab 1
// bdl, jab, feb 2005
2
// Inspired and partly lifted from Nate Robins' Obj loader
3
 
4
#include "TriMesh.h"
5
#include <CGLA/Vec3f.h>
6
#include <stdio.h>
7
#include <iostream>
8
 
9
using namespace std;
10
using namespace CGLA;
11
 
12
namespace Geometry {
13
 
14
	namespace
15
	{
16
		string get_path(const string& _filename)
17
		{
18
			// Make sure we only have slashes and not backslashes
19
			string filename = _filename;
20
			replace(filename.begin(),filename.end(),'\\','/');
21
 
22
			// Find the last occurrence of slash.
23
			// Everything before is path.
24
			unsigned int n = filename.rfind("/");
25
			if(n > filename.size())
26
				return "./";
27
			string pathname = "";
28
			pathname.assign(filename,0,n);
29
			pathname.append("/");
30
			return pathname;
31
		}
32
	}
33
	class TriMeshObjLoader
34
	{
35
		TriMesh *mesh;
36
		std::string pathname;
37
 
38
		int get_vert(int i) {
39
			assert(i!=0);
40
			if (i<0) {
41
				return mesh->geometry.no_vertices()+i;
42
			} else
43
				return i-1;
44
		}
45
 
46
		int get_normal(int i) {
47
			if (i<0) {
48
				return mesh->normals.no_vertices()+i;
49
			} else
50
				return i-1;
51
		}
52
 
53
		int get_texcoord(int i) {
54
			if (i<0) {
55
				return mesh->texcoords.no_vertices()+i;
56
			} else
57
				return i-1;
58
		}
59
 
510 jrf 60
		void read_material_library(const string& filename, vector<Material>& materials);
61
 
79 jab 62
	public:
63
 
64
		TriMeshObjLoader(TriMesh *_mesh): mesh(_mesh) {}
65
 
66
		void load(const std::string& filename);
510 jrf 67
    void load_material_library(const string& filename, vector<Material>& materials)
68
    {
69
      pathname = get_path(filename);
70
      read_material_library(filename, materials);
71
    }
79 jab 72
	};
73
 
510 jrf 74
	void TriMeshObjLoader::read_material_library(const string& filename, vector<Material>& materials)
79 jab 75
	{
76
		string fn = pathname + filename;
77
		FILE* file = fopen(fn.data(), "r");
78
		if (!file) 
79
			{
80
				cerr << "Could not open " << filename << endl;
81
				return;
82
			}
83
 
84
		char  buf[128];
85
		unsigned int nummaterials=1;
86
 
87
		// count the number of materials in the file 
88
		while(fscanf(file, "%s", buf) != EOF) 
89
			{
90
				switch(buf[0]) 
91
					{
92
					case '#':				/* comment */
93
						/* eat up rest of line */
94
						fgets(buf, sizeof(buf), file);
95
						break;
96
					case 'n':				/* newmtl */
97
						fgets(buf, sizeof(buf), file);
98
						nummaterials++;
99
						sscanf(buf, "%s %s", buf, buf);
100
						break;
101
					default:
102
						/* eat up rest of line */
103
						fgets(buf, sizeof(buf), file);
104
						break;
105
					}
106
			}
107
		rewind(file);
108
 
109
		/* allocate memory for the materials */
510 jrf 110
		materials.resize(nummaterials);
79 jab 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 */
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++;
510 jrf 124
				materials[nummaterials].name = buf;
79 jab 125
				break;
126
			case 'N':
421 jrf 127
        switch(buf[1])
128
          {
129
          case 's':
510 jrf 130
				    fscanf(file, "%f", &materials[nummaterials].shininess);
421 jrf 131
				    /* wavefront shininess is from [0, 1000], so scale for OpenGL */
510 jrf 132
				    materials[nummaterials].shininess /= 1000.0;
133
				    materials[nummaterials].shininess *= 128.0;
421 jrf 134
            break;
135
          case 'i':
510 jrf 136
				    fscanf(file, "%f", &materials[nummaterials].ior);
421 jrf 137
            break;
138
					default:
139
						/* eat up rest of line */
140
						fgets(buf, sizeof(buf), file);
141
						break;
142
          }
79 jab 143
				break;
144
			case 'K': 
145
				switch(buf[1]) 
146
					{
147
					case 'd':
148
						fscanf(file, "%f %f %f",
510 jrf 149
									 &materials[nummaterials].diffuse[0],
150
									 &materials[nummaterials].diffuse[1],
151
									 &materials[nummaterials].diffuse[2]);
79 jab 152
						break;
153
					case 's':
154
						fscanf(file, "%f %f %f",
510 jrf 155
									 &materials[nummaterials].specular[0],
156
									 &materials[nummaterials].specular[1],
157
									 &materials[nummaterials].specular[2]);
79 jab 158
						break;
159
					case 'a':
160
						fscanf(file, "%f %f %f",
510 jrf 161
									 &materials[nummaterials].ambient[0],
162
									 &materials[nummaterials].ambient[1],
163
									 &materials[nummaterials].ambient[2]);
79 jab 164
						break;
165
					default:
166
						/* eat up rest of line */
167
						fgets(buf, sizeof(buf), file);
168
						break;
169
					}
170
				break;
421 jrf 171
      case 'T':
172
				fscanf(file, "%f %f %f",
510 jrf 173
               &materials[nummaterials].transmission[0],
174
               &materials[nummaterials].transmission[1],
175
               &materials[nummaterials].transmission[2]);
421 jrf 176
        break;
177
      case 'i':
510 jrf 178
				fscanf(file, "%d", &materials[nummaterials].illum);
421 jrf 179
        break;
79 jab 180
			case 'm': // Map ... all maps are treated equally.
181
				{
182
					fscanf(file,"%s",buf);
510 jrf 183
					materials[nummaterials].tex_path = pathname;
184
					materials[nummaterials].tex_name = string(buf);
185
          materials[nummaterials].has_texture = true;
79 jab 186
				}
187
				break;
188
			default:
189
				/* eat up rest of line */
190
				fgets(buf, sizeof(buf), file);
191
				break;
192
			}
193
		}
436 jrf 194
    fclose(file);
79 jab 195
	}
196
 
197
 
198
	void TriMeshObjLoader::load(const std::string& filename) 
199
	{
200
		pathname = get_path(filename);
201
		FILE *fp = fopen(filename.data(), "r");
202
		if (fp==0) {
203
			cerr << "File " << filename << " does not exist" << endl;
364 jrf 204
      exit(0);
79 jab 205
		}
206
		mesh->materials.resize(1);
207
 
208
		char buf[256];
209
		Vec3f v_geo;
210
		Vec3f v_normals;
211
		Vec3f v_texcoords;
212
 
213
		Vec3i f_geo;
214
		Vec3i f_normals;
215
		Vec3i f_texcoords;
216
		int current_material=0;
217
		int v,n,t;
218
		while(fscanf(fp, "%s", buf) != EOF) 
219
			{
220
				switch(buf[0]) 
221
					{
222
					case '#': // A comment
223
						fgets(buf, sizeof(buf), fp);
224
						break;
225
					case 'm':
226
						fgets(buf, sizeof(buf), fp);
227
						sscanf(buf, "%s %s", buf, buf);
510 jrf 228
						read_material_library(buf, mesh->materials);
79 jab 229
						break;
230
					case 'u':
231
						fgets(buf, sizeof(buf), fp);
232
						sscanf(buf, "%s %s", buf, buf);
233
						current_material = mesh->find_material(buf);
234
						break;
235
					case 'v': // v, vn, vt
236
						switch(buf[1]) 
237
							{
238
							case '\0': // vertex
239
								fscanf(fp, "%f %f %f", &v_geo[0], &v_geo[1], &v_geo[2]);
240
								mesh->geometry.add_vertex(v_geo);
241
								break;
242
							case 'n': // normal
243
								fscanf(fp, "%f %f %f", &v_normals[0], &v_normals[1], &v_normals[2]);
244
								mesh->normals.add_vertex(v_normals);
245
								break;
246
							case 't': // texcoord
247
								fscanf(fp, "%f %f", &v_texcoords[0], &v_texcoords[1]);
248
								v_texcoords[2]=1;
249
								mesh->texcoords.add_vertex(v_texcoords);
250
								break;
251
							}
252
						break;
253
					case 'f':
254
						v = n = t = 0;
255
						fscanf(fp, "%s", buf);
256
						// can be one of %d, %d//%d, %d/%d, %d/%d/%d 
257
						if(sscanf(buf, "%d/%d/%d", &v, &t, &n) == 3)
258
							{ // v/t/n
259
 
260
								f_geo[0]=get_vert(v); 
261
								f_texcoords[0]=get_texcoord(t);
262
								f_normals[0]=get_normal(n);
263
 
264
								fscanf(fp, "%d/%d/%d", &v, &t, &n); 
265
								f_geo[1]=get_vert(v); 
266
								f_texcoords[1]=get_texcoord(t);
267
								f_normals[1]=get_normal(n);
268
 
269
								fscanf(fp, "%d/%d/%d", &v, &t, &n); 
270
								f_geo[2]=get_vert(v); 
271
								f_texcoords[2]=get_texcoord(t);
272
								f_normals[2]=get_normal(n);
273
 
274
								int idx = mesh->geometry.add_face(f_geo);
275
								mesh->normals.add_face(f_normals, idx);
276
								mesh->texcoords.add_face(f_texcoords, idx);
277
								mesh->mat_idx.push_back(current_material);
278
 
279
								// Load a general polygon and convert to triangles
280
								while(fscanf(fp, "%d/%d/%d", &v, &t, &n)==3) 
281
									{
282
										f_geo[1]=f_geo[2];
283
										f_normals[1]=f_normals[2];
284
										f_texcoords[1]=f_texcoords[2];
285
 
286
										f_geo[2]=get_vert(v);
287
										f_normals[2]=get_normal(n);
288
										f_texcoords[2]=get_texcoord(t);
289
 
290
										int idx = mesh->geometry.add_face(f_geo);
291
										mesh->normals.add_face(f_normals, idx);
292
										mesh->texcoords.add_face(f_texcoords, idx);
293
										mesh->mat_idx.push_back(current_material);
294
									}
295
							} 
296
						else if (sscanf(buf, "%d//%d", &v, &n)==2)
297
							{// v//n 
298
								f_geo[0]=get_vert(v);
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
			}
436 jrf 383
    fclose(fp);
79 jab 384
	}
385
 
386
 
510 jrf 387
	void obj_load(const string& filename, TriMesh& mesh)
79 jab 388
	{
389
		TriMeshObjLoader loader(&mesh);
390
		loader.load(filename);
391
	}
392
 
510 jrf 393
  void mtl_load(const string& filename, vector<Material>& materials)
394
  {
395
    TriMeshObjLoader loader(0);
396
    loader.load_material_library(filename, materials);
397
  }
79 jab 398
}