Directx 在XNA上移动3d相机

Directx 在XNA上移动3d相机,directx,xna,direct3d,Directx,Xna,Direct3d,我在XNA上做了一些练习,我创建了一个表示相机的类 我的目标是,当用户按下某些键时,将相机(而不是目标)在X轴上平移90度(以从不同角度查看我放置在场景中的对象)。当我在X、Y和Z方向移动相机时没有问题 实际上,为了设置我的相机,我使用了以下代码行: public void SetUpCamera() { #region ## SET DEFAULTS ## this.FieldOfViewAngle = 45.0f; th

我在XNA上做了一些练习,我创建了一个表示相机的类

我的目标是,当用户按下某些键时,将相机(而不是目标)在X轴上平移90度(以从不同角度查看我放置在场景中的对象)。当我在X、Y和Z方向移动相机时没有问题

实际上,为了设置我的相机,我使用了以下代码行:

public void SetUpCamera()
{
            #region ## SET DEFAULTS ##
            this.FieldOfViewAngle = 45.0f;
            this.AspectRatio =1f;
            this.NearPlane = 1.0f;
            this.FarPlane = 10000.0f;
            #endregion

            this.ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(this.FieldOfViewAngle), 16 / 9, this.NearPlane, this.FarPlane);
            this.ViewMatrix = Matrix.CreateLookAt(new Vector3(this.PositionX, this.PositionY, this.PositionZ), new Vector3(this.TargetX, this.TargetY, this.TargetZ), Vector3.Up);
}
我有以下方法来移动相机:

public void UpdateView()
{
     this.ViewMatrix = Matrix.CreateLookAt(new Vector3(this.PositionX, this.PositionY, this.PositionZ), new Vector3(this.TargetX, this.TargetY, this.TargetZ), Vector3.Up);
}
然后在游戏中(更新事件处理程序我有以下代码)

我想知道如何使这个相机平移90度,以围绕我放在屏幕上的一个物体

为了更好地解释我自己对摄像机运动的看法,youtube上有一段视频,它使用了我试图描述的确切运动(见14秒)

假设视频中的摄像头正在围绕汽车运行,下面是您在XNA中实现这一点的方法

为了可读性,我们将只使用向量,而不是它们各自的组件。所以“target”是指一个向量3,包括TargetX、TargetY和TargetZ。相机的位置也一样。如果以后愿意,您可以将X、Y、Z值分解为字段,并将它们转换成矢量3插入到代码中,但实际上最好是在矢量级别而不是组件级别工作

//To orbit the car (target)
cameraPosition = Vector3.Transform(cameraPosition – target, Matrix.CreateRotationY(0.01f)) + target;
this.ViewMatrix = Matrix.CreateLookAt(cameraPosition, target, Vector3.Up);
由于所有矩阵旋转都围绕与世界原点相交的轴进行,因此要使用旋转矩阵围绕汽车旋转摄影机,必须移动旋转对象,以使目标(以及旋转轴)位于世界原点。CameraPosition-目标完成此任务。现在摄像机的位置可以旋转一点。一旦cameraPosition稍微旋转一点,就需要将其发送回手边的场景,这就是行末尾的“+目标”的作用


0.01f可以调整为适合您的任何旋转速度。

此解决方案中有几个小缺陷:1)旋转速度应乘以该帧所用的时间。2) 我建议在角度上累积旋转,而不是相机位置本身——为了更好地测量,我可能会在角度上使用
WrapAngle
。@Andrew。1) 我在实践中同意,但我故意省略了“经过的时间”来简化算法,以便更好地可视化和理解。也许不是个好选择,我不知道。2) 我不同意这一点。在3d中,存储与帧到帧的旋转/方向有关的角度是不好的。在2d中,存储某物方向的角度表示是正确的。在3d中,这很糟糕。请看此链接,重点放在博客文章的最后一段:@Steve我恐怕不同意。虽然作为一般规则,不使用角度进行计算是完全正确的,但使用角度放置轨道摄影机是完全有效的。为了画出一个圆,你必须从一个角度创建一个旋转矩阵(你自己做)。我只是建议一种更好的储存方式。Shawn文章的主旨是,像
CreateLookAt
这样的实现不应该使用角度和三角学,而应该使用点积和叉积(确实如此)。角度方法要求旋转轴是恒定的,尽管在OP的情况下可能是恒定的,但并不总是如此。在三维中,与二维不同,轴不受约束。所以,如果,比如说,轨道轴在轨道中间被改变了,你的角度方法会受到影响,而不会增加数学复杂性。我的方法没有底线不是你“一般不应该使用角度”,而是“你不应该使用角度来存储方向信息”,因为角度需要一个轴,然后你会被限制到该轴或不必要的数学来解决三维变化。不完全是这样。圆轨道相机由原点(平移)、旋转平面(旋转)、角度(旋转)和距离(平移)四个变换步骤组成。所有这些都可以单独设置动画,并应按此方式存储。你甚至可以将两个旋转步骤存储为可怕的“三个角度”。在圆形轨道的情况下,万向节锁不是这样的问题。对于一个自由轨道相机,一些更坚固的东西可能是合适的(但你也不能积累四元数-另请参阅stackoverflow.com/questions/319189)。
//To orbit the car (target)
cameraPosition = Vector3.Transform(cameraPosition – target, Matrix.CreateRotationY(0.01f)) + target;
this.ViewMatrix = Matrix.CreateLookAt(cameraPosition, target, Vector3.Up);