如何使用4x4矩阵变换顶点矩阵?

时间:2020-08-31 15:12:34

标签: c++ geometry linear-algebra eigen

我有一个MatrixXd输入,其中每个代表一个顶点。我需要输入Matrix4d transform (变换)来对所有这些顶点进行变换

int main(int argc, char** argv)
{
    double arrVertices[] = {
        -1.0 , -1.0 , -1.0 ,
        1.0 , -1.0 , -1.0 ,
        1.0 , 1.0 , -1.0 ,
        -1.0 , 1.0 , -1.0 ,
        -1.0 , -1.0 , 1.0 ,
        1.0 , -1.0 , 1.0 ,
        1.0 , 1.0 , 1.0 ,
        -1.0 , 1.0 , 1.0
    };

    double arrTransformation[] = {
        0.85656139265934328,
        -0.43936858626129838,
        -0.27066182961813096,
        0.00000000000000000,
        0.51460157667407691,
        0.76645256154673991,
        0.38436400479622890,
        0.00000000000000000,
        0.038571983226693918,
        -0.46851437150336084,
        0.88261344075692039,
        0.00000000000000000,
        3.8451662635348320,
        -11.029392777345908,
        19.898165291232520,
        1.0000000000000000
    };

    Eigen::MatrixXd vertices = Eigen::Map<Eigen::Matrix<double, 8, 3>>(arrVertices);
    Eigen::Matrix4d transformation = Eigen::Map<Eigen::Matrix<double, 4, 4>>(arrTransformation);

    for (int i = 0; i < vertices.rows(); ++i) {
        vertices.row(i) = transformation * vertices.row(i); // This causes "INVALID_MATRIX_PRODUCT"
    }
}

1 个答案:

答案 0 :(得分:1)

从对矩阵的描述来看,您似乎正在尝试将affine transform(旋转+平移)应用于一组顶点。我鼓励您阅读上面或this one链接中的数学解释,但这是一个快速的TLDR:

您的变换矩阵不仅仅代表 linear 变换。线性变换(例如,旋转 R )由3x3矩阵表示。您可以将3D顶点 v 乘以3x3矩阵,以获得变换后的顶点,例如 v' = < em> R v

在这里您要应用两个变换:旋转 R (3x3矩阵)和平移 t ,即您想要 v' = R v + < strong> t

在许多计算机图形应用程序中,这种转换是represented in a 4x4 matrix,其中

  • 前3x3个元素是旋转矩阵
  • 最后一列是翻译向量
  • 最后一行是[0,0,0,1]

这正是矩阵的结构:

 0.856561  0.514602  0.038572   3.84517
-0.439369  0.766453 -0.468514  -11.0294
-0.270662  0.384364  0.882613   19.8982
        0         0         0         1

如果将此4x4变换矩阵与顶点相乘,则算术运算会成功。这不适用于3D顶点本身(您无法将4x4矩阵与3D向量相乘)。要使该技巧起作用,您需要在第4个坐标上添加1(这称为homogenous coordinates;您可以尝试检查一下数学运算是否能完成旋转和平移。)

幸运的是,Eigen中有一个Transform类可以为您完成此任务。您需要从4x4矩阵创建一个Transform并直接乘以3D向量(它在引擎盖下进行同构坐标转换)。请注意,您需要将顶点放在列中才能使用,因此我们将转置矩阵。

 Eigen::Matrix<double,8, 3> vertices = Eigen::Map<Eigen::Matrix<double, 8, 3>>(arrVertices);
 Eigen::Matrix4d transformation_matrix = Eigen::Map<Eigen::Matrix<double, 4, 4>>(arrTransformation);

 // Create a 3D affine transform
 Eigen::Transform<double, 3, Eigen::Affine> transform(transformation_matrix);
 // Transpose the vertices to put them in columns and transform them :
 cout << transform * vertices.transpose() << endl;