Rev 97 | Rev 132 | 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
// ----------------------------------------
#if (_MSC_VER >= 1200)
#pragma warning (disable: 4786)
#endif
#include <list>
#include <vector>
#include <CGLA/Vec3f.h>
#include <CGLA/Mat4x4f.h>
#include <GL/glut.h>
#include "Geometry/TriMesh.h"
#include "Graphics/SimpleTrackBall.h"
#include "Geometry/obj_load.h"
using namespace std;
using namespace CGLA;
using namespace Geometry;
using namespace Graphics;
namespace
{
int win_size_x = 800;
int win_size_y = 800;
SimpleTrackBall* ball;
int main_window;
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->gl_view();
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;
}
TriMesh mesh;
void mouse_motion(int x, int y)
{
ball->roll(x,y);
}
void mouse(int button, int state, int x, int y)
{
if(button==GLUT_RIGHT_BUTTON && state==GLUT_DOWN)
{
Vec3f p;
if(depth_pick(x, y, p))
ball->set_center(p);
}
else if(button==3)
ball->farther();
else if(button==4)
ball->closer();
}
void idle()
{
if ( glutGetWindow() != main_window )
glutSetWindow(main_window);
glutPostRedisplay();
}
void display()
{
static bool washere = false;
static unsigned int l;
if(!washere)
{
cout << "Creating display list" << endl;
l = glGenLists(1);
glNewList(l, GL_COMPILE);
mesh.gl_draw();
glEndList();
washere = true;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
ball->gl_view();
glCallList(l);
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case '\033': exit(0); break;
case '+': ball->closer(); break;
case '-': ball->farther(); break;
default:
ball->up_axis(key);
}
}
}
int main(int argc, char** argv)
{
// 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);
glutIdleFunc(idle);
// 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(argc>1)
fn = argv[1];
else
fn = "../../data/head.obj";
cout << "Loading " << fn << endl;
if(fn == "") exit(0);
obj_load(fn, mesh);
if(!mesh.has_normals())
{
cout << "Computing normals" << endl;
mesh.compute_normals();
}
// Initialize textures
mesh.gl_init_textures();
// Initialize Trackball
Vec3f c;
float r;
mesh.get_bsphere(c,r);
r *= 1.5;
ball = new SimpleTrackBall(c,r);
// Setup projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(53,1.0f,r/100,r*3);
glMatrixMode(GL_MODELVIEW);
// Pass control to GLUT
glutMainLoop();
return 0;
}