/* arcballWindow.h
 *
 * Adds view manipulation to the window class.
 *
 * Derived class must provide a draw() routine.
 */


#ifndef ARCBALL_WINDOW_H
#define ARCBALL_WINDOW_H

#ifdef GL
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <GL/glut.h>
#endif

#include "vector.h"
#include "window.h"


typedef enum { TRANSLATE, ROTATE } ModeType;
typedef enum { LEFT_BUTTON, MIDDLE_BUTTON, RIGHT_BUTTON, NO_BUTTON } ButtonType;
typedef float Matrix[4][4];


class arcballWindow : public window {

  vector mouse;			// last mouse position
  ButtonType button;		// which button is currently down
  bool   mouseMoved;		// set true when mouse moves
  bool   showInfoAtMouse;
  void rotate( int x, int y );
  void tmmult(float a[4], Matrix m, float v[4]);
  void tmmmult(Matrix ans, Matrix a, Matrix b);
  void tm_matinv(Matrix a);
  void rot_mat2(float q[], Matrix m);
  void calc_quat(float q[], int mousex0, int mousey0, int mousex1, int mousey1);
  void calc_p(int mousex, int mousey, float p[]);
  void arcballWindow::tm_copy(Matrix b, Matrix a);
  void displayMousePosition( int x, int y );

protected:

  ModeType mode;		// translate or rotate mode
#ifdef GL
  GLdouble modelMatrix[16];	// info for gluUnproject
  GLdouble projMatrix[16];
  GLint viewport[4];
#endif

public:

  arcballWindow( int x, int y, int width, int height, char *title )
    : window( x, y, width, height, title ) {
      
      mode = ROTATE;
      button = NO_BUTTON;
      setCursor();
      showInfoAtMouse = false;
    }

  virtual void draw() = 0;

  void display();
  void mouseAction( int button, int state, int x, int y );
  void mouseMotion( int x, int y );
  void keyAction( unsigned char key, int x, int y );
  void checkMouse( int x, int y );
  void setCursor();
  void mouseClick( int button, int x, int y );

  void OutputViewParams( char * filename );
  void ReadViewParams( char * filename );
};

#endif

