【发布时间】:2019-04-10 20:21:00
【问题描述】:
我在 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 方面的任何东西。但是,我想旋转 Y,使其与旋转后 FleX 导出的内容 (X) 匹配。我也尝试过使用四元数,但我仍然无法弄清楚 FleX 是如何转换对象的。我唯一能凭经验弄清楚的是,rx 旋转的值对 FleX 和 Blender 的应用方式相同。这意味着如果在 Blender 的场景中导入对象 X 和 Y 将完全重叠。
我的目标是在 FleX 中旋转对象,以便当我在 Blender 中导入 X 时,对象 Y 的旋转与对象 X 完全匹配。例如,我希望 FleX 旋转对象的方式与 Blender 使用欧拉旋转矢量 [rx, ry, rz] 旋转它的方式相同。我怎样才能做到这一点?
请注意,我不会更改 Blender 中的旋转顺序,而是使用默认的 XYZ 旋转。
这里我是 FleX 和 Blender 对于此类转换的视觉差异的一些图像:
欧拉旋转矢量:[0, 89.9, 0] 在 Blender 中用于对象 Y。
在 FleX 中应用相同的旋转 ([0, 89.9, 0]) 并在 Blender 中导入对象 X 后:
欧拉旋转矢量:[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 上,在 Blender 中导入布料和 Y 并将 Y 旋转 [-43.964176, -1.2689421, 20.641195],差异会更加明显(请注意,我已经交换了 ry 和 @ 987654386@ 在 Blender 中应用旋转时,而不是在 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] 周围的东西,如下所示:
虽然您可能需要更多信息才能准确了解发生了什么,但下面我发布了 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];
}
}
【问题讨论】:
标签: unity3d graphics 3d rotation blender