Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
82 jab 1
// ----------------------------------------
2
// A simple OBJ viewer.
178 bj 3
//
82 jab 4
// Controls:
5
// - left mouse down + mouse motion : rotate
6
// - Scroll button and +- buttons   : zoom
7
// - right mouse click              : centre trackball
8
// - esc                            : exits
178 bj 9
// - x,y,z buttons                  : switch trackball up axis
82 jab 10
// ----------------------------------------
11
 
102 bj 12
#if (_MSC_VER >= 1200)
82 jab 13
#pragma warning (disable: 4786)
102 bj 14
#endif
82 jab 15
 
16
#include <list>
17
#include <vector>
18
 
195 jrf 19
#include <assert.h>
20
#include <stdio.h>
21
#ifdef WIN32
22
#include <windows.h>
23
#include <io.h>
24
#endif
25
#include <string.h>
26
#include <stdlib.h>
27
 
28
#include <iostream>
337 jab 29
 
195 jrf 30
#include <IL/il.h>
31
#include <IL/ilu.h>
32
 
337 jab 33
#include <CGLA/Vec2i.h>
34
#include <CGLA/Vec2f.h>
82 jab 35
#include <CGLA/Vec3f.h>
36
#include <CGLA/Mat4x4f.h>
357 jab 37
#include "glsl_shader.h"
178 bj 38
#include "GLGraphics/gel_glut.h"
299 jrf 39
#include "GLGraphics/QuatTrackBall.h"
178 bj 40
#include "GLGraphics/draw.h"
82 jab 41
#include "Geometry/TriMesh.h"
42
#include "Geometry/obj_load.h"
365 jab 43
#include "HMesh/x3d_load.h"
337 jab 44
#include "ply_load.h"
45
 
82 jab 46
using namespace std;
47
using namespace CGLA;
48
using namespace Geometry;
365 jab 49
using namespace HMesh;
178 bj 50
using namespace GLGraphics;
82 jab 51
 
52
namespace
53
{
337 jab 54
	int win_size_x = 800;
55
	int win_size_y = 800;
363 jab 56
	bool per_vertex_normals = 1;
57
	bool redo_display_list = 1;
337 jab 58
	QuatTrackBall* ball;
59
	int spin_timer = 20;
60
	void spin(int x);
61
	int main_window;
62
	TriMesh mesh;
368 jrf 63
  bool brute_wire = false;
64
  bool do_textures = true;
65
  vector<bool> has_texture;
337 jab 66
 
67
	bool load_image_into_texture(const std::string& name, GLuint& id)
68
	{
69
		unsigned char* image = 0;
70
		unsigned int bpp = 0;
71
		unsigned int size_x = 0;
72
		unsigned int size_y = 0;
73
		unsigned int load_size_x = 0;
74
		unsigned int load_size_y = 0;
75
 
76
 
77
		ILenum Error;
78
		ILuint  ImgId;
79
 
80
		static bool washere = false;
81
		if(!washere)
82
		{
83
			ilInit();
84
			iluInit();
85
			washere=true;
86
		}
87
		ilEnable(IL_CONV_PAL);
88
		ilEnable(IL_ORIGIN_SET);
89
		ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
90
		ilGenImages(1, &ImgId);
91
		ilBindImage(ImgId);
92
		char* name_cstr = const_cast<char*>(name.c_str());
93
		if(!ilLoadImage(name_cstr))
94
		{
95
			cout << "could not load <" << name_cstr  << ">" << endl;
96
			return false;
97
		}
98
 
99
		load_size_x = ilGetInteger(IL_IMAGE_WIDTH);
100
		load_size_y = ilGetInteger(IL_IMAGE_HEIGHT);
101
		bpp = ilGetInteger(IL_IMAGE_BITS_PER_PIXEL);
102
 
103
		if (bpp==24)
104
			ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
105
		else if (bpp==32)
106
			ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
107
		else if (bpp==8)
108
			ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE);
109
		else
110
			assert(0);
111
 
112
		unsigned int i;
113
		for (i=2;i<=4096 ;i*=2)
114
			if (i>=load_size_x)
115
				break;
116
		size_x = i;
117
		for (i=2;i<=4096 ;i*=2)
118
			if (i>=load_size_y)
119
				break;
120
		size_y = i;
121
 
122
		if(size_x != load_size_x || size_y != load_size_y)
123
		{
124
			iluImageParameter(ILU_FILTER, ILU_BILINEAR);
125
			iluScale(size_x, size_y, 1);
126
		}
127
 
128
		const int image_size =size_x*size_y*ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL);
