【问题标题】:Extract 3x3 rotation matrix from model matrix for OBB从 OBB 的模型矩阵中提取 3x3 旋转矩阵
【发布时间】:2016-04-06 03:48:32
【问题描述】:

我正在尝试通过使用 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 变换矩阵的最佳方法是什么,留下平移和缩放?

【问题讨论】:

    标签: c++ math matrix glm-math


    【解决方案1】:

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

    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;
    

    结果:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-19
      相关资源
      最近更新 更多