我正在尝试通过使用 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;
结果:
这种情况可以消除矩阵的所有仿射操作,不仅可以缩放,还可以消除旋转和平移。但是还有更快速的方法,但只适用于尺度转换。
将矩阵缩小到 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;
关于c++ - 从 OBB 的模型矩阵中提取 3x3 旋转矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34558844/