OpenGL学习之路12----相机控制(键盘操作)

代码放在github上

本文根据教程:ogldev进行扩充学习,一步步从零开始,记录学习历程

上一篇博文讲述了我们怎么把相机摆在三维空间的任意一个位置,想要了解的同学请移步上一篇博客:
OpenGL学习之路11—-相机空间

这次我们的目标是通过键盘上的方向键来移动相机。但是仅仅是改变相机的位置,而并没有改变相机的目标朝向(target向量)和竖直头顶方向(up向量)。

一、键盘操作

1.1 回顾显示回调函数

先回顾下我们渲染显示一个图形的时候是怎么做的:

glutDisplayFunc(Render);
glutIdleFunc(Render);
  • 我们把渲染函数Render()注册成为显示回调函数,再把它设置成全局闲置回调函数。因为我们的OpenGL程序跑在一个窗口系统里,大多数工作通过回调函数完成,我们在渲染函数里面还传递了Uniform变量的值,所以要让程序闲置时就不停的执行它。
  • 主要是明白我们显示图形是通过回调渲染函数,渲染函数里有绘制命令从而完成的

1.2 注册键盘事件回调

同理我们想要获取键盘值并执行相应操作,我们也要注册一个回调事件,用于在获得键盘按下后执行某些操作。

一般使用两个GLUT接口函数用来注册键盘按下后的回调函数

glutSpecialFunc()
glutKeyboardFunc()
  • glutKeyboardFunc()用于注册常规按键(字母和数字键)触发后的回调函数。我们这次没有用到,所以不做解释。
  • glutSpecialFunc()函数用于注册”特殊按键”按下后执行的回调函数
  • 在freeglut_std.h中可以看到定义好的特殊按键的值,从名称就可以看出是哪些按键:
/*
 * GLUT API macro definitions -- the special key codes:
 */
#define  GLUT_KEY_F1                        0x0001
#define  GLUT_KEY_F2                        0x0002
#define  GLUT_KEY_F3                        0x0003
#define  GLUT_KEY_F4                        0x0004
#define  GLUT_KEY_F5                        0x0005
#define  GLUT_KEY_F6                        0x0006
#define  GLUT_KEY_F7                        0x0007
#define  GLUT_KEY_F8                        0x0008
#define  GLUT_KEY_F9                        0x0009
#define  GLUT_KEY_F10                       0x000A
#define  GLUT_KEY_F11                       0x000B
#define  GLUT_KEY_F12                       0x000C
#define  GLUT_KEY_LEFT                      0x0064
#define  GLUT_KEY_UP                        0x0065
#define  GLUT_KEY_RIGHT                     0x0066
#define  GLUT_KEY_DOWN                      0x0067
#define  GLUT_KEY_PAGE_UP                   0x0068
#define  GLUT_KEY_PAGE_DOWN                 0x0069
#define  GLUT_KEY_HOME                      0x006A
#define  GLUT_KEY_END                       0x006B
#define  GLUT_KEY_INSERT                    0x006C
  • glutSpecialFunc()注册的函数必须带有三个int变量的参数,第一个参数是按键的键值也就是上面define各个按键的键值,x和y是以左上角为起点按键事件发生时鼠标点所处的位置(本节没用到鼠标)
glutSpecialFunc(Keyboard);
void Keyboard(int key,int x,int y );

二、相机类

为了使我们的程序高内聚低耦合,更加层次分明我们设置一个相机类,用来存放跟相机有关的参数变量和对应的方法

2.1 opengl_camera.h:

#ifndef __OPENGL_CAMERA_H
#define __OPENGL_CAMERA_H
#include "opengl_math.h"
class Camera
{
private:
    Vector3f m_pos;
    Vector3f m_target;
    Vector3f m_up;

    int m_windowWidth;
    int m_windowHeight;
public:
    Camera(int Window_Width, int Window_Height)
    {
        m_windowWidth = Window_Width;
        m_windowHeight = Window_Height;
        LoadVector3(m_pos,0.0f, 0.0f, 0.0f);
        LoadVector3(m_target,0.0f, 0.0f, 1.0f);
        LoadVector3(m_target,0.0f, 1.0f, 0.0f);
    }
    Camera(int Window_Width, int Window_Height, const Vector3f& Pos, const Vector3f& Target, const Vector3f& Up)
    {
        m_windowWidth = Window_Width;
        m_windowHeight = Window_Height;
        CopyVector3(m_pos, Pos);
        CopyVector3(m_target, Target);
        CopyVector3(m_up, Up);
    }
    const Vector3f& GetPos()
    {
        return m_pos;
    }
    const Vector3f& GetTarget()
    {
        return m_target;
    }
    const Vector3f& GetUp()
    {
        return m_up;
    }
    bool OnKeyboard(int key);
};

#endif
  • 可以看到私有变量共有五个,这些向量在之前的学习中已经详细解释过了它们的含义,分别是

    m_pos: 相机所处世界空间的位置
    m_target: 相机的朝向方向向量
    m_up: 相机的头顶方向向量
    m_windowWidth: 屏幕的宽
    m_windowHeight: 屏幕的高

  • 两个类的构造函数,用来初始化相机的参数
  • 三个获得相机三个重要参数的接口函数
  • 还有一个返回一个布尔类型的方法,从函数名可以看出是键盘操作,具体会在opengl_camera.cpp里实现

2.2 opengl_camera.cpp:

#include "opengl_camera.h"
#include <gl/freeglut_std.h>
#include <stdio.h>
#define StepSize 1
bool Camera::OnKeyboard(int key)
{
    bool Ret = false;

    switch (key) {
    case GLUT_KEY_UP:
    {
        for (int i = 0; i < 3; i++)
            m_pos[i] += m_target[i] * StepSize;
        Ret = TRUE;
    }
    break;
    case GLUT_KEY_DOWN:
    {
        for (int i = 0; i < 3; i++)
            m_pos[i] -= m_target[i] * StepSize;
        Ret = TRUE;
    }
    break;
    case GLUT_KEY_LEFT:
    {
        Vector3f 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值