变换矩阵在左右坐标系的转换

疑惑

Max导出的fbx模型文件加载到客户端,对变换矩阵做了如下的转换,把Z-up右手坐标系的变换矩阵换到Y-up左手坐标系的变换矩阵。咋一看相当懵逼~

FORCEINLINE void _DxMatrixToApexMatrix(physx::PxMat44& matrix, const XMFLOAT4X4& xmMatrix)
{
    XMFLOAT4X4 mat = xmMatrix;    

    std::swap(mat._21, mat._31);
    std::swap(mat._22, mat._32);
    std::swap(mat._23, mat._33);
    std::swap(mat._24, mat._34);

    std::swap(mat._12, mat._13);
    std::swap(mat._22, mat._23);
    std::swap(mat._32, mat._33);
    std::swap(mat._42, mat._43);

    memcpy((void*)matrix.front(), &mat._11, sizeof(float) * 16);    
}

坐标系的不同

coordinate

  • max
    max里面是Z朝上的右手坐标系,如图(a)所示.

  • DX11
    客户端用的DX11是Y轴朝上的左手坐标系,如图(b)所示.

坐标系转换

  • 错误的做法
    一开始想的是把Y和Z换一下就好了,那么矩阵里面把第二行和第三行换一下不就行了。代码应该是这样:
FORCEINLINE void _DxMatrixToApexMatrix(physx::PxMat44& matrix, const XMFLOAT4X4& xmMatrix)
{
    XMFLOAT4X4 mat = xmMatrix;    

    std::swap(mat._21, mat._31);
    std::swap(mat._22, mat._32);
    std::swap(mat._23, mat._33);
    std::swap(mat._24, mat._34);

    memcpy((void*)matrix.front(), &mat._11, sizeof(float) * 16);    
}

结果为什么还要换一下第二列和第三列呢?
把Y和Z换一下这个是对的,比如一个向量(x, y, z)变成(x, z, y)。但是,变换矩阵却不能这样操作!我的理解是,矩阵里面有旋转、缩放、平移,针对的是模型上的所有点。只换第二行和第三行是包括了部分缩放和旋转信息,最后对模型上点进行转换的时候都不知道结果是什么。

  • 验证
    假设在Z-up右手坐标系有一个点P ( x , y , z ) (x, y, z) ,和这个点的变换矩阵:
    M = [ m 11 m 12 m 13 m 14 m 21 m 22 m 23 m 24 m 31 m 32 m 33 m 34 m 41 m 42 m 43 m 44 ] M = \begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34} \\ m_{41} & m_{42} & m_{43} & m_{44} \\ \end{bmatrix}
    算一下点P在Z-up右手坐标系变换后的点,和点P1在Y-up左手坐标系变换后的点是不是依旧是同一个点!其中P1=(x, z, y)

注意:在Y-up的变换矩阵下P也应该在该坐标系下面,即P1 = (x, z, y)

(1)点P在Z-up右手坐标系变换之后的点为:PM
P M = ( x , y , z ) M = ( x m 11 + y m 21 + z m 31 + m 41 , x m 12 + y m 22 + z m 32 + m 42 , x m 13 + y m 23 + z m 33 + m 43 ) P*M = (x, y, z)M = (xm_{11}+ym_{21}+zm_{31}+m_{41}, xm_{12}+ym_{22}+zm_{32}+m_{42}, xm_{13}+ym_{23}+zm_{33}+m_{43})
(2)点P在错误的Y-up左手坐标系变换之后的点为:P1
M1
M 1 = [ m 11 m 12 m 13 m 14 m 31 m 32 m 33 m 34 m 21 m 22 m 23 m 24 m 41 m 42 m 43 m 44 ] M1 = \begin{bmatrix} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{31} & m_{32} & m_{33} & m_{34} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{41} & m_{42} & m_{43} & m_{44} \\ \end{bmatrix}
P 1 M 1 = ( x , z , y ) M 1 = ( x m 11 + z m 31 + y m 21 + m 41 , x m 12 + z m 32 + y m 22 + m 42 , x m 13 + z m 33 + y m 23 + m 43 ) P1*M1 = (x, z, y)M1 = (xm_{11}+zm_{31}+ym_{21}+m_{41}, xm_{12}+zm_{32}+ym_{22}+m_{42}, xm_{13}+zm_{33}+ym_{23}+m_{43})
(3)点P在正确的Y-up左手坐标系变换矩阵变换之后的嗲哪位:P1*M2
M 2 = [ m 11 m 13 m 12 m 14 m 31 m 33 m 32 m 34 m 21 m 23 m 22 m 24 m 41 m 42 m 43 m 44 ] M2 = \begin{bmatrix} m_{11} & m_{13} & m_{12} & m_{14} \\ m_{31} & m_{33} & m_{32} & m_{34} \\ m_{21} & m_{23} & m_{22} & m_{24} \\ m_{41} & m_{42} & m_{43} & m_{44} \\ \end{bmatrix}
P 1 M 2 = ( x , z , y ) M 2 = ( x m 11 + z m 31 + y m 21 + m 41 , x m 13 + z m 33 + y m 23 + m 43 , x m 12 + z m 32 + y m 22 + m 42 ) P1*M2 = (x, z, y)M2 = (xm_{11}+zm_{31}+ym_{21}+m_{41}, xm_{13}+zm_{33}+ym_{23}+m_{43}, xm_{12}+zm_{32}+ym_{22}+m_{42})

小结:
(1)可以看到,PM和P1M2的结果换一下Y和Z轴就是一样的,这也说明M2才是正确的变换矩阵!
(2)同时,可以看到P1M1的结果和PM的结果是一样的,这就奇怪了,P1在Y-up左手坐标系用这个矩阵变换后又回到了Z-up右手坐标系里面的坐标(等于没有变换了)

原理

参考[1]中给出了说明,翻译一下如下:

M_YZ右手 = ...// 变换YZ坐标得到在Z-up右手坐标系的点
M_YZ左手 = 求逆(M_YZ右手)  // 变换YZ坐标重新得到在Y-up左手坐标系的坐标
M右手 = ...  // 在Z-up右手坐标系下的一个变换矩阵
M左手 = M_YZ右手 * M右手 * M_YZ左手

简单说明一下:

  • 理解上就是不能在不同的坐标系下面矩阵变换。现在是已知在Z-up下面的变换矩阵,求在Y-up下面的变换矩阵。那么就先把点变换到Z-up右手坐标系中,进行矩阵变换,得到点在Z-up右手坐标系新的位置,然后再把这个点换YZ坐标重新得到在Y-up左手坐标系的坐标。

  • M_YZ右手指的是在Z-up右手坐标系里面的把Y和Z换一下,也就是把Z-UP右手坐标系里面的点变换到了Y-up左手坐标系里面的点
    M Y Z R i g h t = [ 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 ] M_{YZ-Right} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 &1 \\ \end{bmatrix}

  • M_YZ左手是相反的操作,其实就是M_YZ右手的逆矩阵,而这里两者是相等的,简单验证就是 M Y Z L e f t M Y Z R i g h t 1 M_{YZ-Left} * {M_{YZ-Right}}^{-1} 为单位矩阵
    M Y Z L e f t = M Y Z R i g h t 1 = [ 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 ] M_{YZ-Left} = {M_{YZ-Right}}^{-1} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 &1 \\ \end{bmatrix}

结论

  • 数学大法好啊

参考

[1]Changing a matrix from right-handed to left-handed coordinate system

发布了41 篇原创文章 · 获赞 7 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/pkxpp/article/details/100109480
今日推荐