Subversion Repositories gelsvn

Rev

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