从OBB的模型矩阵中提取3x3旋转矩阵

时间:2016-01-01 18:31:57

标签: c++ math matrix glm-math

我正在尝试使用4个点的列表构建平面形状的3D OBB,如下所示:

    glm::vec3 = plane.getPosition();
    glm::vec3 points[ 4 ]={ 
        p+glm::vec3( -c->getWidth()*0.5f,0.0f,-c->getLength()*0.5f), //left front
        p+glm::vec3(-c->getWidth()*0.5f,0.0f,c->getLength()*0.5f),  //left back
        p+glm::vec3( c->getWidth()*0.5f,0.0f,-c->getLength()*0.5f),   //right front
        p+glm::vec3( c->getWidth()*0.5f,0.0f,c->getLength()*0.5f),  //right back

哪个工作正常。然而,将点旋转到形状所代表的对象的方向是困难的,因为mat4变换包含缩放信息,其放大了框的尺寸,导致碰撞检测系统中的空洞。

从原始mat4变换矩阵中提取3x3变换矩阵的最佳方法是什么,留下翻译和缩放?

1 个答案:

答案 0 :(得分:0)

要从矩阵中删除比例,您必须在某种向量中存储有关缩放的信息。

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显示'X'我们得到的矩阵值,用于构建我们的仅旋转矩阵。

这里我发布代码以显示我自己的线性代数库上的比例删除(抱歉无法显示在glm donot上,但我相信有方法可以用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;

结果:

enter image description here

这种情况可以消除你的矩阵的每一个仿射操作,不仅缩放,而且旋转和平移。但是有更快的方法,但只适用于规模转换。

将矩阵减少到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;

结果: enter image description here

相关问题