我有一个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"
}
}
答案 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,其中
这正是矩阵的结构:
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;