1

我正在尝试使用四元数在两个三角形之间实现形状插值,正如Alexa、Cohen-Or 和 Levin在 2000 年的论文As-rigid-as-possible shape interpolation中所讨论的那样。

假设三角形 1 有点 A、B、C,三角形 2 有点 M、N、O。两个对应的矩阵(分别为 T1 和 T2)如下:

T1 = {A.x, B.x, C.x},
     {A.y, B.y, C.y},
     {1,   1,   1  }

T2 = {M.x, N.x, N.x},
     {M.y, N.y, N.y},
     {1,   1,   1  }

然后我取 T1 的倒数并乘以 T2 以执行奇异值分解以获得矩阵 SVD,以找到旋转和缩放矩阵。

Eigen::Matrix3f A = T1.inverse().eval() * T2;
Eigen::JacobiSVD<MatrixXf> SVD;
SVD.compute(A, ComputeFullU | ComputeFullV);
Eigen::MatrixXf D = SVD.singularValues().asDiagonal().toDenseMatrix();
Eigen::Matrix3f rotationMatrix = SVD.MatrixU() * SVD.MatrixV();
Eigen::Matrix3f sMatrix = SVD.MatrixV() * D * SVD.MatrixV().transpose();
Eigen::Quaternionf quat = rotationMatrix;

然后我使用这个四元数和 sMatrix 进行插值。注意:计时器从 0.0f 开始并增加 0.0001f(一些小常数)直到达到 1.0f。动画转换。

Eigen::MatrixXf Rtime = (Quaternionf::Identity().slerp(timer, quat)).toRotationMatrix();
MatrixXf Stime = MatrixXf::Identity(3, 3) * (1 - timer) + sMatrix * timer;
Eigen::MatrixXf A = Rtime * ((1 - timer) * MatrixXf::Identity(3, 3) + timer * Stime);

然后我将原始三角形的每个点 P 转换为它自己的 3x1 向量并乘以 A。

Eigen::Vector3f v;
v(0) = P.x;
v(1) = P.y;
v(2) = 1;
v = At * v;

最后,我在新的 v(0) 和 v(1) 处画一个点,然后对三角形的其他两个顶点重复此操作。

当计时器非常小时(接近 0)时,当我在原始三角形 (T1) 的位置得到一个新三角形时,随着计时器的增加,新三角形会缩放并从 T1 平移,但不会移向最终三角形(T2)。

如果我只使用通过取 T1.inverse() 并乘以 T2 计算的矩阵,线性插值似乎有效。所以,我认为我的问题在于 slerp 或 SVD 的实施,但我不确定。

还有什么我应该包括的内容有助于确定我出错的地方吗?

编辑:添加时间矩阵,在 V 矩阵上切换转置调用。

4

0 回答 0