如何在另一个 3D 软件中旋转形状,使旋转与 Blender 中的旋转相匹配?
How to rotate a shape in another 3D software so that the rotation matches with the rotation in Blender?
我在 Blender 中导入一个网格,使用设置 axis_forward='-Z', axis_up='Y'
导出它,在 NVIDIA 的 FleX 中导入,旋转它并存储在磁盘上;我称这个网格为 X
。我还在 Blender 中导入网格并将其旋转相同的量;我称这个网格为 Y
。在 Blender 中导入 X
后(设置 axis_forward='-Z', axis_up='Y'
)我意识到 X
有不同的旋转,这意味着 FleX 使用不同的全局轴(我认为它是 -Y
向前和 Z
向上)或者它以不同的顺序或两者的组合应用旋转。所以我现在很困惑。我不想更改 FleX 方面的任何内容。但是,我想以一种与旋转后 FleX 输出 (X
) 相匹配的方式旋转 Y
。我也尝试过使用四元数,但我仍然无法弄清楚 FleX 是如何转换对象的。根据经验,我唯一能够弄清楚的是 rx
旋转值对 FleX 和 Blender 的应用方式相同。这意味着如果在 Blender 的场景中导入对象 X
和 Y
将完全重叠。
我的目标 是在 FleX 中旋转对象,以便当我导入 [=14] 时对象 Y
的旋转与对象 X
完全匹配=] 在搅拌机中。例如,我希望 FleX 旋转对象的方式与 Blender 使用 [rx, ry, rz]
的欧拉旋转矢量旋转对象的方式相同。我怎样才能做到这一点?
注意 我没有更改 Blender 中的旋转顺序,我使用的是默认 XYZ
旋转。
这里是 FleX 和 Blender 进行此类转换的视觉差异的一些图片:
欧拉旋转矢量:[0, 89.9, 0]
在 Blender 中的对象 Y
。
在 Blender 中应用旋转后(对象 Y
):
在 FleX 中应用相同的旋转 ([0, 89.9, 0]
) 并在 Blender 中导入对象 X
之后:
Euler 旋转向量:[0, 0, 89.9]
用于 Blender 中的对象 Y
。
在 FleX 中应用相同的旋转 ([0, 0, 89.9]
) 并在 Blender 中导入对象 X
之后:
看起来很容易从图像中猜出 FleX 在应用旋转时交换了 ry
和 rz
。如果我在 Blender 中应用旋转时也交换了 ry
和 rz
,那么 X
和 Y
都会重叠。但是,这仅在旋转矢量的所有分量都为零时才有效,其中一个除外。如果旋转矢量类似于 [-43.964176, 20.641195, -1.2689421]
X
和 Y
不再重叠并且差异开始出现,如下所示:
如果我在 FleX 中将布料放在 X
上,将布料和 Y
导入 Blender 并将 Y
旋转 [-43.964176, -1.2689421, 20.641195]
,差异会更加明显(注意我在 Blender 中应用旋转时交换了 ry
和 rz
,而不是在 FleX 中):
请注意,如果我在这里输入 X
,布料会在接触它的表面时完美地覆盖它:
在对最后一个示例进行一些修改后,我注意到如果我应用旋转矢量 [-43.964176, 1.2689421, 20.641195]
(rx, -rz, ry),对象几乎完美重叠:
再举一个例子,我想在 Blender 中应用旋转 [87.68034, 79.94778, 82.697876]
,这应该 理想地 给我这样的东西:
但是,FleX 给出了以下信息(在将旋转矢量传递给 FleX 之前没有交换):
我在想,也许在 Blender 中按 (rx, -rz, ry)
的顺序应用旋转会给我在上一个示例中得到的完美重叠结果,但相反,我在另一个示例中得到了非常奇怪的结果,如下所示。请注意,我想将对象旋转 [87.68034, 79.94778, 82.697876]`:
通过在 Blender 中手动旋转对象,我最终可以使它尽可能接近 Y
(从 FleX 导出)。令人惊讶的是,与 X
和 Y
重叠的旋转矢量与 (rx, ry, rz)
中的 [87.68034, 79.94778, 82.697876]
或 (rx, -rz, ry)
中的 [87.68034 -82.697876, 79.94778]
有很大不同。 `(rx, ry, rz) 中的 [5.38, -10.1, 88.6]
左右,如下所示:
虽然您可能需要更多信息才能准确了解发生了什么,但下面我 post 是 FleX 中用于计算其旋转矩阵的代码。上面一个是用欧拉角的时候用的,第二个是输入四元数的时候用的:
// generate a rotation matrix around an axis, from PBRT p74
inline Mat44 RotationMatrix(float angle, const Vec3& axis)
{
Vec3 a = Normalize(axis);
float s = sinf(angle);
float c = cosf(angle);
float m[4][4];
m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
m[0][3] = 0.0f;
m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
m[1][3] = 0.0f;
m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
return Mat44(&m[0][0]);
}
inline Mat44 RotationMatrix(Quat q)
{
Matrix33 rotation(q);
Matrix44 m;
m.SetAxis(0, rotation.cols[0]);
m.SetAxis(1, rotation.cols[1]);
m.SetAxis(2, rotation.cols[2]);
m.SetTranslation(Point3(0.0f));
return m;
}
下面是我如何应用欧拉旋转矢量:
obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));
我认为 Transform()
应该是这样定义的:
void Mesh::Transform(const Matrix44& m)
{
for (uint32_t i=0; i < m_positions.size(); ++i)
{
m_positions[i] = m*m_positions[i];
m_normals[i] = m*m_normals[i];
}
}
我只需要进行以下更改即可[手动]将 FleX 的坐标系更改为 Blender 使用的坐标系:
obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 0.0f, -1.0f)))
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 1.0f, 0.0f)));
我认为这是我生成三个旋转矢量 [90, 0, 0]
、[0, 90, 0]
和 [0, 0, 90]
并在 FleX 中旋转形状。然后我将形状加载到 Blender 中,并凭经验计算出 Blender 中哪个轴上的旋转与从 FleX 导入的形状相匹配。我了解到,当我在 Blender 中将 Y
轴上的形状旋转 90 度时,它与 FleX 中 Z
轴上的 90 度旋转相匹配。此外,我了解到在 Blender 中将对象在 Z
轴上旋转 -90 度与在 FleX 中在 Y
轴上旋转 90 度相匹配。
我在 Blender 中导入一个网格,使用设置 axis_forward='-Z', axis_up='Y'
导出它,在 NVIDIA 的 FleX 中导入,旋转它并存储在磁盘上;我称这个网格为 X
。我还在 Blender 中导入网格并将其旋转相同的量;我称这个网格为 Y
。在 Blender 中导入 X
后(设置 axis_forward='-Z', axis_up='Y'
)我意识到 X
有不同的旋转,这意味着 FleX 使用不同的全局轴(我认为它是 -Y
向前和 Z
向上)或者它以不同的顺序或两者的组合应用旋转。所以我现在很困惑。我不想更改 FleX 方面的任何内容。但是,我想以一种与旋转后 FleX 输出 (X
) 相匹配的方式旋转 Y
。我也尝试过使用四元数,但我仍然无法弄清楚 FleX 是如何转换对象的。根据经验,我唯一能够弄清楚的是 rx
旋转值对 FleX 和 Blender 的应用方式相同。这意味着如果在 Blender 的场景中导入对象 X
和 Y
将完全重叠。
我的目标 是在 FleX 中旋转对象,以便当我导入 [=14] 时对象 Y
的旋转与对象 X
完全匹配=] 在搅拌机中。例如,我希望 FleX 旋转对象的方式与 Blender 使用 [rx, ry, rz]
的欧拉旋转矢量旋转对象的方式相同。我怎样才能做到这一点?
注意 我没有更改 Blender 中的旋转顺序,我使用的是默认 XYZ
旋转。
这里是 FleX 和 Blender 进行此类转换的视觉差异的一些图片:
欧拉旋转矢量:[0, 89.9, 0]
在 Blender 中的对象 Y
。
在 Blender 中应用旋转后(对象 Y
):
在 FleX 中应用相同的旋转 ([0, 89.9, 0]
) 并在 Blender 中导入对象 X
之后:
Euler 旋转向量:[0, 0, 89.9]
用于 Blender 中的对象 Y
。
在 FleX 中应用相同的旋转 ([0, 0, 89.9]
) 并在 Blender 中导入对象 X
之后:
看起来很容易从图像中猜出 FleX 在应用旋转时交换了 ry
和 rz
。如果我在 Blender 中应用旋转时也交换了 ry
和 rz
,那么 X
和 Y
都会重叠。但是,这仅在旋转矢量的所有分量都为零时才有效,其中一个除外。如果旋转矢量类似于 [-43.964176, 20.641195, -1.2689421]
X
和 Y
不再重叠并且差异开始出现,如下所示:
如果我在 FleX 中将布料放在 X
上,将布料和 Y
导入 Blender 并将 Y
旋转 [-43.964176, -1.2689421, 20.641195]
,差异会更加明显(注意我在 Blender 中应用旋转时交换了 ry
和 rz
,而不是在 FleX 中):
请注意,如果我在这里输入 X
,布料会在接触它的表面时完美地覆盖它:
在对最后一个示例进行一些修改后,我注意到如果我应用旋转矢量 [-43.964176, 1.2689421, 20.641195]
(rx, -rz, ry),对象几乎完美重叠:
再举一个例子,我想在 Blender 中应用旋转 [87.68034, 79.94778, 82.697876]
,这应该 理想地 给我这样的东西:
但是,FleX 给出了以下信息(在将旋转矢量传递给 FleX 之前没有交换):
我在想,也许在 Blender 中按 (rx, -rz, ry)
的顺序应用旋转会给我在上一个示例中得到的完美重叠结果,但相反,我在另一个示例中得到了非常奇怪的结果,如下所示。请注意,我想将对象旋转 [87.68034, 79.94778, 82.697876]`:
通过在 Blender 中手动旋转对象,我最终可以使它尽可能接近 Y
(从 FleX 导出)。令人惊讶的是,与 X
和 Y
重叠的旋转矢量与 (rx, ry, rz)
中的 [87.68034, 79.94778, 82.697876]
或 (rx, -rz, ry)
中的 [87.68034 -82.697876, 79.94778]
有很大不同。 `(rx, ry, rz) 中的 [5.38, -10.1, 88.6]
左右,如下所示:
虽然您可能需要更多信息才能准确了解发生了什么,但下面我 post 是 FleX 中用于计算其旋转矩阵的代码。上面一个是用欧拉角的时候用的,第二个是输入四元数的时候用的:
// generate a rotation matrix around an axis, from PBRT p74
inline Mat44 RotationMatrix(float angle, const Vec3& axis)
{
Vec3 a = Normalize(axis);
float s = sinf(angle);
float c = cosf(angle);
float m[4][4];
m[0][0] = a.x * a.x + (1.0f - a.x * a.x) * c;
m[0][1] = a.x * a.y * (1.0f - c) + a.z * s;
m[0][2] = a.x * a.z * (1.0f - c) - a.y * s;
m[0][3] = 0.0f;
m[1][0] = a.x * a.y * (1.0f - c) - a.z * s;
m[1][1] = a.y * a.y + (1.0f - a.y * a.y) * c;
m[1][2] = a.y * a.z * (1.0f - c) + a.x * s;
m[1][3] = 0.0f;
m[2][0] = a.x * a.z * (1.0f - c) + a.y * s;
m[2][1] = a.y * a.z * (1.0f - c) - a.x * s;
m[2][2] = a.z * a.z + (1.0f - a.z * a.z) * c;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
return Mat44(&m[0][0]);
}
inline Mat44 RotationMatrix(Quat q)
{
Matrix33 rotation(q);
Matrix44 m;
m.SetAxis(0, rotation.cols[0]);
m.SetAxis(1, rotation.cols[1]);
m.SetAxis(2, rotation.cols[2]);
m.SetTranslation(Point3(0.0f));
return m;
}
下面是我如何应用欧拉旋转矢量:
obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 1.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 0.0f, 1.0f)));
我认为 Transform()
应该是这样定义的:
void Mesh::Transform(const Matrix44& m)
{
for (uint32_t i=0; i < m_positions.size(); ++i)
{
m_positions[i] = m*m_positions[i];
m_normals[i] = m*m_normals[i];
}
}
我只需要进行以下更改即可[手动]将 FleX 的坐标系更改为 Blender 使用的坐标系:
obj->Transform(RotationMatrix(op.rotate.x, Vec3(1.0f, 0.0f, 0.0f)));
obj->Transform(RotationMatrix(op.rotate.y, Vec3(0.0f, 0.0f, -1.0f)))
obj->Transform(RotationMatrix(op.rotate.z, Vec3(0.0f, 1.0f, 0.0f)));
我认为这是我生成三个旋转矢量 [90, 0, 0]
、[0, 90, 0]
和 [0, 0, 90]
并在 FleX 中旋转形状。然后我将形状加载到 Blender 中,并凭经验计算出 Blender 中哪个轴上的旋转与从 FleX 导入的形状相匹配。我了解到,当我在 Blender 中将 Y
轴上的形状旋转 90 度时,它与 FleX 中 Z
轴上的 90 度旋转相匹配。此外,我了解到在 Blender 中将对象在 Z
轴上旋转 -90 度与在 FleX 中在 Y
轴上旋转 90 度相匹配。