簡體   English   中英

如何將右手 XYZ 坐標系中定義的網格轉換為左手 XYZ 坐標系

[英]How to convert mesh defined in a right-handed XYZ coordinate system to a left-handed XZY one

我需要一種方法來傳遞到這些坐標系,但我在數學上很掙扎。

基本上,我有一個“為 OpenGL”創建的網格,因此是右手 XYZ 坐標系,我想在使用左手 XZY 坐標系的不同環境(虛幻引擎 4)中加載它。

現在,以這個網格為例,在它的原始狀態下: 在此處輸入圖片說明

如果加載它使所有頂點保持原樣,我會得到: 在此處輸入圖片說明

如果仔細觀察,您會發現它是“鏡像”的,蜘蛛的左腿與右腿互換。 此外,在圖像中不是很清楚,但深度是關閉的,我可以看到蜘蛛的“內部”(如果你注意到了,眼睛因此不見了)。

現在,如果我用 -YI 交換每個頂點的 Y 坐標,基本上得到與原始相同的結果: 在此處輸入圖片說明

現在,我使用的網格格式具有對象層次結構,這意味着網格的一個子集可能有另一個子集作為父子集,如果是這樣,它具有相對於與其關聯的父級的位置和旋轉矩陣。 這意味着加載網格時會出現更多問題,因為旋轉矩陣和位置也在錯誤的坐標系中定義。 為了應用這些更改,我創建了頂點,然后由這些頂點組成的對象,將其分配給它的父對象,然后應用旋轉矩陣和位置。

以這個網格為例,用這種格式定義; 組成它的所有各個部分都是按照我描述的方式分層的: 在此處輸入圖片說明

如果我按原樣加載它,頂點、相對旋轉矩陣和位置在錯誤的坐標系中,我會得到: 在此處輸入圖片說明

哪種看起來相同,只是它沿軸“鏡像”。 請注意圖像最右側的黃色東西(不知道如何稱呼它):它位於原始圖像中位置的另一側。 此外,如果您查看文本“BROKK”(它不是紋理,它由頂點組成),它也會被反轉。

現在,如果我應用與蜘蛛相同的技巧,將 Y 切換為 -Y,我會得到: 在此處輸入圖片說明

現在它看起來沒有鏡像,但是機器的“手臂”全都錯了,可能是因為我將相對旋轉矩陣和位置留在了它們的原始坐標系中? 我試着弄亂他們,但我遇到了各種奇怪的事情,沒有接近解決方案。

我環顧四周,在坐標系之間切換,我發現了截然不同的想法。 我嘗試應用下面的這個矩陣來切換軸並反轉軸“向前”,但結果是錯誤的:

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

我很無奈,你有什么想法嗎?

編輯:感謝 Ripi2 的建議(僅將符號反轉為 Z 坐標),我已經接近理想的解決方案了。 這是結果: 在此處輸入圖片說明

即使它是顛倒的(我可以稍后簡單地旋轉它),它也不再鏡像了。 盡管如此,在那張圖片中,我只是反轉了網格頂點和孩子位置的 Z 坐標。 在圖片中,除了手臂之外的所有部分都處於正確的方向,因為它們的旋轉矩陣是單位矩陣。 在手臂中,雖然旋轉矩陣不是身份,而且由於我將它保留在原始坐標系中,因此它看起來全錯了。

我需要某種矩陣來乘以每個旋轉矩陣,但我不知道是什么!

矩陣從X+ right, Y+ up, Z- deepY+ 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. 構建完整世界后,您可以使用視圖矩陣和另一個矩陣的投影來設置相機。 在這一點上,您要應用軸系統變換矩陣。

讓我們在您的模型中使用臂端。 它有自己的矩陣 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 0
0 0 1
0 1 0

在代碼中(記住,我使用的是 Unreal 引擎),它是這樣的:

// 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());

為構成網格的每個部分執行此代碼。 最終結果是這樣的,對於我用作示例的模型: 在此處輸入圖片說明

請注意,它沿 X 軸移動了 90 度。 我不知道如何避免這種情況,但是對於我所需要的,只需在創建后旋轉網格就足夠了,如下所示:

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

mMesh->SetWorldRotation(rotation);

最終結果: 在此處輸入圖片說明

再次感謝 Ripi2 的幫助!

要制作從 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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM