- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我为 UE4 编写了一个插件,用于在 UE4 关卡中匹配和生成静态网格物体 Actors。
该插件从每个脚本从 Softimage XSI 导出的文本文件(缩放、旋转、变换)中读取坐标。一切正常。但不是旋转。
我知道跟坐标系有关系。但我究竟如何从一种转换为另一种?
到目前为止我认为我发现了什么(不是 100% 肯定)
XSI 是右手 Y 向上,旋转顺序 XYZ
UE4是左手Z向上,旋转顺序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) 原始坐标系。
不确定这是否是必需的,但我将维基百科中关于欧拉的信息放入 C++ 代码中的矩阵。
这是所有 6 个 Tait-Bryan 角矩阵:
它是否正确?如果是这样,我将如何定义
(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
}
}
最佳答案
好的,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();
}
关于c++ - 如何将欧拉旋转从一个坐标系转换到另一个坐标系?右手 Y 向上到左手 Z 向上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57025469/
在编程中,我只使用整数。不过这次要进行一些计算。我需要计算Euler-Mascheroni Constant γ .最多 n 位小数。{虽然 n ∈ [30, 150]对我来说已经足够了。 [x] =
有人可以帮忙处理这段代码吗?它应该得到第 10,001 个素数。我知道 is_prime 函数可以测试一个数字是否为素数,因为我成功地利用此代码解决了上一个问题。现在我只是尝试在 for 循环中调用它
我发现了几个与这个问题相关的主题,我只是想知道为什么我的代码返回不正确的数据。所以我们必须找到第一个除数超过 500 的三角形数。详情可在此处找到:http://projecteuler.net/pr
#include int main(void) { char *num = "73167176531330624919225119674426574742355349194934"
我正在尝试投影欧拉问题 8,但是我遇到了问题。1000位数字中相邻四位的乘积最大为9×9×8×9=5832。 731671765313306249192251196744265747423553491
这是针对 Project Euler 19 的。我几乎想出了代码,但由于某种原因我的输出是 +1。 #include #define SIZE 12 int main(void) {
int main(void) { int n, div, a, b; double phi; printf("Enter n:\n"); if (scanf("%d", &n) < 1
欧拉问题: 如果我们列出所有 10 以下的自然数,它们是 3 或 5 的倍数,我们得到 3、5、6 和 9。这些倍数的和是 23。 求 1000 以下的所有 3 或 5 的倍数之和。 我试图从 pro
我知道这可能会被否决,但我真的很沮丧 24 小时,查看其他 Euler 3 线程并没有帮助我解决这个问题。有人可以帮助我的代码吗?我认为我非常接近。 function is_prime(num) {
我卡在了Question 7欧拉计划。我有这段代码。 #include int main (void) { int contador = 0, i, n, variavel = 0;
我正在尝试使用 sympy 的 idiff 函数对某些表达式执行隐式微分。 在本例中,rdot 为 dr/ds,其中 s 是仿射参数。我想对相同的仿射参数对 Ltdot、Lphidot 和 Lrdot
我正在尝试解决我的第一个项目 Euler 问题,只是为了玩 Rust,但被困在似乎需要极长计算时间的问题上 问题: https://projecteuler.net/problem=757 我想出了这
我正在学习C编程,并制定了以下算法来解决这个问题: 代码实际上有效,但最初循环只有 10 次重复(rep int main() { float p; //the power for e
我之前曾尝试暴力破解它,但没有成功。这是我的递归尝试#2(第一次使用递归方法)。请帮忙! 发生的情况是这样的:代码运行良好,数字较小,但是当我们达到一百万时,代码就会运行,并且什么也不会发生。在 Ec
Given a number find the 5 digits before the trailing 0. 9! = 362880 so f(9)=36288 10! = 3628800 so f
我是一名优秀的程序员,十分优秀!