129
		image = new unsigned char[image_size];
130
		memcpy(image, ilGetData(), image_size);
131
		ilDeleteImages(1, &ImgId);
132
 
133
		bool any_errors=false;
134
		while ((Error = ilGetError())) {
135
			cout << __LINE__ << "Error: " << iluErrorString(Error) << endl;
136
			any_errors = true;
137
		}
138
		if(any_errors) return false;
139
 
140
		GLint internalFormat=0;
141
		GLenum format=0;
142
 
143
		glGenTextures(1, &id);
144
		switch (bpp)
145
		{
146
			case 8:
147
				internalFormat =  GL_LUMINANCE;
148
				format = GL_LUMINANCE;
149
				break;
150
			case 24:
151
				internalFormat =  GL_RGB;
152
				format = GL_RGB;
153
				break;
154
			case 32:
155
				internalFormat =  GL_RGBA;
156
				format = GL_RGBA;
157
				break;
158
			default:
159
				return false;
160
		}
161
 
162
		glBindTexture(GL_TEXTURE_2D, id);
163
		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size_x, size_y, 0,
164
					 format, GL_UNSIGNED_BYTE, image);
165
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
166
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
167
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
168
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
169
 
170
		return true;
171
	}
172
 
368 jrf 173
	void load_textures(TriMesh& tm)
337 jab 174
	{
368 jrf 175
    has_texture.resize(tm.materials.size());
337 jab 176
		for(unsigned int i=0;i<tm.materials.size(); ++i)
177
		{
178
			Material& mat = tm.materials[i];
179
			if(mat.tex_name != "")
180
			{
181
				string name = mat.tex_path + mat.tex_name;
182
 
183
				GLuint tex_id;
184
				if(load_image_into_texture(name, tex_id))
368 jrf 185
        {
337 jab 186
					mat.tex_id = tex_id;
368 jrf 187
          has_texture[i] = true;
188
        }
337 jab 189
			}
190
		}
191
	}
368 jrf 192
 
193
  void enable_textures(TriMesh& tm)
194
	{
195
		for(unsigned int i=0;i<has_texture.size(); ++i)
196
			tm.materials[i].has_texture = has_texture[i];
197
	}
198
 
199
  void disable_textures(TriMesh& tm)
200
	{
201
		for(unsigned int i=0;i<has_texture.size(); ++i)
202
			tm.materials[i].has_texture = false;
203
	}
337 jab 204
 
357 jab 205
	void toggle_wire()
206
	{
207
		static bool wire= false;
208
		static string shader_path = "/Users/jab/SrcTree/Appsrc/wireframepaper/";
209
		static GLhandleARB prog_P0;
210
 
368 jrf 211
    wire = !wire;
212
 
357 jab 213
		static bool washere = false;
214
		if(!washere)
215
		{
368 jrf 216
      if(!GLEW_EXT_geometry_shader4)
217
      {
218
        brute_wire = !brute_wire;
219
        redo_display_list = true;
220
        return;
221
      }
222
 
223
      washere = true;
357 jab 224
 
225
			// Create s	haders directly from file
226
			GLuint vs = create_glsl_shader(GL_VERTEX_SHADER, shader_path, "tri.vert");
227
			GLuint gs = create_glsl_shader(GL_GEOMETRY_SHADER_EXT, shader_path, "tri.geom");
228
			GLuint fs = create_glsl_shader(GL_FRAGMENT_SHADER, shader_path, "tri.frag");
229
 
230
			// Create the program
231
			prog_P0 = glCreateProgram();
232
 
233
			// Attach all shaders
234
			if(vs) glAttachShader(prog_P0, vs);
235
			if(gs) glAttachShader(prog_P0, gs);
236
			if(fs) glAttachShader(prog_P0, fs);
237
 
238
			// Specify input and output for the geometry shader. Note that this must be
239
			// done before linking the program.
240
			glProgramParameteriEXT(prog_P0,GL_GEOMETRY_INPUT_TYPE_EXT,GL_TRIANGLES);
241
			glProgramParameteriEXT(prog_P0,GL_GEOMETRY_VERTICES_OUT_EXT,3);
242
			glProgramParameteriEXT(prog_P0,GL_GEOMETRY_OUTPUT_TYPE_EXT,GL_TRIANGLE_STRIP);
243
 
244
			// Link the program object and print out the info log
245
			glLinkProgram(prog_P0);
246
		}
247
		if(wire)
248
		{
249
			glUseProgram(prog_P0);
250
			// Set the value of a uniform
251
			glUniform2f(glGetUniformLocation(prog_P0,"WIN_SCALE"), win_size_x/2.0, win_size_y/2.0);
252
		}
253
		else
254
			glUseProgram(0);		
255
	}
