【Overload游戏引擎细节分析】鼠标键盘控制摄像机原理

这篇具有很好参考价值的文章主要介绍了【Overload游戏引擎细节分析】鼠标键盘控制摄像机原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在上文中分析了摄像机类的实现,在计算投影视图矩阵时需要给摄像机输入其位置及转动四元数。这两个量一般通过鼠标键盘来控制,从而达到控制摄像机的目的。本文分析一下其控制原理。

Overload的摄像机控制实现在类CameraController中,其有三个个方法HandleCameraPanning、HandleCameraFPSMouse、HandleCameraOrbit、HandleCameraZoom是鼠标控制摄像机的平移、绕自身转动、绕特定点转动、缩放。还有一个方法,HandleCameraFPSKeyboard是键盘控制摄像机。其头文件如下,已删除本文不关注的代码及字段。

namespace OvEditor::Core
{
	class CameraController
	{
	private:
		// 控制摄像机的平移
		void HandleCameraPanning(const OvMaths::FVector2& p_mouseOffset, bool p_firstMouse);
		// 控制摄像机绕物体进行旋转
		void HandleCameraOrbit(const OvMaths::FVector2& p_mouseOffset, bool p_firstMouse);
		// 鼠标控制摄像机旋转
		void HandleCameraFPSMouse(const OvMaths::FVector2& p_mouseOffset, bool p_firstMouse);

		// 控制滚轮放大缩小
		void HandleCameraZoom();
		// 键盘控制摄像机
		void HandleCameraFPSKeyboard(float p_deltaTime);
		void UpdateMouseState();

	private:
		OvRendering::LowRenderer::Camera& m_camera; // 当前摄像机
		OvMaths::FVector3& m_cameraPosition; // 当前摄像机的位置
		OvMaths::FQuaternion& m_cameraRotation; // 当前摄像机的旋转四元数
	};
}

这四个函数就是通过改变m_cameraPosition、m_cameraRotation从而达到控制摄像机的目的。

一、鼠标控制缩放HandleCameraZoom
鼠标控制缩放的代码如下:

void OvEditor::Core::CameraController::HandleCameraZoom()
{
	m_cameraPosition += m_cameraRotation * OvMaths::FVector3::Forward * ImGui::GetIO().MouseWheel;
}

OvMaths::FVector3::Forward是固定矢量(0,0,1),其与m_cameraRotation相乘获取当前摄像机的Z轴,也叫Forward量,或可称为摄像机的指向。Imgui可获取鼠标滚轮的转动量,与Forward相乘,累加到摄像机位置上,产生摄像机拉进或拉远的效果。在其他软件中,我还见到过通过改变视口的大小实现缩放的,这种改变摄像机位置方式感觉更直观。但这种方式对正向相机缺点:滚轮不能缩放物体,因为正交投影相当于将物体放到一个正方形盒子中,在盒子一侧看,这个物体沿深度方向改变是不会有近大远小的效果的。所以一些工业软件中使用改变视口大小,实现物体缩放效果。

二、鼠标控制平动HandleCameraPanning

void OvEditor::Core::CameraController::HandleCameraPanning(const OvMaths::FVector2& p_mouseOffset, bool p_firstMouset)
{
   // 根据设置的拖动速度计算增量
	auto mouseOffset = p_mouseOffset * m_cameraDragSpeed;
	
	// 摄像机位置沿着Right、Up轴移动
	m_cameraPosition += m_cameraRotation * OvMaths::FVector3::Right * mouseOffset.x;
	m_cameraPosition -= m_cameraRotation * OvMaths::FVector3::Up * mouseOffset.y;
}

p_mouseOffset是鼠标移动矢量,是二维向量,但摄像机坐标系有三个轴,所以只能控制两个轴的平动。

三、鼠标控制绕自身转动HandleCameraFPSMouse
这个函数实现摄像机绕自身原点转动。p_firstMouse是当鼠标按下是为true,转动过程中为false。当第一次转动时,先将转动转换为欧拉角,RemoveRoll是对欧拉角做特殊处理,看着像是为了克服万向节死锁,没看太明白,有用的时候再来深究吧。

