Rev 442 | Rev 596 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
// ----------------------------------------
// A simple OBJ viewer.
//
// Controls:
// - left mouse down + mouse motion : rotate
// - Scroll button and +- buttons : zoom
// - right mouse click : centre trackball
// - esc : exits
// - x,y,z buttons : switch trackball up axis
// - w : toggle wireframe on/off
// - t : toggle texture on/off
// - f : switch between vertex and face normals
// ----------------------------------------
#include <iostream>
#include <string>
#include <GL/glew.h>
#include "Util/ArgExtracter.h"
#include "CGLA/Vec2i.h"
#include "CGLA/Vec3f.h"
#include "GLGraphics/gel_glut.h"
#include "GLGraphics/QuatTrackBall.h"
#include "GLGraphics/draw.h"
#include "Geometry/TriMesh.h"
#include "Geometry/load.h"
using namespace std;
using namespace CGLA;
using namespace Geometry;
using namespace GLGraphics;
int win_size_x = 800;
int win_size_y = 800;
bool per_vertex_normals = 1;
bool redo_display_list = 1;
bool do_wireframe = false;
Vec3f line_col = Vec3f(1,0,0);
QuatTrackBall* ball;
int spin_timer = 20;
void spin(int x);
int main_window;
TriMesh mesh;
bool do_textures = true;
bool depth_pick(int x, int y,Vec3f& wp)
{
// Enquire about the viewport dimensions
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
// Get the minimum and maximum depth values.
float minmax_depth[2];
glGetFloatv(GL_DEPTH_RANGE, minmax_depth);
// Read a single pixel at the position of the mouse cursor.
float depth;
glReadPixels(x, viewport[3]-y, 1,1, GL_DEPTH_COMPONENT,
GL_FLOAT, (void*) &depth);
// If the depth corresponds to the far plane, we clicked on the
// background.
if(depth == minmax_depth[1])
return false;
// The lines below copy the viewing transformation from OpenGL
// to local variables. The call to gluLookAt must have exactly
// the same parameters as when the scene is drawn.
glLoadIdentity();
ball->set_gl_modelview();
double mvmat[16];
glGetDoublev(GL_MODELVIEW_MATRIX, mvmat);
// Copy the projection matrix. We assume it is unchanged.
double prjmat[16];
glGetDoublev(GL_PROJECTION_MATRIX, prjmat);
// Now unproject the point from screen to world coordinates.
double ox, oy, oz;
gluUnProject(x,viewport[3]-y,depth,
mvmat,prjmat,viewport,
&ox, &oy, &oz);
wp = Vec3f(ox,oy,oz);
return true;
}
void mouse_motion(int x, int y)
{
ball->roll_ball(Vec2i(x,y));
}
void mouse(int btn, int state, int x, int y)
{
if(state == GLUT_DOWN)
{
if(btn == GLUT_LEFT_BUTTON)
ball->grab_ball(ROTATE_ACTION, Vec2i(x,y));
else if(btn == GLUT_MIDDLE_BUTTON)
ball->grab_ball(ZOOM_ACTION, Vec2i(x, y));
else if(btn == GLUT_RIGHT_BUTTON)
ball->grab_ball(PAN_ACTION, Vec2i(x, y));
}
else if(state == GLUT_UP)
ball->release_ball();
}
void spin(int x)
{
ball->do_spin();
glutTimerFunc(spin_timer, spin, 0);
glutPostRedisplay();
}
void display()
{
static unsigned int l;
if(redo_display_list)
{
cout << "Creating display list" << endl;
l = glGenLists(1);
glNewList(l, GL_COMPILE);
draw(mesh, per_vertex_normals);
glEndList();
redo_display_list = false;
glutTimerFunc(spin_timer, spin, 0);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
ball->set_gl_modelview();
if(do_wireframe)
{
if(GLEW_EXT_geometry_shader4)
draw_triangles_in_wireframe(mesh, per_vertex_normals, Vec3f(1,0,0));
else
draw_wireframe_oldfashioned(mesh, per_vertex_normals, Vec3f(1,0,0));
}
else
glCallList(l);
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case '\033': exit(0); break;
case 'w': do_wireframe = !do_wireframe; break;
case 'f': per_vertex_normals = !per_vertex_normals; redo_display_list = true; break;
break;
}
redo_display_list=true;
}
int main(int argc, char** argv)
{
Util::ArgExtracter ae(argc, argv);
bool redo_normals = ae.extract("-n");
// GLUT INIT
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
glutInitWindowSize(win_size_x, win_size_y);
glutInit(&argc, argv);
main_window = glutCreateWindow("OBJ Viewer");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMotionFunc(mouse_motion);
glutMouseFunc(mouse);
glewInit();
// GL INIT
glClearColor(.8f, 0.9f, 1.0f, 0.f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
glShadeModel(GL_SMOOTH);
// LOAD OBJ
string fn;
if(ae.no_remaining_args())
fn = ae.get_last_arg();
else
fn = "../../data/head.obj";
load(fn, mesh);
load_textures(mesh);
if(!mesh.has_normals() || redo_normals)
{
cout << "Computing normals" << endl;
mesh.compute_normals();
}
// Initialize Trackball
Vec3f c;
float r;
mesh.get_bsphere(c,r);
r *= 1.5;
ball = new QuatTrackBall(c,r,800,800);
// Setup projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(53,1.0f,r/100.0,r*3.0);
glMatrixMode(GL_MODELVIEW);
// Pass control to GLUT
glutMainLoop();
return 0;
}