256
 
337 jab 257
	bool depth_pick(int x, int y,Vec3f& wp)
258
	{
259
		// Enquire about the viewport dimensions
260
		GLint viewport[4];
261
		glGetIntegerv(GL_VIEWPORT, viewport);
262
 
263
		// Get the minimum and maximum depth values.
264
		float minmax_depth[2];
265
		glGetFloatv(GL_DEPTH_RANGE, minmax_depth);
266
 
267
		// Read a single pixel at the position of the mouse cursor.
268
		float depth;
269
		glReadPixels(x, viewport[3]-y, 1,1, GL_DEPTH_COMPONENT,
270
					 GL_FLOAT, (void*) &depth);
271
 
272
		// If the depth corresponds to the far plane, we clicked on the
273
		// background.
274
		if(depth == minmax_depth[1])
275
			return false;
276
 
277
		// The lines below copy the viewing transformation from OpenGL
278
		// to local variables. The call to gluLookAt must have exactly
279
		// the same parameters as when the scene is drawn.
280
		glLoadIdentity();
281
		ball->set_gl_modelview();
282
		double mvmat[16];
283
		glGetDoublev(GL_MODELVIEW_MATRIX, mvmat);
284
 
285
		// Copy the projection matrix. We assume it is unchanged.
286
		double prjmat[16];
287
		glGetDoublev(GL_PROJECTION_MATRIX, prjmat);
288
 
289
		// Now unproject the point from screen to world coordinates.
290
		double ox, oy, oz;
291
		gluUnProject(x,viewport[3]-y,depth,
292
					 mvmat,prjmat,viewport,
293
					 &ox, &oy, &oz);
294
 
295
		wp = Vec3f(ox,oy,oz);
296
 
297
		return true;
298
	}
299
 
368 jrf 300
  void mouse_motion(int x, int y)
301
  {
302
      ball->roll_ball(Vec2i(x,y));
303
  }
82 jab 304
 
368 jrf 305
  void mouse(int btn, int state, int x, int y)
306
  {
307
	  if(state == GLUT_DOWN) 
308
	  {
309
		  if(btn == GLUT_LEFT_BUTTON) 
310
			  ball->grab_ball(ROTATE_ACTION, Vec2i(x,y));
311
		  else if(btn == GLUT_MIDDLE_BUTTON) 
312
			  ball->grab_ball(ZOOM_ACTION, Vec2i(x, y));
313
		  else if(btn == GLUT_RIGHT_BUTTON) 
314
			  ball->grab_ball(PAN_ACTION, Vec2i(x, y));
315
	  }
316
	  else if(state == GLUT_UP)
317
		  ball->release_ball();	
318
  }
82 jab 319
 
368 jrf 320
  void spin(int x)
321
  {
322
	  ball->do_spin();
323
	  glutTimerFunc(spin_timer, spin, 0);  
324
	  glutPostRedisplay();
325
  }
178 bj 326
 
368 jrf 327
  void display()
