OpenGL工程实现实用教程2---freeglut库的输入响应

这篇教程详细介绍了如何在OpenGL使用freeglut库处理键盘和鼠标输入。通过glutKeyboardFunc和glutMouseFunc注册回调函数响应键盘和鼠标消息。此外,还提到了freeglut扩展库中的glutMouseWheelFunc用于处理鼠标滚轮事件,以及利用定时器实现鼠标双击检测。文章最后提到了获取鼠标位置的glutPassiveMotionFunc函数,并给出了完整代码示例。
摘要由CSDN通过智能技术生成

在PC上用户的输入操作一般分为键盘+鼠标两种,freeglut库已经帮我们封装好了这些操作的消息响应,只需要用户注册并编写响应逻辑即可。

键盘响应

键盘的消息注册函数为glutKeyboardFunc,消息响应回调函数可定义如下:

//第一个参数表示按下的按键的ASCII码。
//其余两个参数提供了当键按下时当前的鼠标位置(相对于当前客户窗口的左上角)。
void keyboardFunc(unsigned char key, int x, int y)
{
  switch (key)
  {
  case 27:
    std::cout << "按下退出键" << std::endl;
    glutLeaveMainLoop();//退出消息循环
    break;
  case 'R':
    std::cout << "按下R键" << std::endl;
    break;
  }
}

注册函数的完整代码:

glutKeyboardFunc(keyboardFunc);//定义键盘响应函数

鼠标响应

鼠标的消息注册函数为glutMouseFunc,消息响应回调函数可定义如下:

//参数一是鼠标对象,参数二是状态。
//其余两个参数提供了当前的鼠标位置(相对于当前客户窗口的左上角)。
void mouseFunc(int button, int state, int x, int y)
{
    //按键判断
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
            std::cout << "鼠标左键按下" << std::endl;
        else if (state == GLUT_UP)
            std::cout << "鼠标左键释放" << std::endl;
    }
    if (button == GLUT_MIDDLE_BUTTON)
    {
        if (state == GLUT_DOWN)
            std::cout << "鼠标中键按下" << std::endl;
        else if (state == GLUT_UP)
            std::cout << "鼠标中键释放" << std::endl;
    }
    if (button == GLUT_RIGHT_BUTTON)
    {
        if (state == GLUT_DOWN)
            std::cout << "鼠标右键按下" << std::endl;
        else if (state == GLUT_UP)
            std::cout << "鼠标右键释放" << std::endl;
    }
}

从该响应函数可以看到两个不足,一是没有鼠标中键的信息,二是没有双击鼠标按钮的信息。

针对问题一,在freeglut的扩展库中提供了解决方法,注册鼠标滚轮消息函数glutMouseWheelFunc,然后将消息响应函数定义如下:

//鼠标滚轮上下响应函数,最重要的是参数二,大于0表示上滚,小于0则表示下滚
void mouseWheel(int button, int dir, int x, int y)
{
  if (dir > 0)
    std::cout << "鼠标滚轮向上" << std::endl;
  else
    std::cout << "鼠标滚轮向下" << std::endl;
}

针对问题二,没有现成的解决办法。。。可以通过判断两次鼠标点击的时间间隔来实现。由于freeglut提供可定时器函数,因此实现起来也很简单。

首先,声明两个全局变量:

bool leftbuttondown1 = false;
bool leftbuttondown2 = false;

然后,将鼠标响应函数改为:

if (button == GLUT_LEFT_BUTTON)
{
    if (state == GLUT_DOWN)
    {
        leftbuttondown2 = leftbuttondown1;
        leftbuttondown1 = true;
        if (!leftbuttondown2)
        {
            glutTimerFunc(200, timerProc, 1);//设置定时器200毫秒后调用timerProc函数,id为1
        }
    }
}

最后定义定时器响应函数即可:

