Subversion Repositories gelsvn

Rev

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