在d3d中默认使用左手系坐标,其实就是在生成变换矩阵时,习惯使用带有LH后缀的函数,如LookAtLH、PerspectiveFovLH等。但是大部分编辑器(如Maya)使用的是右手系坐标,所以会在导入相关模型的时候转换到左手系。但这样会导致应用程序空间和编辑器控件不一致,写程序时非常麻烦。
我这边决定直接使用右手系坐标,终结下需要注意的事项:
模型空间
如果使用的模型是左手系空间的,则需要对定点、法线等数据的 z 值取反,但是Maya默认使用右手系,则在导入时可以将数据原封不动的装入
Culling Mode
理论上,右手系空间应当使用逆时针顺序(CCW,counterclockwise)作为三角形的正面,但是这也可以取决于编辑器,如Maya使用顺时针,那也以可直设置成CW模式
View空间
View空间右可理解为相机空间,这里要注意的是左手系的View空间是 Z 轴向外,而右手系则是 Z 轴向内(即正 Z 轴方向与相机相反),所以在生成 uvn 矩阵的时候要注意
n=normalize(eye - at),参见 D3DXMatrixLookAtRH
Vector3 zaxis = (eye - at).normalize(); Vector3 xaxis = up.cross(zaxis).normalize(); Vector3 yaxis = zaxis.cross(xaxis); return Matrix4( xaxis.x, yaxis.x, zaxis.x, 0, xaxis.y, yaxis.y, zaxis.y, 0, xaxis.z, yaxis.z, zaxis.z, 0, -xaxis.dot(eye), -yaxis.dot(eye), -zaxis.dot(eye), 1);
Projection空间
既然右手系中 Z 轴与相机正方向相反,那么这里的 Near Z、Far Z 的理解就不同了,由于通常 Near Z、Far Z 描述成正值,那么在求解透视矩阵时,就要对其反向处理(这一点和左手系是不同的),参见 D3DXMatrixPerspectiveFovRH
float yScale = cot(fovy / 2); float xScale = yScale / aspect; return Matrix4( xScale, 0, 0, 0, 0, yScale, 0, 0, 0, 0, zf / (zn - zf), -1, 0, 0, zn * zf / (zn - zf), 0);