我为UE4编写了一个插件,用于将静态网格物体Actor匹配并生成到UE4级别。
该插件从文本文件(Scale,Rotation,Transformation)读取坐标,该文本文件按脚本从Softimage XSI导出。一切正常。但不是旋转。
我知道它与坐标系有关。 但是我该如何准确地从一个转换为另一个呢?
到目前为止,我认为我发现了什么(不确定100%)
XSI为右手Y-up,旋转顺序为XYZ
UE4左旋Z-up,旋转顺序XZY
在这两种应用中,我的欧拉角均以度为单位。
因此,在我的3D软件(Softimage XSI)中,我具有XYZ度,并将其存储到磁盘上的文本文件中。
逐行,其中每行都是一个对象。
在UE4中,该插件读取此行并生成SM Actor到关卡。
+++++新信息+++++
您好,谢谢您的回答!
我制作了一个视频,以显示细节和情况。
https://www.youtube.com/watch?v=sWX84FxZTw0
+++++ Actor产生函数+++++
void SpawnSMActor(const TCHAR *path,float sX,float sY,float sZ,float rX,float rY,float rZ,float pX,float pY,float pZ)
{
// Load Static Mesh from given Reference Path from UE4 Explorer
UStaticMesh* StaMesh = LoadObject<UStaticMesh>(nullptr, path);
// Transform
FVector objectScale(sX, sY, sZ); // Scale
// ********************************************************************************
// Conversion XSI Coordinate System to UE4 Coordinate System
FVector NewPosition;
FRotator NewRotation;
// We just simply swap the Z and Y Coordinates
NewPosition.X = pX * 100; // TX
NewPosition.Y = pZ * 100; // TZ
NewPosition.Z = pY * 100; // TY
// We just simply swap the Pitch(Y) and Yaw(Z) angles
NewRotation.Roll = rX; // RX
NewRotation.Pitch = rZ; // RZ
NewRotation.Yaw = -rY; // RY
FRotator NewobjectRotation(NewRotation.Quaternion());
FTransform objectTransform(NewobjectRotation, NewPosition, objectScale);
// ********************************************************************************
// Creating the Actor and Positioning it in the World based on the Static Mesh
UWorld* currentWorld = GEditor->GetEditorWorldContext().World();
ULevel* currentLevel = currentWorld->GetCurrentLevel();
UClass* StaticMeshClass = AStaticMeshActor::StaticClass();
AActor* NewActorCreated = GEditor->AddActor(currentLevel, StaticMeshClass, objectTransform, true, RF_Public | RF_Standalone | RF_Transactional);
AStaticMeshActor* smActor = Cast<AStaticMeshActor>(NewActorCreated);
smActor->GetStaticMeshComponent()->SetStaticMesh(StaMesh);
smActor->SetActorScale3D(objectScale);
// ID Name & Visible Name
//smActor->Rename(TEXT("MyStaticMeshInTheWorld"));
//smActor->SetActorLabel("MyStaticMeshInTheWorld");
GEditor->EditorUpdateComponents();
smActor->GetStaticMeshComponent()->RegisterComponentWithWorld(currentWorld);
currentWorld->UpdateWorldComponents(true, false);
smActor->RerunConstructionScripts();
GLevelEditorModeTools().MapChangeNotify();
}
如果我在3D应用程序中将对象在UP轴上顺时针旋转45度
,在X轴上旋转45度,则得到:
X -54,7356°
Y -30°
Z 35,2644°
如果我在UE4中执行相同的旋转,则会得到:
X -35,2644°
Y 30°
Z 35,2644°
所以这些将是UE4中正确的旋转角度!
但是使用上面列出的代码,我得到:
X -54,7355°
Y 35,2643°
Z 30°
那是错的!因为它看起来只是在翻转一些位置。角度与我的3D应用程序中的角度基本相同。
这是我第二次尝试在没有UE4 API的情况下解决转换的问题。
我知道它还不完整,我仍然不完全了解我必须采取的步骤。
但它有望成为一个开始。
就像上面提到的@ DavidC.Rankin一样,我需要定义(1)原始坐标系。
不知道这是否是必要的,但是我将Wikipedia中有关Euler的信息放入了C ++代码中的矩阵。
这是所有Tait–Bryan角度矩阵中的6个:
它是否正确?如果是这样,我将如何定义
(2)目标坐标系?
(3)旋转顺序?
#include "pch.h"
#include <iostream>
#include <string>
#include "linalg.h"
using namespace linalg::aliases;
using namespace std;
float x,y,z;
//Pre
void MatrixXZY(float3 angles, float3x3& matrix);
void MatrixXYZ(float3 angles, float3x3& matrix);
void MatrixYXZ(float3 angles, float3x3& matrix);
void MatrixYZX(float3 angles, float3x3& matrix);
void MatrixZYX(float3 angles, float3x3& matrix);
void MatrixZXY(float3 angles, float3x3& matrix);
void PrintMatrix(string name, float3 angles, float3x3& matrix);
void MatrixDecomposeYXZ(float3x3& matrix, float3& angles);
int main()
{
float3 AnglesIn = { 0, 0, 0 };
float3 AnglesOut;
float3x3 Matrix; // Matrix [Spalte][Zeile]
cout << "-----------------------------" << endl;
cout << "Input" << endl;
cout << AnglesIn[0] << " " << AnglesIn[1] << " " << AnglesIn[2] << " " << endl;
cout << "-----------------------------" << endl << endl;
MatrixXZY(AnglesIn, Matrix);
PrintMatrix("XZY", AnglesIn, Matrix);
MatrixXYZ(AnglesIn, Matrix);
PrintMatrix("XYZ", AnglesIn, Matrix);
MatrixYXZ(AnglesIn, Matrix);
PrintMatrix("YXZ", AnglesIn, Matrix);
MatrixDecomposeYXZ(Matrix, AnglesOut);
cout << "-----------------------------" << endl;
cout << AnglesOut.x << " " << AnglesOut.y << " " << AnglesOut.z << " " << endl;
cout << "-----------------------------" << endl << endl;
MatrixYZX(AnglesIn, Matrix);
PrintMatrix("YZX", AnglesIn, Matrix);
MatrixZYX(AnglesIn, Matrix);
PrintMatrix("ZYX", AnglesIn, Matrix);
MatrixZXY(AnglesIn, Matrix);
PrintMatrix("ZXY", AnglesIn, Matrix);
}
void MatrixXZY(float3 angles, float3x3& matrix)
{
float cosX = cosf(angles.x); // X
float sinX = sinf(angles.x);
float cosY = cosf(angles.y); // Y
float sinY = sinf(angles.y);
float cosZ = cosf(angles.z); // Z
float sinZ = sinf(angles.z);
matrix[0][0] = cosZ * cosY; // Spalte 1
matrix[0][1] = sinX * sinY + cosX * cosY * sinZ;
matrix[0][2] = cosY * sinX * sinZ - cosX * sinY;
matrix[1][0] = -sinZ; // Spalte 2
matrix[1][1] = cosX * cosZ;
matrix[1][2] = cosZ * sinX;
matrix[2][0] = cosZ * sinY; // Spalte 3
matrix[2][1] = cosX * sinZ * sinY - cosY * sinX;
matrix[2][2] = cosX * cosY + sinX * sinZ * sinY;
}
void MatrixXYZ(float3 angles, float3x3& matrix)
{
float cosX = cosf(angles.x); // X
float sinX = sinf(angles.x);
float cosY = cosf(angles.y); // Y
float sinY = sinf(angles.y);
float cosZ = cosf(angles.z); // Z
float sinZ = sinf(angles.z);
matrix[0][0] = cosY * cosZ; // Spalte 1
matrix[0][1] = cosX * sinZ + cosZ * sinX * sinY;
matrix[0][2] = sinX * sinZ - cosX * cosZ * sinY;
matrix[1][0] = -cosY * sinZ; // Spalte 2
matrix[1][1] = cosX * cosZ - sinX * sinY * sinZ;
matrix[1][2] = cosZ * sinX + cosX * sinY * sinZ;
matrix[2][0] = sinY; // Spalte 3
matrix[2][1] = -cosY * sinX;
matrix[2][2] = cosX * cosY;
}
void MatrixYXZ(float3 angles, float3x3& matrix)
{
float cosX = cosf(angles.x); // X
float sinX = sinf(angles.x);
float cosY = cosf(angles.y); // Y
float sinY = sinf(angles.y);
float cosZ = cosf(angles.z); // Z
float sinZ = sinf(angles.z);
matrix[0][0] = cosY * cosZ + sinY * sinX * sinZ; // Spalte 1
matrix[0][1] = cosX * sinZ;
matrix[0][2] = cosY * sinX * sinZ - cosZ * sinY;
matrix[1][0] = cosZ * sinY * sinX - cosY * sinZ; // Spalte 2
matrix[1][1] = cosX * cosZ;
matrix[1][2] = cosY * cosZ * sinX + sinY * sinZ;
matrix[2][0] = cosX * sinY; // Spalte 3
matrix[2][1] = -sinX;
matrix[2][2] = cosY * cosX;
}
void MatrixYZX(float3 angles, float3x3& matrix)
{
float cosX = cosf(angles.x); // X
float sinX = sinf(angles.x);
float cosY = cosf(angles.y); // Y
float sinY = sinf(angles.y);
float cosZ = cosf(angles.z); // Z
float sinZ = sinf(angles.z);
matrix[0][0] = cosY * cosZ; // Spalte 1
matrix[0][1] = sinZ;
matrix[0][2] = -cosZ * sinY;
matrix[1][0] = sinY * sinX - cosY * cosX * sinZ; // Spalte 2
matrix[1][1] = cosZ * cosX;
matrix[1][2] = cosY * sinX + cosX * sinY * sinZ;
matrix[2][0] = cosX * sinY + cosY * sinZ * sinX; // Spalte 3
matrix[2][1] = -cosZ * sinX;
matrix[2][2] = cosY * cosX - sinY * sinZ * sinX;
}
void MatrixZYX(float3 angles, float3x3& matrix)
{
float cosX = cosf(angles.x); // X
float sinX = sinf(angles.x);
float cosY = cosf(angles.y); // Y
float sinY = sinf(angles.y);
float cosZ = cosf(angles.z); // Z
float sinZ = sinf(angles.z);
matrix[0][0] = cosZ * cosY; // Spalte 1
matrix[0][1] = cosY * sinZ;
matrix[0][2] = -sinY;
matrix[1][0] = cosZ * sinY * sinX - cosX * sinZ; // Spalte 2
matrix[1][1] = cosZ * cosX + sinZ * sinY * sinX;
matrix[1][2] = cosY * sinX;
matrix[2][0] = sinZ * sinX + cosZ * cosX * sinY; // Spalte 3
matrix[2][1] = cosX * sinZ * sinY - cosZ * sinX;
matrix[2][2] = cosY * cosX;
}
void MatrixZXY(float3 angles, float3x3& matrix)
{
float cosX = cosf(angles.x); // X
float sinX = sinf(angles.x);
float cosY = cosf(angles.y); // Y
float sinY = sinf(angles.y);
float cosZ = cosf(angles.z); // Z
float sinZ = sinf(angles.z);
matrix[0][0] = cosZ * cosY - sinZ * sinX * sinY; // Spalte 1
matrix[0][1] = cosY * sinZ + cosZ * sinX * sinY;
matrix[0][2] = -cosX * sinY;
matrix[1][0] = -cosX * sinZ; // Spalte 2
matrix[1][1] = cosZ * cosX;
matrix[1][2] = sinX;
matrix[2][0] = cosZ * sinY + cosY * sinZ * sinX; // Spalte 3
matrix[2][1] = sinZ * sinY - cosZ * cosY * sinX;
matrix[2][2] = cosX * cosY;
}
void PrintMatrix(string name, float3 angles, float3x3& matrix)
{
cout << "-----------------------------" << endl;
cout << name << "-Matrix" << endl;
cout << "-----------------------------" << endl;
cout << matrix[0][0] << " " << matrix[1][0] << " " << matrix[2][0] << " " << endl;
cout << matrix[0][1] << " " << matrix[1][1] << " " << matrix[2][1] << " " << endl;
cout << matrix[0][2] << " " << matrix[1][2] << " " << matrix[2][2] << " " << endl;
cout << "-----------------------------" << endl << endl << endl;
}
void MatrixDecomposeYXZ(float3x3& matrix, float3& angles)
{
angles.x = asinf(-matrix[2][1]); // X
if (cosf(angles.x) > 0.0001) // Not at poles X
{
angles.y = atan2f(matrix[2][0], matrix[2][2]); // Y
angles.z = atan2f(matrix[0][1], matrix[1][1]); // Z
}
else
{
angles.y = 0.0f; // Y
angles.z = atan2f(-matrix[1][0], matrix[0][0]); // Z
}
}
答案 0 :(得分:1)
好的,Zakwayda先生在gamedev.net上解决了问题(谢谢!)-> Link
Softimage XSI 2015到Unreal Engine 4.22.3
void SpawnSMActor(const TCHAR *path,float sX,float sY,float sZ,float rX,float rY,float rZ,float pX,float pY,float pZ)
{
float rad = 0.0174532925199444; // FQuat needs Radians. So degree * Pi/180 | Pi/180 = 0.0174532...
// Transform
FVector Scale(sX, sY, sZ); // Scale
FVector Position; // Translation
// ************************************************************************************
// Conversion XSI Coordinate System to UE4 Coordinate System
// Position - Swap Z and Y axis and correct Position Scaling
Position.X = pX * 100;
Position.Y = pZ * 100;
Position.Z = pY * 100;
// Quaternions - Convert Rotations from XSI to UE4
FQuat qx(FVector(1, 0, 0), -rX * rad);
FQuat qz(FVector(0, 0, 1), -rY * rad);
FQuat qy(FVector(0, 1, 0), -rZ * rad);
FQuat qu = qy * qz * qx; // Change Rotation Order if necessary
FRotator Rotation(qu);
FTransform Transform(Rotation, Position, Scale);
// ************************************************************************************
// Load Static Mesh from given Reference Path from UE4 Explorer
UStaticMesh* StaMesh = LoadObject<UStaticMesh>(nullptr, path);
// Creating the Actor and Positioning it in the World based on the Static Mesh
UWorld* currentWorld = GEditor->GetEditorWorldContext().World();
ULevel* currentLevel = currentWorld->GetCurrentLevel();
UClass* StaticMeshClass = AStaticMeshActor::StaticClass();
AActor* NewActorCreated = GEditor->AddActor(currentLevel, StaticMeshClass, Transform, true, RF_Public | RF_Standalone | RF_Transactional);
AStaticMeshActor* smActor = Cast<AStaticMeshActor>(NewActorCreated);
smActor->GetStaticMeshComponent()->SetStaticMesh(StaMesh);
smActor->SetActorScale3D(Scale);
// ID Name & Visible Name
//smActor->Rename(TEXT("MyStaticMeshInTheWorld"));
//smActor->SetActorLabel("MyStaticMeshInTheWorld");
GEditor->EditorUpdateComponents();
smActor->GetStaticMeshComponent()->RegisterComponentWithWorld(currentWorld);
currentWorld->UpdateWorldComponents(true, false);
smActor->RerunConstructionScripts();
GLevelEditorModeTools().MapChangeNotify();
}
答案 1 :(得分:0)
您可以在UE4中使用FTransform变换旋转方式。 这为您提供了一个转换矩阵,我相信可以解决您的问题。
https://api.unrealengine.com/INT/API/Runtime/Core/Math/FTransform/index.html
由比例,旋转(作为四元数)和 翻译。
转换可用于将一个空间转换为另一个空间,例如 通过将位置和方向从本地空间转换为 世界空间。
从外观上看,听起来像您只需要交换Z和Y坐标值以及俯仰和偏航值即可进行旋转。
例如:
Pitch = Yaw;
Yaw = Pitch;
这是一个代码示例,说明如何在UE4 C ++中执行此操作
// We just simply swap the Z and Y Coordinates
FVector NewPosition;
NewPosition.X = InPosition.X;
NewPosition.Y = InPosition.Z;
NewPosition.Z = InPosition.Y;
SetActorLocation(NewPosition);
因此,我们只需交换Y
和Z
坐标。
现在我们可以对旋转进行相同的操作,注意命名有些不同,但是UE4很快解释了一下,这是一张图片:
// We just simply swap the Pitch(Y) and Yaw(Z) angles
FRotator NewRotation;
NewRotation.Roll = InRotation.X;
NewRotation.Pitch = InRotation.Z;
NewRotation.Yaw = InRotation.Y;
SetActorRotation(NewRotation.Quaternion());
现在从您的问题中我不能确定轴的方向,但是如果网格沿相反的方向移动,则可以简单地取轴的负值,例如:
FVector NewPosition;
NewPosition.X = -InPosition.X; // Note the - in front of InPosition.X; You can also multiply with -1
NewPosition.Y = InPosition.Z;
NewPosition.Z = InPosition.Y;
SetActorLocation(NewPosition);
在这里,我们将InPosition.X
设为负数来移动-InPosition.X
,则方向相反。
在两个不同的坐标系之间进行转换应该很简单。