208 lines
5.3 KiB
C++
208 lines
5.3 KiB
C++
#include "Input.h"
|
|
#include "utils.h"
|
|
#include "Renderer.h"
|
|
|
|
#include <GL/glut.h>
|
|
#include <iostream>
|
|
|
|
Input Input::m_instance;
|
|
|
|
GLvoid Input::keyboard_event(GLubyte key, GLint x, GLint y)
|
|
{
|
|
switch ( key ) {
|
|
case 'w':
|
|
this->menu(ZOOM_IN_EVENT);
|
|
break;
|
|
case 's':
|
|
this->menu(ZOOM_OUT_EVENT);
|
|
break;
|
|
case 'a':
|
|
this->menu(ANIMATE_EVENT);
|
|
break;
|
|
case 'l':
|
|
this->menu(LINES_EVENT);
|
|
break;
|
|
case 'f':
|
|
this->menu(FULL_EVENT);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
GLvoid Input::menu( int value )
|
|
{
|
|
switch ( value ) {
|
|
case ZOOM_IN_EVENT:
|
|
Renderer::getInstance()->divViewDist(1.2);
|
|
break;
|
|
case ZOOM_OUT_EVENT:
|
|
Renderer::getInstance()->multViewDist(1.2);
|
|
break;
|
|
case LINES_EVENT:
|
|
glDisable(GL_CULL_FACE);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
Renderer::getInstance()->render();
|
|
break;
|
|
case FULL_EVENT:
|
|
glEnable(GL_CULL_FACE);
|
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
|
Renderer::getInstance()->render();
|
|
break;
|
|
case ANIMATE_EVENT:
|
|
Renderer::getInstance()->animate =
|
|
Renderer::getInstance()->animate ? false : true;
|
|
Renderer::getInstance()->render();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
GLvoid Input::passive_motion(GLint mx, GLint my)
|
|
{
|
|
}
|
|
|
|
GLvoid Input::button_motion(GLint mx, GLint my)
|
|
{
|
|
/* First calculate P */
|
|
static Point v;
|
|
Point p, w, a;
|
|
|
|
//Give us the scaled p on the sphere
|
|
scalePoint(p,mx,my);
|
|
|
|
//get the unit vector of p
|
|
GLfloat length = p.magnitude();
|
|
if (length==0) {
|
|
return;
|
|
} else {
|
|
w.x = p.x / length;
|
|
w.y = p.y / length;
|
|
w.z = p.z / length;
|
|
}
|
|
|
|
//This is the first time the movement has been made
|
|
if (oldPoint.z == -1) {
|
|
scalePoint(oldPoint,(int)oldPoint.x,(int)oldPoint.y);
|
|
|
|
length = oldPoint.magnitude();
|
|
if (length==0) {
|
|
return;
|
|
} else {
|
|
v.x = oldPoint.x / length;
|
|
v.y = oldPoint.y / length;
|
|
v.z = oldPoint.z / length;
|
|
}
|
|
}
|
|
|
|
cross(a,oldPoint,p);
|
|
length = a.magnitude();
|
|
if (length==0) {
|
|
return;
|
|
} else {
|
|
a.x /= length;
|
|
a.y /= length;
|
|
a.z /= length;
|
|
}
|
|
|
|
GLfloat angle = dot(v,w);
|
|
if (angle > 1) {
|
|
angle = 1;
|
|
} else if (angle < -1) {
|
|
angle = -1;
|
|
}
|
|
|
|
angle = acos(angle);
|
|
|
|
/* Perform the rotation calculation */
|
|
GLfloat newMatrix[16];
|
|
|
|
calcAngle(newMatrix,angle,a);
|
|
|
|
/* Make OpenGL do our work */
|
|
glPushMatrix();
|
|
glLoadMatrixf(newMatrix);
|
|
glMultMatrixf(Renderer::getInstance()->currModelTransform);
|
|
glGetFloatv(GL_MODELVIEW_MATRIX,Renderer::getInstance()->currModelTransform);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
|
|
oldPoint = p;
|
|
v = w;
|
|
|
|
glutPostRedisplay();
|
|
|
|
return;
|
|
}
|
|
|
|
GLvoid Input::mouse_button(GLint btn, GLint state, GLint mx, GLint my)
|
|
{
|
|
|
|
switch( btn ) {
|
|
case GLUT_LEFT_BUTTON:
|
|
switch( state ) {
|
|
case GLUT_DOWN:
|
|
oldPoint.x = mx;
|
|
oldPoint.y = my;
|
|
oldPoint.z = -1;
|
|
break;
|
|
case GLUT_UP:
|
|
break;
|
|
}
|
|
break;
|
|
case GLUT_MIDDLE_BUTTON:
|
|
switch( state ) {
|
|
case GLUT_DOWN:
|
|
break;
|
|
case GLUT_UP:
|
|
break;
|
|
}
|
|
break;
|
|
case GLUT_RIGHT_BUTTON:
|
|
switch( state ) {
|
|
case GLUT_DOWN:
|
|
break;
|
|
case GLUT_UP:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Input::calcAngle(GLfloat *newMatrix, GLfloat angle, Point& a) {
|
|
newMatrix[0] = 1.+(1.-cos(angle))*(pow(a.x,2)-1.);
|
|
newMatrix[1] = a.z*sin(angle) + (1.-cos(angle)) * a.x * a.y;
|
|
newMatrix[2] = -1. * a.y * sin(angle) + (1.-cos(angle))*a.x*a.z;
|
|
newMatrix[3] = 0;
|
|
newMatrix[4] = -1. * a.z * sin(angle) + (1.-cos(angle)) * a.x * a.y;
|
|
newMatrix[5] = 1. + (1. - cos(angle))*(pow(a.y,2)-1.);
|
|
newMatrix[6] = a.x * sin(angle) + (1.-cos(angle))*a.y*a.z;
|
|
newMatrix[7] = 0;
|
|
newMatrix[8] = a.y * sin(angle) + (1.-cos(angle))*a.x * a.z;
|
|
newMatrix[9] = -1. * a.x * sin(angle) + (1.-cos(angle))*a.y*a.z;
|
|
newMatrix[10] = 1. + (1.-cos(angle))*(pow(a.z,2)-1.);
|
|
newMatrix[11] = newMatrix[12] = newMatrix[13] = newMatrix[14] = 0;
|
|
newMatrix[15] = 1.;
|
|
}
|
|
|
|
void Input::scalePoint(Point& p, GLint mx, GLint my) {
|
|
//scale to -1 and 1
|
|
float scale = ceil(Renderer::getInstance()->getVPD()/2.);
|
|
p.x = (mx / scale) -1.;
|
|
p.y = (my / scale) -1.;
|
|
p.y*=-1.; //handle reversed y
|
|
|
|
p.z = 1.-pow(p.x,2)-pow(p.y,2);
|
|
|
|
if (p.z < 0) {
|
|
float under = sqrt((p.x*p.x)+(p.y*p.y));
|
|
p.x /= under;
|
|
p.y /= under;
|
|
p.z = 0;
|
|
} else {
|
|
p.z = sqrt(p.z);
|
|
}
|
|
|
|
}
|