D3DXMatrixLookAtLH视图变换函数详解

本文深入探讨了D3DXMatrixLookAtLH函数在三维空间变换中的作用,详细解释了如何使用此函数创建世界到视图变换矩阵,包括坐标系转换、矩阵构成原理以及参数意义。文章还提供了原型说明和实例代码,帮助开发者正确地应用此函数进行场景观察和物体定位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*D3DXMatrixLookAtLH函数返回的是世界->视图变换矩阵。

视图坐标系和局部坐标系是一样的,都是世界坐标系转换为指定的局部坐标系,从局部点到世界点需要先缩放旋转后平移Mx*My*Mz*P的变换矩阵,而从世界点到局部点要进行先平移后旋转缩放的逆过程P-1Mz-1My-1Mx-1的变换矩矩阵(PMzMyMx是重用局部点到世界的变换).

矩阵是重新分解和组合空间位置和方位的空间变换过程;

矩阵行是新坐标系的基向量或表示平移,用变换后的向量在原坐标系各轴分解得的向量表示;

矩阵列是对应原坐标系的各轴,是各新基向量在列对应原坐标系的轴上的累积(组合)向量。

*/

 D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);//camera在世界坐标系中的位置向量

 D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);//target是camera的朝向向量,可以是原点,也 可以是其它观察点

 D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);//定义向上的方向,一般是[0,1,0]

  D3DXMATRIX V;

 D3DXMatrixLookAtLH(&V, &position, &target, &up);//V是world-to-view空间的变换矩阵,是view-to-world空间变换矩阵的逆矩阵

 Device->SetTransform(D3DTS_VIEW, &V);//设置变换的状态,实际变换时,先得到变换矩阵,然后才将相机内的物体乘以变换矩阵

原型:

D3DXMATRIX* D3DXMatrixLookAtLH(
  _Inout_       D3DXMATRIX  *pOut,
  _In_    const D3DXVECTOR3 *pEye, // 视图坐标系中新的观察点的位置(可以解释为新的摄像机位置from)
  _In_    const D3DXVECTOR3 *pAt, // 观察目标原来所在的世界坐标系的位置(变换时需要camera观察点平移旋转到该点),一般是(0,0,0)或者原来世界坐标系位置(观察目标位置)(可以解释为变换后的摄像机平移旋转到的位置to,世界物体根据新的观察坐标系进行参考定位)
  _In_    const D3DXVECTOR3 *pUp // 向上的方向,一般是(0,1,0)
);

返回的新坐标系是:

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)
    
 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1

视图变换矩阵是用视图坐标系来观察世界坐标系。所以是将物体在世界坐标系中旋转平移(视图转换不包含缩放要缩放在世界中进行)变换后的逆变换,也就是R*T矩阵的逆矩阵。

/*因为矩阵的行是用旧坐标描述的新坐标系的基向量,所以新的基向量就是物体旋转变换,而平移也是用旧坐标系描述的,所以平移时的xaxis, yaxis, zaxis应该是旧坐标系的原始轴(一个原因是两个向量描述的位置应该是基于相同的参考坐标系,另一个是新的坐标系是基于旧的坐标系描述的旋转和

平移都是基于相同的旧坐标系进行的)。

dot(xaxis, eye) = |xaxis|*|eye|*cos theta = |eye|*cos theta, 刚好是得到基于旧坐标系的位移,求逆则转换到从视图坐标系作为参考原点。

*/

上述注释部分为臆断思考,感觉很有道理,但是是错误的结果。


由于单位向量是标准正交基,那么求这个矩阵的只要求它的转置矩阵即可。
将平移和旋转部分合并起来就是视图变换矩阵,如下:
1   0   0   0      rx  ux  dx  0    rx    ux   dx   0
0   1   0   0   *  ry  uy  dy  0  = ry    uy   dy   0
0   0   1   0      rz  uz  dz  0    rz    uz   dz   0
-px -py -pz 1      0   0   0   1    -pr   -pu  -pd  1

R*T矩阵的逆矩阵,是T^-1 * R^-1,所以得到变换结果和D3D文档中描述是一致的。

复杂的变换,是不能够分开考虑臆断思考的,而是应该用公式来推导,叫做基于旧坐标轴连续变换。


从变换来求取变换矩阵,欧拉角,或四元数,首先需要明天矩阵,欧拉角,四元数的含义。然后用它们来描述人类理解的变换,对于矩阵变换的求取:1)用变换前坐标系作为参考坐标系,先取得一个变换前向量,然后取得一个变换后向量。

2)通过相对于参考坐标系数值不变;数值对称取反;作垂线平分线于参考坐标系,假设转换为已知坐标轴关系例如旋转基向量求取;通过向量的点积投影和叉乘法向量,三角关系sin theta,cos theta 关系,来求得变换后向量用变换前向量表示的推导公式。

3)因为矩阵的行是用旧坐标系表示的基向量(由原来对应的基向量变换而来,且用原来三个轴值表示);矩阵的列被解释为原来各旧轴对于旧轴上定义的顶点的重新分解组合权重向量。所以用旧轴上的基向量分别进行2)中的推导公式计算作为新坐标系基向量,即可。

欧拉角直接相对于x,y,z轴分别旋转,然后转换为四元数即可;四元数作为自己的旋转乘法计算实现变换。

一般描述旋转:直接矩阵;欧拉角转换为四元数,四元数转换为矩阵;直接图形工具导出四元数,四元数实现快速变换,结果转换为矩阵。或者欧拉角输入变换为矩阵矩阵实现旋转。

平移直接用矩阵或者向量即可。

缩放(镜像切变)及投影直接用矩阵来实现即可。

记得这些变换在同一个坐标系中,特别是子节点-父节点(物-世界)如果都是相对于父节点刻画的,那么都需要先进行缩放->旋转->平移实现变换。如果是父节点-子节点(世界-物体)变换,那么需要进行子节点-父节点变换的逆来实现。单纯的变换坐标系来实现变换物体仅是理论上的。


// 注意到平移是各个方向上都求了逆,旋转是旋转物体的逆矩阵也就是实现坐标系变换,用新的坐标系描述所有物体。

参考:http://msdn.microsoft.com/zh-cn/library/windows/desktop/bb205342%28v=vs.85%29.aspx


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值