void OvEditor::Core::CameraController::HandleCameraFPSMouse(const OvMaths::FVector2& p_mouseOffset, bool p_firstMouse)
{
	auto mouseOffset = p_mouseOffset * m_mouseSensitivity;

	if (p_firstMouse)
	{
		m_ypr = OvMaths::FQuaternion::EulerAngles(m_cameraRotation);
		m_ypr = RemoveRoll(m_ypr);
	}

	m_ypr.y -= mouseOffset.x;
	m_ypr.x += -mouseOffset.y;
	m_ypr.x = std::max(std::min(m_ypr.x, 90.0f), -90.0f);

	m_cameraRotation = OvMaths::FQuaternion(m_ypr);
}

鼠标偏移量改变欧拉角,注意其改变的值是x、y分量,最后再转换为四元数。

四、摄像机绕特殊点旋转HandleCameraOrbit
这个实际软件中使用也很多。这个相对于绕摄像机原点旋转多了平移分量,会同时改变摄像机的位置与姿态。

void OvEditor::Core::CameraController::HandleCameraOrbit(const OvMaths::FVector2& p_mouseOffset, bool p_firstMouse)
{
	auto mouseOffset = p_mouseOffset * m_cameraOrbitSpeed; // 鼠标偏移量

	if (p_firstMouse)
	{
		m_ypr = OvMaths::FQuaternion::EulerAngles(m_cameraRotation); // 转换为欧拉角
		m_ypr = RemoveRoll(m_ypr); // 可能是为了解决万向节死锁
		m_orbitTarget = &EDITOR_EXEC(GetSelectedActor()).transform.GetFTransform();
		m_orbitStartOffset = -OvMaths::FVector3::Forward * OvMaths::FVector3::Distance(m_orbitTarget->GetWorldPosition(), m_cameraPosition); // 摄像机需要平移的量(摄像机局部坐标系下)
	}

	m_ypr.y += -mouseOffset.x;  // 对欧拉角进行改变
	m_ypr.x += -mouseOffset.y;
	m_ypr.x = std::max(std::min(m_ypr.x, 90.0f), -90.0f);

	auto& target = EDITOR_EXEC(GetSelectedActor()).transform.GetFTransform();
	OvMaths::FTransform pivotTransform(target.GetWorldPosition());
	OvMaths::FTransform cameraTransform(m_orbitStartOffset); // 设置摄像机平移量
	cameraTransform.SetParent(pivotTransform); 
	pivotTransform.RotateLocal(OvMaths::FQuaternion(m_ypr)); // 将绕的点进行旋转
	m_cameraPosition = cameraTransform.GetWorldPosition();  // 获取摄像机位置
	m_cameraRotation = cameraTransform.GetWorldRotation(); // 获取摄像机转角
}

其原理是将围绕的点进行旋转,再平移获取摄像机的位置及姿态。

五、键盘控制摄像机平动HandleCameraFPSKeyboard
这个函数原理类似于鼠标平动,都是线用转动四元数获取当前轴,给位置一个增量即可,这里就不详细分析了。

如何使用这些函数与产品设计相结合?
上面只是摄像机控制的单个函数,想在产品中集成还需其他的GUI库(如QT、glfw、imgui等)配合获取鼠标键盘状态,不断分情况调用这些函数。这些代码差异较大,跟产品设计密切相关,不具有通用性,不再分析。Overload这部分代码在CameraController::HandleInputs函数中,有兴趣可以阅读。文章来源地址https://www.toymoban.com/news/detail-721480.html

