OpenGL基础:glut处理鼠标事件(含滚轮输入)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jacky_chenjp/article/details/69396540

检测鼠标单击

  要想在OpenGL中处理鼠标事件非常的方便,GLUT已经为我们的注册好了函数,只要我们提供一个方法。使用函数glutMouseFunc,就可以帮我们注册我们的函数,这样当发生鼠标事件时就会自动调用我们的方法。

函数的原型是:

void glutMouseFunc(void(*func)(int button,int state,int x,int y));  
参数:  
func:处理鼠标click事件的函数的函数名。

  从上面可以看到,处理鼠标单击事件的函数,一定有4个参数。第一个参数表明哪个鼠标键被按下或松开,这个变量可以是下面的三个值中的一个:

GLUT_LEFT_BUTTON
GLUT_MIDDLE_BUTTON
GLUT_RIGHT_BUTTON
// 下面两个是重构的OpenGL库函数中带的值,表示滚轮上下滚动的状态
GLUT_WHEEL_UP
GLUT_WHEEL_DOWN

  第二个参数表明,函数被调用发生时,鼠标键的状态,也就是被按下,或松开,可能取值如下:

GLUT_DOWN
GLUT_UP

  当函数被调用时,state的值是GLUT _DOWN。那么程序可能会假定将会有个GLUT _UP事件,甚至鼠标移动到窗口外面,也如此。然而,如果程序调用glutMouseFunc传递NULL作为参数,那么GLUT将不会改变鼠标的状态。

  剩下的两个参数(x,y)提供了鼠标当前的窗口坐标(以左上角为原点)。

检测动作

  GLUT提供鼠标动作检测能力。有两种GLUT处理的motion:active motion和passive motion。

  Active motion是指鼠标移动并且有一个鼠标键被按下。
  Passive motion是指当鼠标移动时,并有没鼠标键按下。
  如果一个程序正在追踪鼠标,那么鼠标移动期间,每一帧将产生一个结果。

  和以前一样,你必须注册将处理鼠标事件的函数(定义函数)。GLUT让我们可以指定两个不同的函数,一个追踪passive motion,另一个追踪active motion。

函数原型如下:

void glutMotionFunc(void(*func)(int x,int y));
void glutPassiveMotionFunc(void (*func)(int x,int y));
参数:
Func:处理各自类型motion的函数名。
处理motion的参数函数的参数(x,y)是鼠标在窗口的坐标。以左上角为原点。

检测鼠标进入或离开窗口

  GLUT还能检测鼠标鼠标离开,进入窗口区域。一个回调函数可以被定义去处理这两个事件。GLUT里,调用这个函数的是glutEntryFunc,函数原型如下:

void glutEntryFunc(void(*func)(int state));
参数:
Func:处理这些事件的函数名。
上面函数的参数中,state有两个值表明是离开还是进入窗口:
GLUT_LEFT
GLUT_ENTERED

应用

  现在想实现的功能就是使用鼠标拖动,来转动场景中的物体,当鼠标左键按下,并且上下左右滑动时,场景中的模型相应的会随之上下左右旋转,当鼠标右键按下,并且上下左右滑动时,场景中的模型相应的会随之在屏幕中进行平移。

首先,定义几个全局变量:

bool mouseLeftDown;
bool mouseRightDown;
bool mouseMiddleDown;
float mouseX, mouseY;
float cameraDistanceX;
float cameraDistanceY;
float cameraAngleX;
float cameraAngleY;
float times=1;

  其中,mouseLeftDown和 mouseRightDown变量标志鼠标左右键按下与否,mouseX和mouseY变量标志鼠标滑动时,前一刻的鼠标所在位置。
  cameraDistanceX和cameraDistanceY变量根据鼠标右键按下并滑动操作来控制模型物体的平移。cameraAngleX和cameraAngleY变量根据鼠标左键按下并滑动来控制场景中物体的旋转。
  times变量表示缩放倍数,默认是原样缩放,为1倍。

void mouseCB(int button, int state, int x, int y)
{
    mouseX = x;
    mouseY = y;
    times = 1;

    if(button == GLUT_LEFT_BUTTON)
    {
        if(state == GLUT_DOWN)
        {
            mouseLeftDown = true;
        }
        else if(state == GLUT_UP)
            mouseLeftDown = false;
    }

    else if(button == GLUT_RIGHT_BUTTON)
    {
        if(state == GLUT_DOWN)
        {
            mouseRightDown = true;
        }
        else if(state == GLUT_UP)
            mouseRightDown = false;
    }

    /*
    * 鼠标滚轮控制图形缩放
    */
    else if (state == GLUT_UP && button == GLUT_WHEEL_UP)
    {
        times = 0.008f+1;
        glutPostRedisplay();
    }

    else if (state == GLUT_UP && button == GLUT_WHEEL_DOWN)
    {
        times = -0.008f+1;
        glutPostRedisplay();
    }
}  

void mouseMotionCB(int x, int y)
{
    cameraAngleX = cameraAngleY = 0;
    cameraDistanceX = cameraDistanceY = 0;

    if (mouseLeftDown)
    {
        cameraAngleY += (x - mouseX) * 0.1f;
        cameraAngleX += (y - mouseY) * 0.1f;
        mouseX = x;
        mouseY = y;
    }
    if (mouseRightDown)
    {
        cameraDistanceX = (x - mouseX) * 0.002f;
        cameraDistanceY = -(y - mouseY) * 0.002f;
        mouseY = y;
        mouseX = x;
    }

    glutPostRedisplay();
}

  最后,在主函数中,调用相应的函数注册即可:

glutMouseFunc(mouseCB);
glutMotionFunc(mouseMotionCB);

  在场景中物体绘制之前,这样就可以:

glScalef(times, times, times);//缩放
glTranslatef(cameraDistanceX, cameraDistanceY, 0);
glRotatef(cameraAngleX, 1, 0, 0);
glRotatef(cameraAngleY, 0, 1, 0);

备注

  由于默认的OpenGL库中,不含接收鼠标滚轮输入的库函数,故在本文中的所有与滚轮控制缩放相关的功能实现,需要配置重构的OpenGL库。具体资源及使用注意我已经打包好了,下载地址是:
  下载:OpenGL库函数拓展
  完成效果的视频演示:
  视频演示
  源码参见:
  源码传送门

猜你喜欢

转载自blog.csdn.net/Jacky_chenjp/article/details/69396540