Viewport3D中的摄像机(二、摄像机动作)

简介: 原文:Viewport3D中的摄像机(二、摄像机动作)前文介绍了Viewport3D中的两种摄像机:OrthographicCamera和PerspectiveCamera。在3D场景里漫游,最主要的工作就是针对用户输入(例如鼠标左右移动、键盘按下A、W、S、D等键)来改变摄像机的位置、方向。
原文: Viewport3D中的摄像机(二、摄像机动作)

前文介绍了Viewport3D中的两种摄像机:OrthographicCamera和PerspectiveCamera。在3D场景里漫游,最主要的工作就是针对用户输入(例如鼠标左右移动、键盘按下A、W、S、D等键)来改变摄像机的位置、方向。本文接下来介绍如何通过改变PerspectiveCamera的属性,来达到场景的漫游效果。

摄像机动作

我摄像机的动作可以分成三类、移动、旋转、拉升镜头。用一个枚举来描述这些动作:

public enum SceneCameraAction
{
    MoveForward,    //向前移动
    MoveBack,       //向后移动
    MoveLeft,       //向左移动
    MoveRight,      //向后移动
    MoveUp,         //向上移动
    MoveDown,       //向下移动
    TurnLeft,       //左转
    TurnRight,      //右转
    TurnUp,         //向上看
    TurnDown,       //向下看
    ZoomIn,         //拉近镜头
    ZoomOut,        //拉远镜头
}

移动摄像机

在WPF3D里,可以通过改变计算机的Position属性,来移动PerspectiveCamera,假设摄像机的移动速度为Speed,有以下移动公式:

新坐标=原坐标+速度×移动方向

下图为摄像机向前、向左、向上移动的方向,为了方便计算,移动方向都为单位向量。

image

向前、向后移动

向前移动的移动方向为LookDirection,向后为-1*LookDirection

向前移动:

Camera.Position += (Speed * Camera.LookDirection);

向后移动

Camera.Position -= (Speed * Camera.LookDirection);

向左、向右移动

向左、向右移动,相当于在XZ平面上,沿着摄像机的LookDirection投影垂直的直线方向移动。

向左移动:

Camera.Position += Speed * (Camera.LookDirection.Rotate(0, Math.PI / 2, 0).GetUnit());

向右移动:

Camera.Position += Speed * (Camera.LookDirection.Rotate(0, -1 * Math.PI / 2, 0).GetUnit());

上面的变换,我用了两个扩展函数:

把向量旋转拆分成分别绕x轴、y轴、z轴旋转:

image

用以下函数计算一个向量分别绕x、y、z轴旋转后得到的新向量:

/// <summary>
/// 向量旋转
/// </summary>
/// <param name="x">绕x轴旋转值</param>
/// <param name="y">绕y轴旋转值</param>
/// <param name="z">绕z轴旋转值</param>
/// <returns>旋转结果</returns>
public static Vector3D Rotate(this Vector3D vector3D,double x, double y, double z)
{
    Matrix3D rotateX = new Matrix3D(
        1,              0,              0,              0,
        0,              Math.Cos(x),    Math.Sin(x),    0,
        0,              -Math.Sin(x),   Math.Cos(x),    0,
        0,              0,              0,              1);

    Matrix3D rotateY = new Matrix3D(
        Math.Cos(y),    0,              -Math.Sin(y),   0,
        0,              1,              0,              0,
        Math.Sin(y),    0,              Math.Cos(y),    0,
        0,              0,              0,              1);

    Matrix3D rotateZ = new Matrix3D(
        Math.Cos(z),    Math.Sin(z),    0,              0,
        -Math.Sin(z),   Math.Cos(z),    0,              0,
        0,              0,              1,              0,
        0,              0,              0,              1);

    return vector3D * rotateX * rotateY * rotateZ;

}

GetUnit函数是计算一个响亮的单位向量:

public static Vector3D GetUnit(this Vector3D vector3D)
{
    double length = 1.0d;
    return new Vector3D(vector3D.X * length / vector3D.Length,
        vector3D.Y * length / vector3D.Length,
        vector3D.Z * length / vector3D.Length);
}

向上、向下移动

向上、向下移动相当于延y轴改变Camera的Position属性:

向上移动:

Camera.Position += Speed * new Vector3D(0, 1, 0);

向下移动:

Camera.Position += Speed * new Vector3D(0, -1, 0);

旋转摄像机

和移动摄像机不同,旋转摄像机时,保持摄像机的Position属性不变,根据旋转值修改摄像机的LookDirection属性。这里仅仅假设绕Y轴旋转:

/// <summary>
/// 旋转摄像头
/// </summary>
/// <param name="ModelCameraAction">旋转角度</param>
public void Turn(SceneCameraAction ModelCameraAction)
{
    double speed = Math.PI / 60;

    if (ModelCameraAction == SceneCameraAction.TurnLeft)
    {
        Camera.LookDirection = Camera.LookDirection.Rotate(0, speed, 0).GetUnit();
    }

    if (ModelCameraAction == SceneCameraAction.TurnRight)
    {
        Camera.LookDirection = Camera.LookDirection.Rotate(0, -1 * speed, 0).GetUnit();
    }
}
目录
相关文章
|
4月前
|
传感器 机器学习/深度学习 存储
使用激光雷达(LiDAR)和相机进行3D物体跟踪
使用激光雷达(LiDAR)和相机进行3D物体跟踪
|
4月前
[光源频闪] Basler相机光源频闪设置操作说明
[光源频闪] Basler相机光源频闪设置操作说明
73 0
|
9月前
|
传感器
使用校准相机测量平面物体
使用校准相机测量平面物体。
82 0
|
4月前
|
C# 图形学
控制物体的运动相关脚本
控制物体的运动相关脚本
|
9月前
检测使用校准的立体摄像头拍摄的视频中的人物并确定其与摄像头的距离
检测使用校准的立体摄像头拍摄的视频中的人物,并确定他们与摄像头的距离。
99 0
|
11月前
|
传感器 定位技术 图形学
SIGGRAPH | 6个惯性传感器和1个手机实现人体动作捕捉、定位与环境重建(2)
SIGGRAPH | 6个惯性传感器和1个手机实现人体动作捕捉、定位与环境重建
143 0
|
11月前
|
传感器 机器学习/深度学习 算法
SIGGRAPH | 6个惯性传感器和1个手机实现人体动作捕捉、定位与环境重建(1)
SIGGRAPH | 6个惯性传感器和1个手机实现人体动作捕捉、定位与环境重建
147 0
利用相机焦距进行物体尺寸测量
利用相机焦距进行物体尺寸测量
890 0
利用相机焦距进行物体尺寸测量
Threejs - 相机? 什么是相机? 照相机?
Threejs - 相机? 什么是相机? 照相机?
Threejs - 相机? 什么是相机? 照相机?