我正在尝试使用四元数在两个三角形之间实现形状插值,正如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 矩阵上切换转置调用。