如何将右手XYZ坐标系中定义的网格转换为左手XZY

时间:2017-02-05 12:19:04

标签: opengl matrix mesh coordinate-systems

我需要一种传递给这些坐标系的方法,但我在努力学习数学。

基本上我有一个为“OpenGL”创建的网格,所以右手XYZ坐标系,我想在不同的环境(虚幻引擎4)中加载它,它使用左手XZY坐标系。 / p>

现在,以原始状态为例,以此网格为例: enter image description here

如果加载它会保留所有顶点,我得到这个: enter image description here

如果你仔细观察,你会发现它是“镜像的”,蜘蛛的左腿与右边的腿交换。此外,在图像不是很清楚,但深度是关闭的,我可以看到蜘蛛“内部”(如果你注意到,眼睛因此缺失)。

现在,如果我用-Y交换每个顶点的Y坐标,我基本上得到与原始相同的结果: enter image description here

现在,我正在使用的网格格式具有对象层次结构,这意味着网格的子集可以作为父节点的另一个子集,如果是这样的话,它具有相对于与其关联的父节点的位置和旋转矩阵。这意味着在加载网格时会出现更多问题,因为旋转矩阵和位置也是在错误的坐标系中定义的。 要应用此更改,我创建顶点,然后创建由这些顶点组成的对象,为其指定父节点,然后应用旋转矩阵和位置。

以这种格式定义的网格为例;以我描述的方式构成它的所有各个部分: enter image description here

如果我按原样加载它,顶点,相对旋转矩阵和位置在错误的坐标系中,我得到: enter image description here

除了沿着轴“镜像”之外,哪种外观相同。请注意图像最右边的黄色物体(不知道如何调用它):它位于原始图像中其位置的另一侧。 另外,如果你看一下文字“BROKK”(它不是一个纹理,它是由顶点组成的),它也是相反的。

现在,如果我应用与蜘蛛相同的技巧,将Y切换到-Y,我得到: enter image description here

现在它看起来没有镜像,但是机器的“手臂”都是错的,可能是因为我离开相对旋转矩阵并在它们的原始坐标系中的位置可能?我试着弄乱它们,但是我得到了各种奇怪的事情,没有接近解决方案。

我看了很多,在我找到对比的想法的坐标系之间切换。我尝试在下面应用这个矩阵来切换轴并将轴反转为“向前”,但结果是疯狂的错误:

(1 0 0)
(0 0 1)
(0 -1 0)

我很无奈,你有什么想法吗?

编辑:感谢Ripi2的建议(仅将符号反转为Z坐标)我更接近理想的解决方案。这是结果: enter image description here

即使它是颠倒的(我可以稍后简单地旋转它),它也不会被反映出来。尽管如此,在那张照片中,我只是反转网格顶点和儿童位置的Z坐标。在图片中,除了手臂之外的所有部件都处于正确的方向,因为它们的旋转矩阵是单位矩阵。虽然旋转矩阵不是身份,但是因为我将它留在原始坐标系中,所以它看起来都是错误的。

我需要某种矩阵来乘以每个旋转矩阵,但我不知道是什么!

3 个答案:

答案 0 :(得分:1)

矩阵从X+ right, Y+ up, Z- deep转换为Y+ right, Z+ up, X+ deep

 0  1  0  0
 0  0  1  0
-1  0  0  0
 0  0  0  1 

及其反向

0  0 -1  0
1  0  0  0
0  1  0  0
0  0  0  1

没有矩阵代码可能如下所示:

x2 = -z1
y2 = x1
z2 = y1

修改

你得到错误的结果?也许你有一个不同的系统变化。例如,如果只改变Y符号就足够了,这就是矩阵:

1  0  0  0
0 -1  0  0
0  0  1  0
0  0  0  1

记住矩阵计算顺序Result = Transform * Origin

