opengl 教程(14) 摄像机控制(1)
原帖地址:http://ogldev.atspace.co.uk/www/tutorial14/tutorial14.html
前面一篇教程中,我们把摄像机放在三维空间的固定位置,本章我们尝试控制摄像机,在三维空间任意方向移动它。我们用键盘来控制摄像机的位置,用鼠标来改变摄像机lookat的方向,这个有点类似第一人称射击游戏中的摄像机控制。本章先来学习一下用键盘控制摄像机位置,下章来学习鼠标改变摄像机方位。
注意:我们用键盘移动的时候,仅仅是改变摄像机的位置,并没有改变lookat方向和up方向。glut中控制键盘的回调函数是 glutSpecialFunc(),当特殊的键被按下的时候,将会执行这个函数,比如方向键、翻页键等等。普通的按键,则需要回调函数 glutKeyboardFunc()。
主要代码:
新建一个camera类来封装摄像机的所有操作,该类保存摄像机的参数,基于接收的事件来改变这些参数,从而控制摄像机的运动。
Camera.h
class Camera
{
public:
Camera();
Camera(const Vector3f& Pos, const Vector3f& Target, const Vector3f& Up);
bool OnKeyboard(int Key);
const Vector3f& GetPos() const
const Vector3f& GetTarget() const
const Vector3f& GetUp() const
private:
Vector3f m_pos;
Vector3f m_target;
Vector3f m_up;
};
camera类中存储了三个属性:位置 position, lookat 向量(target vector) 以及up向量,函数OnKeyboard()用来处理键盘事件。如果是指定的键,则会控制摄像机移动。
Camera.cpp
bool Camera::OnKeyboard(int Key)
{
bool Ret = false;
switch (Key) {
case GLUT_KEY_UP:
{
m_pos += (m_target * StepSize);
Ret = true;
}
break;
case GLUT_KEY_DOWN:
{
m_pos -= (m_target * StepSize);
Ret = true;
}
break;
case GLUT_KEY_LEFT:
{
Vector3f Left = m_target.Cross(m_up);
Left.Normalize();
Left *= StepSize;
m_pos += Left;
Ret = true;
}
break;
case GLUT_KEY_RIGHT:
{
Vector3f Right = m_up.Cross(m_target);
Right.Normalize();
Right *= StepSize;
m_pos += Right;
Ret = true;
}
break;
}
return Ret;
}
当按下上下方向键时候,摄像机会沿着lookat方向移动,而左右方向键则会使摄4像沿着一个righ向量移动。
tutorial14.cpp
static void SpecialKeyboardCB(int Key, int x, int y)
{
GameCamera.OnKeyboard(Key);
}
static void InitializeGlutCallbacks()
{
glutDisplayFunc(RenderSceneCB);
glutIdleFunc(RenderSceneCB);
glutSpecialFunc(SpecialKeyboardCB);
}
我们会注册一个新的回调函数,来处理特殊按键。
tutorial14.cpp
p.SetCamera(GameCamera.GetPos(), GameCamera.GetTarget(), GameCamera.GetUp());
该命令用来初始化摄像机位置。
程序运行后界面如下:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程