要从矩阵中删除比例,您必须将有关缩放的信息存储在某种向量中。
Mcurr = Mscale * Mprev
Mscale_inv = Mscale^(-1)
Mprev2 = Mscale_inv * Mcurr
使用此向量构建原始比例矩阵并将其反转。比将它乘以您拥有的矩阵,您将获得无需缩放的矩阵。
Mprev = {{ X, X, X, Y },
{ X, X, X, Y },
{ X, X, X, Y },
{ Y, Y, Y, Y }};
翻译值不难删除,只需使用您获得的前 3 行和 3 列齐次矩阵。上面的 preudocode 显示了我们为构建仅旋转矩阵而获得的矩阵值。
在这里我发布代码以在我自己的线性代数库上显示比例删除(抱歉不能在 glm 上显示,但我确信有方法可以用 glm 做到这一点):
float identity[] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
float scale[] = {
2.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 2.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
Common::Math::CMatrix4X4 identityM(identity);
std::cout << "Original matrix:\n" << identityM << std::endl;
Common::Math::CMatrix4X4 scaleM(scale);
std::cout << "Scale matrix:\n" << identityM << std::endl;
identityM.RotateX(30);
std::cout << "Rotated original matrix:\n" << identityM << std::endl;
Common::Math::CMatrix4X4 currentM = scaleM * identityM;
std::cout << "Current matrix:\n" << currentM << std::endl;
Common::Math::CMatrix4X4 previousM = scaleM.GetInversed() * currentM;
std::cout << "Result matrix:\n" << previousM << std::endl;
结果:
这种情况可以消除矩阵的所有仿射操作,不仅可以缩放,还可以旋转和平移。但是有更快的方法,但只适用于比例变换。
将矩阵减小到 3x3 大小,移除最后一行/列,而不是对结果矩阵的每一行或每一列进行归一化(在这种情况下,您不必存储比例值向量):
float identity[] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
float scale[] = {
2.0f, 0.0f, 0.0f, 0.0f,
0.0f, 2.0f, 0.0f, 0.0f,
0.0f, 0.0f, 2.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
Common::Math::CMatrix4X4 identityM(identity);
std::cout << "Original matrix:\n" << identityM << std::endl;
Common::Math::CMatrix4X4 scaleM(scale);
std::cout << "Scale matrix:\n" << scaleM << std::endl;
identityM.RotateX(30);
std::cout << "Rotated original matrix:\n" << identityM << std::endl;
Common::Math::CMatrix4X4 currentM = scaleM * identityM;
std::cout << "Current matrix:\n" << currentM << std::endl;
Common::Math::CMatrix3X3 rcurrentM(currentM);
std::cout << "Reduced current matrix:\n" << rcurrentM << std::endl;
// normalizing each row
rcurrentM[0].Normalize();
rcurrentM[1].Normalize();
rcurrentM[2].Normalize();
std::cout << "Result matrix:\n" << rcurrentM << std::endl;
结果: