Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
688 khor 1
// ----------------------------------------
2
// A simple OBJ viewer.
3
//
4
// Controls:
5
// - left mouse down + mouse motion : rotate
6
// - Scroll button and +- buttons   : zoom
7
// - right mouse click              : centre trackball
8
// - esc                            : exits
9
// - x,y,z buttons                  : switch trackball up axis
10
// - w                              : toggle wireframe on/off
11
// - t                              : toggle texture on/off
12
// - f                              : switch between vertex and face normals
13
// ----------------------------------------
14
 
15
#if (_MSC_VER >= 1200)
16
#pragma warning (disable: 4786)
17
#endif
18
 
19
#include <list>
20
#include <vector>
21
 
22
#include <assert.h>
23
#include <stdio.h>
24
#ifdef WIN32
25
#include <windows.h>
26
#include <io.h>
27
#endif
28
#include <string.h>
29
#include <stdlib.h>
30
 
31
#include <fstream>
32
#include <iostream>
33
#include <vector>
34
 
35
#include <GEL/Util/ArgExtracter.h>
36
#include <GEL/CGLA/Vec2i.h>
37
#include <GEL/CGLA/Vec2f.h>
38
#include <GEL/CGLA/Vec3f.h>
39
#include <GEL/CGLA/Mat4x4f.h>
40
#include <GEL/GLGraphics/glsl_shader.h>
41
#include <GEL/GLGraphics/QuatTrackBall.h>
42
#include <GEL/GLGraphics/draw.h>
43
#include <GEL/GLGraphics/SOIL.h>
44
#include <GEL/Geometry/TriMesh.h>
45
#include <GEL/Geometry/load.h>
46
#include <GEL/Geometry/GridAlgorithm.h>
47
#include <GEL/Geometry/HGrid.h>
48
 
49
#ifdef __APPLE__
50
#include <GLUT/GLUT.h>
51
#else
52
#include <GL/glut.h>
53
#endif
54
 
55
using namespace std;
56
using namespace CGLA;
57
using namespace Geometry;
58
using namespace HMesh;
59
using namespace GLGraphics;
60
 
61
int win_size_x = 800;
62
int win_size_y = 800;
63
bool per_vertex_normals = 1;
64
bool redo_display_list = 1;
65
bool do_wireframe = false;
66
Vec3f line_col = Vec3f(1,0,0);
67
QuatTrackBall* ball;
68
int spin_timer = 20;
69
void spin(int x);
70
int main_window;
71
TriMesh mesh;
72
bool do_textures = true;
73
 
74
 
75
bool depth_pick(int x, int y,Vec3f& wp)
76
{
77
	// Enquire about the viewport dimensions
78
	GLint viewport[4];
79
	glGetIntegerv(GL_VIEWPORT, viewport);
80
 
81
	// Get the minimum and maximum depth values.
82
	float minmax_depth[2];
83
	glGetFloatv(GL_DEPTH_RANGE, minmax_depth);
84
 
85
	// Read a single pixel at the position of the mouse cursor.
86
	float depth;
87
	glReadPixels(x, viewport[3]-y, 1,1, GL_DEPTH_COMPONENT,
88
				 GL_FLOAT, (void*) &depth);
89
 
90
	// If the depth corresponds to the far plane, we clicked on the
91
	// background.
92
	if(depth == minmax_depth[1])
93
		return false;
94
 
95
	// The lines below copy the viewing transformation from OpenGL
96
	// to local variables. The call to gluLookAt must have exactly
97
	// the same parameters as when the scene is drawn.
98
	glLoadIdentity();
99
	ball->set_gl_modelview();
100
	double mvmat[16];
101
	glGetDoublev(GL_MODELVIEW_MATRIX, mvmat);
102
 
103
	// Copy the projection matrix. We assume it is unchanged.
104
	double prjmat[16];
105
	glGetDoublev(GL_PROJECTION_MATRIX, prjmat);
106
 
107
	// Now unproject the point from screen to world coordinates.
108
	double ox, oy, oz;
109
	gluUnProject(x,viewport[3]-y,depth,
110
				 mvmat,prjmat,viewport,
111
				 &ox, &oy, &oz);
112
 
113
	wp = Vec3f(ox,oy,oz);
114
 
115
	return true;
116
}
117
 
118
 
119
void mouse_motion(int x, int y)
120
{
121
    ball->roll_ball(Vec2i(x,win_size_y-y));
122
}
123
 
124
void mouse(int btn, int state, int x, int y)
125
{
126
    y = win_size_y-y;
127
	if(state == GLUT_DOWN) 
128
	{
129
		if(btn == GLUT_LEFT_BUTTON) 
130
			ball->grab_ball(ROTATE_ACTION, Vec2i(x,y));
131
		else if(btn == GLUT_MIDDLE_BUTTON) 
132
			ball->grab_ball(ZOOM_ACTION, Vec2i(x, y));
133
		else if(btn == GLUT_RIGHT_BUTTON) 
134
			ball->grab_ball(PAN_ACTION, Vec2i(x, y));
135
	}
136
	else if(state == GLUT_UP)
137
		ball->release_ball();	
138
}
139
 
140
void spin(int x)
141
{
142
	ball->do_spin();
143
	glutTimerFunc(spin_timer, spin, 0);  
144
	glutPostRedisplay();
145
}
146
 
147
void setupshader()
148
{
149
	static GLuint vs,fs,prog;
150
	static bool was_here = false;
151
	if(!was_here)
152
	{
153
		was_here = true;
154
		const string vss = 
155
		"varying vec3 n;\n"
156
		"varying vec3 v;\n"
157
		"varying vec3 v_obj;\n"
158
		"\n"
159
		"void main(void)\n"
160
		"{\n"
161
		"	gl_Position = ftransform();\n"
162
		"   v_obj = gl_Vertex.xyz;\n"
163
		"	v = vec3(gl_ModelViewMatrix * gl_Vertex);\n"
164
		"	n = normalize(gl_NormalMatrix * gl_Normal);\n"
165
		"}\n"
166
		"\n";
167
 
168
		const string fss =
169
		"varying vec3 n;\n"
170
		"varying vec3 v;\n"
171
		"varying vec3 v_obj;\n"
172
		"\n"
173
		"vec4 glazed_shader(vec4 mat_col,  vec4 light_col, vec3 light_dir)\n"
174
		"{\n"
175
		"	vec3 e = normalize(-v);\n"
176
		"	vec3 r = normalize(2.0*dot(e, n)*n - e);\n"
177
		"	float d = max(0.05,dot(light_dir, n));\n"
178
		"	vec4 diff = mat_col * light_col *d; 	\n"
179
		"	vec4 refl = smoothstep(0.7,0.75,dot(r,light_dir)) * light_col;\n"
180
		"	return 0.1*refl + 2.25*diff;\n"
181
		"}\n"
182
		"\n"
183
		"void main(void)\n"
184
		"{\n"
185
		"	vec4 mat_col = vec4(0.7,0.6,1.0,1.0);\n"
186
		"	\n"
187
		"	vec3 light0_dir = vec3(0.0,1.0,0.0);\n"
188
		"	vec4 light0_col = vec4(0.9,0.95,0.95,1.0);\n"
189
		"	\n"
190
		"	vec3 light1_dir = vec3(0.0,0.0,1.0);\n"
191
		"	vec4 light1_col = vec4(.8,.8,.6,1.0);\n"
192
		"	\n"
193
		"	gl_FragColor = \n"
194
		"	0.5*glazed_shader(mat_col, light0_col, light0_dir)+\n"
195
		"	0.5*glazed_shader(mat_col, light1_col, light1_dir);\n"
196
		"	\n"
197
		"	gl_FragColor.a = 1.0;\n"
198
		"}\n";
199
 
200
		vs = create_glsl_shader(GL_VERTEX_SHADER, vss);
201
		print_glsl_program_log(vs);
202
 
203
		fs = create_glsl_shader(GL_FRAGMENT_SHADER, fss);
204
		print_glsl_program_log(fs);
205
 
206
		prog = glCreateProgram();
207
 
208
		if(vs) glAttachShader(prog, vs);
209
		if(fs) glAttachShader(prog, fs);
210
 
211
		glLinkProgram(prog);
212
		print_glsl_program_log(prog);
213
	}
214
	glUseProgram(prog);
215
 
216
}
217
 
218
void display()
219
{
220
	static unsigned int l;
221
    if(redo_display_list)
222
    {
223
        cout << "Creating display list" << endl;
224
        l = glGenLists(1);
225
        glNewList(l, GL_COMPILE);
226
        draw(mesh, per_vertex_normals);
227
        glEndList();
228
        redo_display_list = false;
229
		glutTimerFunc(spin_timer, spin, 0);	
230
	}
231
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
232
    glLoadIdentity();
233
    ball->set_gl_modelview();
234
	if(do_wireframe)
235
	{
236
		if(GLEW_EXT_geometry_shader4)
237
			draw_triangles_in_wireframe(mesh, per_vertex_normals, Vec3f(1,0,0));
238
		else
239
			draw_wireframe_oldfashioned(mesh, per_vertex_normals, Vec3f(1,0,0));
240
	}
241
	else if(!do_textures)
242
	{
243
		setupshader();	
244
		glCallList(l);
245
	}
246
	else
247
		glCallList(l);
248
 
249
    glutSwapBuffers();
250
}
251
 
252
void keyboard(unsigned char key, int x, int y)
253
{
254
    switch(key)
255
    {
256
		case '\033': exit(0); break;
257
		case 'w': do_wireframe = !do_wireframe; break;
258
		case 'f': per_vertex_normals = !per_vertex_normals; redo_display_list = true; break;
259
		case 's': 
260
		{
261
			ofstream f("ball.out", ios::binary);
262
			if(f) f.write(reinterpret_cast<const char*>(ball),sizeof(QuatTrackBall));
263
		}
264
		break;
265
		case 'l':
266
		{
267
			ifstream f("ball.out", ios::binary);
268
			if(f) f.read(reinterpret_cast<char*>(ball),sizeof(QuatTrackBall));
269
		}
270
			break;
271
		case 't': do_textures = !do_textures;
272
			break;
273
    }
274
	redo_display_list=true;
275
}
276
 
277
int main(int argc, char** argv)
278
{
279
	Util::ArgExtracter ae(argc, argv);
280
 
281
	bool redo_normals = ae.extract("-n");
282
 
283
    // GLUT INIT
284
    glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
285
    glutInitWindowSize(win_size_x, win_size_y);
286
    glutInit(&argc, argv);
287
    main_window = glutCreateWindow("OBJ Viewer");
288
    glutDisplayFunc(display);
289
    glutKeyboardFunc(keyboard);
290
    glutMotionFunc(mouse_motion);
291
    glutMouseFunc(mouse);
292
    //glutIdleFunc(idle);
293
 
294
	glewInit();
295
 
296
    // GL INIT
297
    glClearColor(.8f, 0.9f, 1.0f, 0.f);
298
    glEnable(GL_DEPTH_TEST);
299
    glEnable(GL_LIGHTING);
300
    glEnable(GL_LIGHT0);
301
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
302
    glShadeModel(GL_SMOOTH);
303
 
304
    // LOAD OBJ
305
    string fn;
306
    int arg_no = ae.no_remaining_args();
307
    if(arg_no>1)
308
        fn = ae.get_last_arg();
309
    else
310
        fn = "../../data/head.obj";
311
 
312
	load(fn, mesh);
313
	load_textures(mesh);
314
 
315
	if(!mesh.has_normals() || redo_normals)
316
	{
317
		cout << "Computing normals" << endl;
318
		mesh.compute_normals();
319
	}
320
 
321
	// Initialize Trackball
322
	Vec3f c;
323
	float r;
324
	mesh.get_bsphere(c,r);
325
	r *= 1.5;
326
	ball = new QuatTrackBall(c,r,800,800);
327
 
328
	// Setup projection
329
	glMatrixMode(GL_PROJECTION);
330
	glLoadIdentity();
331
	gluPerspective(53,1.0f,r/100.0,r*3.0);
332
	glMatrixMode(GL_MODELVIEW);
333
 
334
	// Pass control to GLUT
335
	glutMainLoop();
336
 
337
	return 0;
338
}