Subversion Repositories gelsvn

Rev

Rev 638 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/* ----------------------------------------------------------------------- *
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
 * Copyright (C) the authors and DTU Informatics
 * For license and list of authors, see ../../doc/intro.pdf
 * ----------------------------------------------------------------------- */

#include "gel_glu.h"
#include "GLViewController.h"
#include "../CGLA/Mat3x3f.h"

using namespace std;
using namespace CGLA;

namespace GLGraphics
{
    
    void GLViewController::reset_projection()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(FOV_DEG, aspect, znear, zfar);
        glMatrixMode(GL_MODELVIEW);
    }
    
    GLViewController::GLViewController()
    : FOV_DEG(53),
    WINX(500), WINY(500),
    aspect(500/float(500)),
    button_down(false),
    spin(false),
    ball(CGLA::Vec3f(0.0,0.0,0.0), 0.0, 500, 500)
    {
        znear = 0.01f*0.0;
        zfar  = 3*0.0;
        //    reset_projection();
    }
    
    
    GLViewController::GLViewController(int _WINX, int _WINY, const CGLA::Vec3f& centre, float rad)
    : FOV_DEG(53),
    WINX(_WINX), WINY(_WINY),
    aspect(WINX/float(WINY)),
    button_down(false),
    spin(false),
    ball(centre, rad, WINX, WINY)
    {
        znear = 0.01f*rad;
        zfar  = 3*rad;
        // reset_projection();
    }
    
    void GLViewController::grab_ball(TrackBallAction action, const CGLA::Vec2i& pos)
    {
        ball.grab_ball(action,pos);
        if(action==ZOOM_ACTION)
            set_near_and_far();
        
        spin = false;
        button_down = true;
        last_action = action;
    }
    
    void GLViewController::roll_ball(const CGLA::Vec2i& pos)
    {
        static Vec2i old_pos = pos;
        Vec2f dir = Vec2f(pos-old_pos);
        float len = dir.length();
        if (len < TINY)
            return;
        
        ball.roll_ball(pos);
        if(last_action==ZOOM_ACTION)
            set_near_and_far();
        
        spin = len>=1.1f;
        old_pos = pos;
    }
    
    
    void GLViewController::release_ball()
    {
        ball.release_ball();
        if(last_action==ZOOM_ACTION)
            set_near_and_far();
    }
    
    bool GLViewController::try_spin()
    {
        if(spin && !ball.is_grabbed())
        {
            ball.do_spin();
            return true;
        }
        return false;
    }
    
    void GLViewController::set_gl_modelview()
    {
        reset_projection();
        ball.set_gl_modelview();
    }
    
    
    void GLViewController::reshape(int W, int H)
    {
        WINX = W;
        WINY = H;
        aspect = WINX/static_cast<float>(WINY);
        glViewport(0,0,WINX,WINY);
        reset_projection();
        ball.set_screen_window(WINX, WINY);
    }
    
    void GLViewController::set_near_and_far()
    {
        float rad = ball.get_eye_dist();
        znear = 0.01f*rad;
        zfar = 3*rad;
        reset_projection();
    }
    
    void GLViewController::set_view_param(const Vec3f& e, const Vec3f& c, const Vec3f& u)
    {
        // native viewing direction is the negative z-axis
        // while right is the x-axis and up is the y-axis
        Vec3f view = c - e;
        float eye_dist = length(view);
        view /= eye_dist;
        Vec3f right = normalize(cross(view, u));
        Vec3f up = cross(right, view);
        Mat3x3f rot(right, up, -view);
        rot = transpose(rot); // since matrix is row-major
        
        // convert the change-of-basis matrix to a quaternion
        Quatf qrot;
        qrot.make_rot(rot);
        set_rotation(qrot);
        set_centre(c);
        set_eye_dist(eye_dist);
    }
    
    bool GLViewController::load(std::ifstream& ifs)
    {
        if(ifs)
        {
            ifs.read(reinterpret_cast<char*>(this), sizeof(GLViewController));
            reset_projection();
            ball.set_screen_window(WINX, WINY);
            return true;
        }
        return false;
    }
    
    bool GLViewController::save(std::ofstream& ofs) const
    {
        if(ofs)
        {
            ofs.write(reinterpret_cast<const char*>(this), sizeof(GLViewController));
            return true;
        }
        return false;
    }
}