我正在尝试使用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变换矩阵的最佳方法是什么,留下翻译和缩放?
答案 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;
结果:
这种情况可以消除你的矩阵的每一个仿射操作,不仅缩放,而且旋转和平移。但是有更快的方法,但只适用于规模转换。
将矩阵减少到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;