到了这里,关于【Overload游戏引擎细节分析】鼠标键盘控制摄像机原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Overload游戏引擎细节分析】画场景栅格的Shader分析

    Overload引擎地址: GitHub - adriengivry/Overload: 3D Game engine with editor 一、栅格绘制基本原理 Overload Editor启动之后,场景视图中有栅格线,这个在很多软件中都有。刚开始我猜测它应该是通过绘制线实现的。阅读代码发现,这个栅格的几何网格只有两个三角形面片组成的正方形,使

    2024年02月07日
    浏览(40)
  • 【Overload游戏引擎细节分析】PBR材质Shader---完结篇

    PBR基于物理的渲染可以实现更加真实的效果,其Shader值得分析一下。但PBR需要较多的基础知识,不适合不会OpenGL的朋友。 一、PBR理论 PBR指基于物理的渲染,其理论较多,需要的基础知识也较多,我在这就不再写一遍了,具体可以参看: LearnOpenGL PBR理论-英文 或者 LearnOpenGL

    2024年02月08日
    浏览(44)
  • 【Overload游戏引擎细节分析】UBO与SSBO的封装

    一、OpenGL的UBO   在OpenGL Shader中,如果逻辑比较复杂,使用的uniform变量较多。通常多个着色器使用同一个uniform变量。由于uniform变量的位置是着色器链接时候产生的,因此它在应用程序中获得的索引会有变化。Uniform Buffer Object(UBO)是一种优化uniform变量访问,不同着色器直接

    2024年02月07日
    浏览(37)
  • 【UE5 智慧城市系列】5-通过鼠标键盘控制摄像机

    通过鼠标WASD键控制摄像机前后左右移动,鼠标滚轮控制弹簧臂长度的修改,鼠标中键控制摄像机旋转。 1. 首先创建一个游戏模式,这里命名为“BP_GameMode” 2. 再创建一个玩家控制器,这里命名为“BP_PlayerController” 3. 新建一个玩家控制的Pawn,这里命名为“BP_CameraPawn” 4. 打开

    2024年02月09日
    浏览(60)
  • Unity3D摄像机,键盘控制前后左右上下移动,鼠标控制旋转、放缩

    Unity3D中运行场景时,实现摄像机的前、后、左、右、上、下,以及鼠标滚轮的放缩,鼠标右键的旋转操作。亲测有效,可供参考。 按键功能介绍:W——前;S——后;A——左;D——右;Q——下降;E——上升;鼠标右键——旋转;鼠标滚轮——放缩。 Tourcamera脚本需要挂在摄

    2024年02月11日
    浏览(61)
  • 瓦片地图编辑器——实现卡马克卷轴的编辑,键盘控制游戏移动和鼠标点击游戏编辑通过同一个视口实现。

      左边是游戏地图编辑区,右边是地图缓冲区,解决了地图缓冲区拖动bug,成功使得缓冲区可以更新。 AWSD进行移动 鼠标左右键分别是绘制/拖动 按F1健导出为mapv3.txt F2清空数组 打印的是游戏数组 easyx开发devcpp 5.11 easyx20220922版本

    2024年01月25日
    浏览(79)
  • Unity【角色/摄像机移动控制】【2.角色跟随鼠标转向】

    本章代码实现基于本系列的【1.角色移动】 在前面的基础上,我们在PlayerController脚本中添加如下函数,随后在update方法中调用即可: 其中mouseSensitivity是前面自定义的一个float变量,用来调节对鼠标转向速度,至此,当我们转动鼠标,角色也会跟着转动

    2024年02月22日
    浏览(56)
  • 【UE4】 通过按钮点击实现摄像机的切换 并通过鼠标控制新摄像机的旋转

    首先创建了4个Actor蓝图类 每个蓝图类内只拥有一个摄像机组件 将每个actor蓝图类摆放到场景的合适位置 在关卡蓝图中创建自定义事件,当该事件触发时切换摄像机 创建一个控件蓝图,在控件蓝图中创建如下5个按钮,并创建点击事件。按钮分别表示车上的4个镜头和车外自由

    2023年04月09日
    浏览(59)
  • UE5回合制游戏【2-摄像机控制】(蓝图版)

    上一篇文章完成了一些基础的设置,这篇文章主要来设置一下摄像机。 摄像机的控制主要有鼠标滚轮控制缩放,WASD键控制前后左右移动,QE键控制左右旋转。 首先打开BP_Pawn,然后添加Spring和Camera组件。 层级关系如下图 我们把摄像机放到弹簧臂下面,这样摄像机就能跟着弹

    2024年02月03日
    浏览(48)
  • Unity制作射击游戏案例01(控制角色+发射子弹+摄像机跟踪)

    //【业务逻辑】这个脚本用来1.控制物体移动旋转(WASD)、   2.发射子弹(空格键) //【程序逻辑2】 首先检测用户没有按下空格键 2.如果按下呢执行发射子弹函数    3.克隆子弹 4.让克隆的子弹往前跑 为子弹模板添加刚体,并且限制旋转 这个脚本需要挂在到摄像机,里面谈

    2024年02月06日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包