代码之家  ›  专栏  ›  技术社区  ›  Drew Noakes

用矩阵变换三维矢量的方法

  •  4
  • Drew Noakes  · 技术社区  · 14 年前

    我一直在读一些关于用矩阵转换向量3的书,并且正在努力深入研究数学,并自己编写代码,而不是使用现有的代码。不管什么原因,我的学校课程从来没有包括矩阵,所以我正在填补我的知识空白。谢天谢地,我想我只需要一些简单的东西。

    上下文是我正在为机器人编程 RoboCup 3D league . 我正在用C编码,但它必须在单声道上运行。理想情况下,我不会为此使用任何现有的图形库(winforms/wpf/xna),因为我真正需要的只是矩阵转换的一个子集。

    具体来说,我需要转换和X/Y/Z旋转,以及将多个转换组合成一个矩阵的方法。这将适用于我自己的 Vector3 键入以生成转换的 矢量3 .

    我读过不同的建议。例如, some 用4x3矩阵对变换建模, others 带4x4矩阵。

    另外,一些例子表明,向量矩阵1需要第四个值。当这个值包含在输出中时会发生什么?

                [1 0 0 0]
    [x y z 1] * [0 1 0 0] = [a b c d]
                [0 0 1 0]
                [2 4 6 1]
    

    我缺少的部分是:

    • 我的矩阵应该有多大
    • 通过将转换矩阵相乘合成转换
    • 用生成的矩阵变换三维矢量

    因为我只想运行这个程序,任何psuedo代码都是很好的。关于什么矩阵值执行什么转换的信息在许多页面上都有很清楚的定义,因此不需要在这里讨论,除非您非常热心:)

    1 回复  |  直到 14 年前
        1
  •  6
  •   Drew Noakes    14 年前

    3x 3矩阵可以编码诸如旋转和反射之类的转换,但不能编码转换。为此,需要添加第四个元素,并用 homogenous coordinates . 为了某些目的,可以使用非方形矩阵,但是如果您想以任何顺序组合它们,它们应该是方形的(因为如果第一个矩阵中的列数等于第二个矩阵中的行数,则只能将两个矩阵相乘)。

    因此,为了您的目的,您应该使用4x4矩阵和4元素同质向量,添加第四个 W 与值1协调。

    将一个变换应用到一组向量上只是一个乘法问题。

    传统上,向量表示为 columns 矩阵在左边。你在上面把它们表示为 rows 在右边乘。两者都是有效的,但是转换矩阵需要在两种情况之间进行转置。您显示的矩阵底部有翻译值,这与您的乘法顺序是正确的。

    向量转换后,需要除以 W 坐标与比例 x,y Z 回到传统的3空间。

    在C-ISH伪代码中,使用行向量约定:

    Vector transform (Vector v, Matrix m)
    {
        Vector result;
        for ( int i = 0; i < 4; ++i )
           result[i] = v[0] * m[0][i] + v[1] * m[1][i] + v[2] + m[2][i] + v[3] * m[3][i];
        result[0] = result[0]/result[3];
        result[1] = result[1]/result[3];
        result[2] = result[2]/result[3];
        return result;
    }
    

    转换序列可以通过将每个矩阵依次相乘而组成。注意,矩阵乘法是 非交换的 ,所以乘法的顺序很重要。反过来,这意味着无论您是在左边乘以行向量还是在右边乘以列向量都很重要。如果你乘法 X X C ,然后使用与执行转换相同的列向量 C 首先,然后 然后最后 . 对于行向量,它是 首先,然后 然后 C . 因此,在构造、组成和应用转换时,保持所有内容的一致性是很重要的。

    同样,在伪代码中应该与 transform 以上:

    Matrix compose (Matrix first, Matrix second)
    {
        Matrix result;
        for ( int i = 0; i < 4; ++i )
            for ( int j = 0; j < 4; ++j )
                result[i][j] = first[i][0] * second[0][j]
                               + first[i][1] * second[1][j]
                               + first[i][2] * second[2][j]
                               + first[i][3] * second[3][j];
        return result;
    }