Subversion Repositories gelsvn

Rev

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;
}