328
  {
329
	  static unsigned int l;
330
      if(redo_display_list)
331
      {
332
          cout << "Creating display list" << endl;
333
          l = glGenLists(1);
334
          glNewList(l, GL_COMPILE);
335
          draw(mesh, per_vertex_normals, brute_wire);
336
          glEndList();
337
          redo_display_list = false;
338
		  glutTimerFunc(spin_timer, spin, 0);	
339
	  }
340
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
341
      glLoadIdentity();
342
      ball->set_gl_modelview();
343
      glCallList(l);
344
      glutSwapBuffers();
345
  }
178 bj 346
 
368 jrf 347
  void keyboard(unsigned char key, int x, int y)
348
  {
349
      switch(key)
350
      {
351
		  case '\033': exit(0);
352
		  case 'w': toggle_wire(); break;
353
		  case 'f': per_vertex_normals = !per_vertex_normals; redo_display_list = true; break;
354
      case 't': 
355
        do_textures = !do_textures; 
356
        if(do_textures) 
357
          enable_textures(mesh); 
358
        else 
359
          disable_textures(mesh); 
360
        redo_display_list = true; 
361
        break;
362
      }
363
  }
299 jrf 364
}
337 jab 365
 
82 jab 366
int main(int argc, char** argv)
178 bj 367
{
368
    // GLUT INIT
369
    glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
370
    glutInitWindowSize(win_size_x, win_size_y);
371
    glutInit(&argc, argv);
372
    main_window = glutCreateWindow("OBJ Viewer");
373
    glutDisplayFunc(display);
374
    glutKeyboardFunc(keyboard);
375
    glutMotionFunc(mouse_motion);
376
    glutMouseFunc(mouse);
299 jrf 377
    //glutIdleFunc(idle);
337 jab 378
 
368 jrf 379
	  glewInit();
357 jab 380
 
178 bj 381
    // GL INIT
382
    glClearColor(.8f, 0.9f, 1.0f, 0.f);
383
    glEnable(GL_DEPTH_TEST);
384
    glEnable(GL_LIGHTING);
385
    glEnable(GL_LIGHT0);
386
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
387
    glShadeModel(GL_SMOOTH);
337 jab 388
 
178 bj 389
    // LOAD OBJ
390
    string fn;
391
    if(argc>1)
392
        fn = argv[1];
393
    else
394
        fn = "../../data/head.obj";
337 jab 395
 
396
	if(fn.substr(fn.length()-4,fn.length())==".obj")
397
	{
398
		obj_load(fn, mesh);
399
	}
400
	else if(fn.substr(fn.length()-4,fn.length())==".ply")
401
	{
402
		ply_load(fn, mesh);
403
	}	
365 jab 404
/*	else if(fn.substr(fn.length()-4,fn.length())==".x3d")
405
	{
406
		TriMesh mesh;
407
		Manifold m;
408
		x3d_load(fn, m);
409
		for(FaceIter f = m.faces_begin(); f!= m.faces_end(); ++f)
410
			{
411
				mesh.
412
			}
413
	}	
414
	*/
337 jab 415
	else
416
	{
417
		cout << "Either the format was unrecognized or the file did not have the appropriate extension" << endl;
418
		exit(0);
419
	}		
368 jrf 420
    load_textures(mesh);	
421
    if(!do_textures)
422
      disable_textures(mesh);
423
    if(!mesh.has_normals() || (argc > 2 && !strcmp(argv[2], "-n")))
178 bj 424
    {
425
        cout << "Computing normals" << endl;
426
        mesh.compute_normals();
427
    }
341 jab 428
 
178 bj 429
    // Initialize Trackball
430
    Vec3f c;
431
    float r;
432
    mesh.get_bsphere(c,r);
433
    r *= 1.5;
299 jrf 434
    ball = new QuatTrackBall(c,r,800,800);
337 jab 435
 
178 bj 436
    // Setup projection
437
    glMatrixMode(GL_PROJECTION);
438
    glLoadIdentity();
299 jrf 439
    gluPerspective(53,1.0f,r/100.0,r*3.0);
178 bj 440
    glMatrixMode(GL_MODELVIEW);
337 jab 441
 
178 bj 442
    // Pass control to GLUT
443
    glutMainLoop();
337 jab 444
 
178 bj 445
    return 0;
82 jab 446
}