如果模型由层次结构中的多个对象组成,则进程如下:

  1. 每个模型都使用自己的矩阵进行平移和旋转,或者 与组成ORDERED的转换。它的 假设如果数据来自文件,则轴系统是相同的 为了所有人。
  2. 构建完整世界后,您可以使用设置相机 视图矩阵和带有另一个矩阵的投影。在这一点上,您需要应用轴系统变换矩阵。
  3. 让我们在您的模型中使用arm-end。它有自己的矩阵T1(例如由旋转然后平移组成,T1 = T·R)。当它被链接到手臂的其余部分(具有T2矩阵)时,它也必须得到主臂变换。因此应用于arm-end的结果矩阵是T2·T1(注意顺序,而不是T1·T2)。如果整个臂被链接到其他部分,那么所需的臂端矩阵是T3·T2·T1。

    现在应用视图矩阵(V),轴变化(A)和投影(P)。所得到的臂端矩阵是P·A·V·T3·T2·T1。

    也许很难在新的轴系统中定义投影。如果仅仅是改变某些符号和交换轴的问题,最好在投影后应用:A·P·V·T3·T2·T1

答案 1 :(得分:0)

这是我找到的解决方案。我需要将矩阵应用于每个顶点,然后将相同的矩阵应用于每个分层组件所具有的旋转平移矩阵。矩阵就是这个:

1 0 0
0 0 1
0 1 0

在代码中(记住,我使用虚幻引擎),它是这样的:

// Iterating over all vertices of the mesh
for(int i = 0; i < verticesNumber; i++)
{
    FVector4 vertex;

    // Getting the coordinates in the original mesh coordinate system.
    // Here the method GetX(), GetY(), GetZ() retrieve the coordinates from the mesh file somehow
    vertex.X = GetX();
    vertex.Y = GetY();
    vertex.Z = GetZ();

    // Creating the matrix that will transform these coordinates in the new coordinate system
    FMatrix mat = FMatrix::Identity;

    mat.M[0][0] = 1, mat.M[0][1] = 0, mat.M[0][2] = 0;
    mat.M[1][0] = 0, mat.M[1][1] = 0, mat.M[1][2] = 1;
    mat.M[2][0] = 0, mat.M[2][1] = 1, mat.M[2][2] = 0;

    // Applying the matrix
    vertex = mat.TransformFVector4(vertex);

    vertices.Add(FVector(vertex.X, vertex.Y, vertex.Z));
}

/* Then I create the indices, normals, and so on. */

// Now I get from the file the roto-translation matrix for the current object and apply the same matrix like this (note that I multiply before and after; this was mainly what I was missing):
rotationTranslationMatrix = mat * rotationTranslationMatrix * mat;

// Then I set the new matrix, relative to the parent of the current object
FVector position;
position.X = rotationTranslationMatrix.M[0][3];
position.Y = rotationTranslationMatrix.M[1][3];
position.Z = rotationTranslationMatrix.M[2][3];
mesh->SetRelativeLocationAndRotation(position, rotationTranslationMatrix.Rotator());

对构成网格的每个部分执行此代码。最终的结果是,对于我用作示例的模型: enter image description here

请注意,它沿X轴移动了90度。我不知道如何避免这种情况,但是我需要的就是在创建后旋转网格就足够了,如下所示:

FRotator rotation;
rotation.Yaw = 0.0f;
rotation.Pitch = 0.0f;
rotation.Roll = -90.0f;

mMesh->SetWorldRotation(rotation);

最终结果: enter image description here

再次感谢Ripi2的帮助!

答案 2 :(得分:0)

要创建从opengl转换为虚幻坐标系的矩阵,您需要:

  1. 用Zu替换Ygl;
  2. 用Yu替换Xgl;
  3. 用-Xu替换Zgl;

FMatrix Mgl2u = FMatrix::Identity;

Mgl2u.M[0][0] = 0; Mgl2u.M[0][1] = 1; Mgl2u.M[0][2] = 0; Mgl2u.M[1][0] = 0; Mgl2u.M[1][1] = 0; Mgl2u.M[1][2] = 1; Mgl2u.M[2][0] = -1; Mgl2u.M[2][1] = 0; Mgl2u.M[2][2] = 0;