//定时器响应
void timerProc(int id)
{
    if (id==1)
    {
        if (leftbuttondown2 && leftbuttondown1)
        {
            std::cout << "鼠标左键双击" << std::endl;
        }
        else
        {
            std::cout << "鼠标左键单击" << std::endl;
        }
        leftbuttondown1 = false;
        leftbuttondown2 = false;
    }
}

另外,如果我们想要做UI,有些控件需要实时获得鼠标的位置信息,这个时候可以使用另外的响应函数glutPassiveMotionFunc,具体的操作也非常简单,先注册该函数:

glutPassiveMotionFunc(mouseMotion);//实时获得鼠标位置信息

然后对其进行定义即可:

//鼠标移动时发送消息
void mouseMotion(int x, int y)
{
    std::cout << "x: " << x << std::endl;
    std::cout << "y: " << y << std::endl;
}

到此我们就完成了freeglut库输入响应的全部介绍,完整的代码如下:

#include <iostream>
#include <GL/freeglut.h>
#include <GL/freeglut_ext.h>

void display(void)
{
    //填充缓冲区表面
    glFlush();
    //缓冲区翻转显示图像
    glutSwapBuffers();
}

//第一个参数表示按下的按键的ASCII码。
//其余两个参数提供了当键按下时当前的鼠标位置(相对于当前客户窗口的左上角)。
void keyboardFunc(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 27:
        std::cout << "按下退出键" << std::endl;
        glutLeaveMainLoop();//退出消息循环
        break;
    case 'R':
        std::cout << "按下R键" << std::endl;
        break;
    }
}

bool leftbuttondown1 = false;
bool leftbuttondown2 = false;

//定时器响应
void timerProc(int id)
{
    if (id==1)
    {
        if (leftbuttondown2 && leftbuttondown1)
        {
            std::cout << "鼠标左键双击" << std::endl;
        }
        else
        {
            std::cout << "鼠标左键单击" << std::endl;
        }
        leftbuttondown1 = false;
        leftbuttondown2 = false;
    }
}

//参数一是鼠标对象,参数二是状态。
//其余两个参数提供了当前的鼠标位置(相对于当前客户窗口的左上角)。
void mouseFunc(int button, int state, int x, int y)
{
    //按键判断
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            leftbuttondown2 = leftbuttondown1;
            leftbuttondown1 = true;
            if (!leftbuttondown2)
            {
                glutTimerFunc(200, timerProc, 1);//设置定时器200毫秒后调用timerProc函数,id为1
            }
        }
    }
}

//鼠标滚轮上下响应函数,最重要的是参数二,大于0表示上滚,小于0则表示下滚
void mouseWheel(int button, int dir, int x, int y)
{
    if (dir > 0)
        std::cout << "鼠标滚轮向上" << std::endl;
    else
        std::cout << "鼠标滚轮向下" << std::endl;
}

//鼠标按钮没有按下时,移动发送消息
void mousePassiveMotion(int x, int y)
{
    std::cout << "x: " << x << std::endl;
    std::cout << "y: " << y << std::endl;
}

//鼠标按钮按下时发送消息
void mouseMotion(int x, int y)
{
    std::cout << "x1: " << x << std::endl;
    std::cout << "y1: " << y << std::endl;
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);//设置绘图模式
    glutInitWindowPosition(0, 0);//设置窗口弹出位置
    glutInitWindowSize(800, 600);//设置窗口大小
    glutCreateWindow("imgshow");//创建窗口
    glutKeyboardFunc(keyboardFunc);//定义键盘响应函数
    glutMouseFunc(mouseFunc);//定义鼠标响应函数
    glutMouseWheelFunc(mouseWheel);//定义鼠标滚轮回调函数
    glutPassiveMotionFunc(mousePassiveMotion);//实时获得鼠标位置信息
    glutMotionFunc(mouseMotion);//实时获得鼠标位置信息
    glutDisplayFunc(&display);//定义绘图回调函数
    glutMainLoop();//进入消息循环
    return 0;
}

下一篇文章我们将介绍freeglut中中文文字的渲染。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值