php网站好做seo,中国网站模板下载,实体店铺托管代运营,公司网站建设基本流程在上文中分析了摄像机类的实现#xff0c;在计算投影视图矩阵时需要给摄像机输入其位置及转动四元数。这两个量一般通过鼠标键盘来控制#xff0c;从而达到控制摄像机的目的。本文分析一下其控制原理。 Overload的摄像机控制实现在类CameraController中#xff0c;其有三个个… 在上文中分析了摄像机类的实现在计算投影视图矩阵时需要给摄像机输入其位置及转动四元数。这两个量一般通过鼠标键盘来控制从而达到控制摄像机的目的。本文分析一下其控制原理。 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);
}鼠标偏移量改变欧拉角最后再转换为四元数。
四、摄像机绕特殊点旋转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 这个函数原理类似于鼠标平动都是线用转动四元数获取当前轴给位置一个增量即可这里就不详细分析了。