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



我有一个MatrixXd的输入,其中每个代表一个顶点。我需要用Matrix4d变换的输入来转换所有这些顶点。

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"
}
}

从矩阵的描述来看,您似乎正在尝试对一组顶点应用仿射变换(旋转+平移(。我鼓励你阅读上面或这个链接中的数学解释,但这里有一个快速的TLDR:

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

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

在许多计算机图形学应用中,这种变换用4x4矩阵表示,其中

  • 前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变换矩阵与顶点相乘,数学运算就会出来。这对三维顶点本身不起作用(不能将4x4矩阵与三维向量相乘(。为了使技巧发挥作用,你需要添加一个1作为第4个坐标(这被称为齐次坐标;你可以尝试检查数学,看看它能完成旋转和平移。(

幸运的是,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;

相关内容

  • 没有找到相关文章

最新更新