我刚开始学习 DirectX。目前我有一个立方体和一个相机,我可以通过球体在立方体周围移动。
但现在我想创建一个功能,这样我就可以稍微转动我的相机(左/右/上/下)。我很容易理解如何在 2D 中制作它:我可以在 LookAt 函数中更改 X 和 Y,它就完成了。我怎么能做同样的事情,但在 3D 中?有3个维度,我的相机可以拍摄任何角度......
我想我需要找到一个垂直于相机矢量的平面并像处理 2D 一样处理它。图片
或者我可以更容易地做到这一点?
视图转换是一个棘手的问题。通常,您有模型转换,例如移动、旋转或缩放对象(世界转换)。
但是,视图转换是一种系统转换。我们可以将其想象为将相机从其位置移动到原点的模型转换。当然,看逆视图变换更容易。将相机放置在其位置的那个。
这就是我们要做的。假设我们有一个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
方法设置视图矩阵。LookAt
再次使用该方法。如果您想调高和调低,请使用XMMatrixRotationX
. 如果要左转和右转,请使用XMMatrixRotationY
. XMMatrixRotationZ
会导致滚动。
对于相机旋转,使用D3DXMatrixLookAtLH方法。您的问题是关于如何计算眼睛所需的“at”或“target”。这个 Vector3 是使用 2D 中使用的相同三角方法计算的,但只是增加了一个维度。您需要一个 Vector3 进行旋转,其每个组件都将围绕该轴旋转。然后使用以下方法将您的旋转应用于使用前面提到的方法创建的矩阵。
要对世界中的对象执行相同的操作,请根据您的旋转方向使用 DirectX 方法D3DXMatrixRotation(X,Y,Z) 。在正确定向的世界中,左右将围绕 Y 轴旋转,上下将围绕 X 轴旋转,并且将围绕 Z 轴进行倾斜。当然,这适用于矩阵旋转,而不是四元数。
记住在执行旋转(或任何操作操作)时要记住操作顺序(ISROT):
这样,您最终就不会发生看似时髦的事情。还要考虑D3DXMatrixYawPitchRoll方法。
首先,你应该阅读这个问题。
基本上,矩阵是一个坐标系,包含 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;
}
对于相机,x
和y
的z
长度1.0
应该是 并且应该相互垂直。
这些例程是 DirectX 特定的,并假设(查看)矩阵是左撇子。
要将相机移动到“右侧”,您需要将矩阵分解为组件,将“x”添加到“pos”并再次构建它。如果您坚持使用“查看”,那么您必须在“查看位置”和“查看位置”中添加“x”。