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

标签 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 变换矩阵而留下平移和缩放的最佳方法是什么?

最佳答案

要从矩阵中移除尺度,您必须存储关于某种 vector 尺度的信息。

Mcurr = Mscale * Mprev

Mscale_inv = Mscale^(-1)

Mprev2 = Mscale_inv * Mcurr 

然后使用此 vector 构建原始比例矩阵并将其反转。将它乘以你拥有的矩阵,你将得到没有缩放你不想拥有的矩阵。

Mprev = {{ X, X, X, Y },
         { X, X, X, Y },
         { X, X, X, Y },
         { Y, Y, Y, Y }};

不难删除的翻译值只需使用您获得的齐次矩阵的前 3 行和 3 列。上面的 preudocode 显示“X”是我们为构建仅旋转矩阵而获得的矩阵值。

我在这里发布代码以在我自己的线性代数库上显示比例删除(抱歉不能在 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;

结果:

enter image description here

这种情况可以消除矩阵的所有仿射操作,不仅可以缩放,还可以消除旋转和平移。但是还有更快速的方法,但只适用于尺度转换。

将矩阵缩小到 3x3 大小,删除最后一行/列,而不是对结果矩阵的每一行或列进行归一化(在这种情况下,您不必存储比例值 vector ):

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

关于c++ - 从 OBB 的模型矩阵中提取 3x3 旋转矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34558844/

相关文章:

python - 用于稀疏矩阵计算的 Scipy 或 Pandas?

math - 计算 LookAt 矩阵

c++ - 将类分离到它们自己的定义和实现文件中,并将 main 放在它自己的文件中

c++ - Linux C++ 文件权限被拒绝

c++ - 从 C++ QStateMachine 控制 QML UI

python - 四舍五入到列表中最接近的数字

javascript - 获取相机当前的旋转 Angular

javascript - 如何从数组值中删除逗号?

python - 硬编码 6x6 numpy 矩阵的简单方法是什么?

c++ - 为什么指针可以避免 warnary-bounds