以3维计算相机LookAt位置(DirectX)

时间:2013-10-02 17:09:25

标签: c++ math 3d directx

我刚开始学习DirectX。目前我有一个立方体和一个相机,我可以通过球体在立方体周围移动。

但是现在我想要创建一个功能,这样我可以稍微转动相机(左/右/上/下)。我很容易理解如何在2D中制作它:我可以在LookAt函数中更改X和Y并完成它。我怎么能在3D中做同样的事情?有3个尺寸,我的相机可以采取任何角度...

我想我需要找到一个垂直于相机矢量的平面,并像2D一样处理它。 Image

或者我可以更轻松地做到这一点?

3 个答案:

答案 0 :(得分:0)

对于相机旋转,请使用D3DXMatrixLookAtLH方法。您的问题是如何计算眼睛所需的“at”或“target”。此Vector3使用2D中使用的相同trig方法计算,但仅使用额外维度。您需要一个Vector3进行旋转,其中每个组件都将围绕该轴旋转。然后使用以下方法将旋转应用于使用前面提到的方法创建的矩阵。

要在您的世界中的对象上执行相同的操作,请根据您的旋转方向使用DirectX方法D3DXMatrixRotation(X,Y,Z)。在正确定向的世界中,左右将围绕Y轴旋转,上下将围绕X轴旋转,并且将围绕Z轴进行倾斜。当然,这是矩阵旋转,而不是四元数。

记住执行旋转(或任何操作操作)以记住操作顺序(ISROT)时:

  • 牙齿
  • S cale
  • R otation
  • O rbit
  • T 翻译

这样你就不会有看似时髦的东西。另请考虑D3DXMatrixYawPitchRoll方法。

答案 1 :(得分:0)

首先,你should read this question

基本上,矩阵是一个包含x,y,z向量和系统位置的坐标系(在父系统的坐标内)。因此,您可以拆分矩阵,修改向量,并重新生成矩阵,而无需使用任何“LookAt”例程。但重要的是,如果在此时放置了一个物体而不是相机,则相机矩阵(视图变换)是物体矩阵(世界变换)的反转。但是,由于相机矩阵具有特殊属性(轴是垂直的并且是正常的单位长度),因此您可以简单地转置它并重新计算矩阵的“位置”部分。

我的这个旧功能将从矢量集构建相机矩阵(“视图”变换或D3DTS_VIEW)。 x点向右,y向上,z向前,pos是相机位置。

typedef D3DXVECTOR3 Vector3;
typedef D3DXMATRIX Matrix;

void vecToCameraMat(Matrix& m, const Vector3& x, const Vector3& y, const Vector3& z, const Vector3& pos){
    m._11 = x.x;
    m._12 = y.x;
    m._13 = z.x;
    m._14 = 0;

    m._21 = x.y;
    m._22 = y.y;
    m._23 = z.y;
    m._24 = 0;

    m._31 = x.z;
    m._32 = y.z;
    m._33 = z.z;
    m._34 = 0;

    m._41 = - (pos.x*x.x + pos.y*x.y + pos.z*x.z);//(pos.x*x.x + pos.y*y.x + pos.z*z.x);
    m._42 = - (pos.x*y.x + pos.y*y.y + pos.z*y.z);
    m._43 = - (pos.x*z.x + pos.y*z.y + pos.z*z.z);
    m._44 = 1;
}

将相机矩阵解构为向量:

void cameraMatToVec(Vector3& x, Vector3& y, Vector3& z, Vector3& pos, const Matrix& m){
    x.x = m._11;
    y.x = m._12;
    z.x = m._13;

    x.y = m._21;
    y.y = m._22;
    z.y = m._23;

    x.z = m._31;
    y.z = m._32;
    z.z = m._33;

    pos.x = -(m._41*x.x + m._42*y.x + m._43*z.x);
    pos.y = -(m._41*x.y + m._42*y.y + m._43*z.y);
    pos.z = -(m._41*x.z + m._42*y.z + m._43*z.z);
}

这将使用类似的矢量集构建OBJECT矩阵(即“世界”变换或D3DTS_WORLD)。

void vecToMat(Matrix& m, const Vector3& x, const Vector3& y, const Vector3& z, const Vector3& pos){
    m._11 = x.x;
    m._12 = x.y;
    m._13 = x.z;
    m._14 = 0;

    m._21 = y.x;
    m._22 = y.y;
    m._23 = y.z;
    m._24 = 0;

    m._31 = z.x;
    m._32 = z.y;
    m._33 = z.z;
    m._34 = 0;

    m._41 = pos.x;
    m._42 = pos.y;
    m._43 = pos.z;
    m._44 = 1;
}

将“对象”矩阵解构为向量集:

void matToVec(Vector3& x, Vector3& y, Vector3& z, Vector3& vpos, const Matrix& m){
    x.x = m._11;
    x.y = m._12;
    x.z = m._13;

    y.x = m._21;
    y.y = m._22;
    y.z = m._23;

    z.x = m._31;
    z.y = m._32;
    z.z = m._33;

    vpos.x = m._41;
    vpos.y = m._42;
    vpos.z = m._43;
}

对于相机,xyz的长度应为1.0,并且应该相互垂直。

这些例程是DirectX特定的,并假设(视图)矩阵是左撇子。

要将摄像机移动到“右侧”,您需要将矩阵分解为组件,将“x”添加到“pos”并再次构建它。如果你坚持使用“look at”,那么你必须在“view position”和“look at position”中添加“x”。

答案 2 :(得分:0)

视图转换是一个棘手的问题。通常,您有模型转换,例如,移动,旋转或缩放对象(世界变换)。

但是,视图转换是系统转换。我们可以把它想象成一个模型转换,将相机从其位置移动到原点。当然,查看逆视图转换更容易。将相机放在其位置的那个。

这就是我们要做的。假设我们有一个转换M来定位相机。相应的视图转换是反向的:V = M^(-1)。如果要旋转相机对象,只需将旋转矩阵乘以模型转换:

M' = R * M

在应用M后,这会将相机旋转到其位置。相应的视图转换仍然是相反的。将反向应用于M'会产生

V' = (M')^(-1) 
   = (R * M)^(-1)
   = M^(-1) * R^(-1)

我们看到M^(-1)是旧视图转换。因此:

V' = V * R^(-1)

因此,如果要旋转相机,请将旋转矩阵(负角度)乘以当前视图矩阵的右侧。

所以工作流程如下:

  • 在游戏开始时,使用LookAt方法设置视图矩阵。
  • 每次玩家旋转相机时,将旋转矩阵乘以当前视图矩阵。确保角度不要太大。如果你每帧旋转10°,那么在60 fps一秒后你已经有600 *。
  • 每当您想要重置相机时,请再次使用LookAt方法。

如果您想要上下翻转,请使用XMMatrixRotationX。如果要左右转,请使用XMMatrixRotationYXMMatrixRotationZ会导致滚动。