我正在尝试实现功能,我可以在其中旋转/平移局部或全局方向的对象,就像在 3D 建模软件中一样,使用 glm。像这样:
void Rotate(float x, float y, float z, bool localOrientation);
但我不知道如何让它工作。局部旋转旋转应该是这样的(?):
m_Orientation *= glm::rotate(x, glm::vec3(1,0,0);
m_Orientation *= glm::rotate(y, glm::vec3(0,1,0);
m_Orientation *= glm::rotate(z, glm::vec3(0,0,1);
// (m_Orientation is glm::mat4)
但是如何将其与本地定位相结合呢?实际上我需要在世界方向上旋转旋转矩阵,对吧? 我希望你明白我所说的面向局部和全局的旋转/平移,就像在 3D 建模程序中一样。在大多数情况下,您都有一个按钮可以在本地和全局之间切换。
然后我将如何计算向前/向右/向上 vector ? 通常它应该是这样的,对吧?:
forward = m_Orientation * glm::vec4(0,0,-1,0);
我用这个尝试了全局旋转:
m_GlobalOrientation = glm::rotate(m_GlobalRotation.x, glm::vec(1,0,0);
m_GlobalOrientation *= glm::rotate(m_GlobalRotation.y, glm::vec(0,1,0);
m_GlobalOrientation *= glm::rotate(m_GlobalRotation.z, glm::vec(0,0,1);
但是只有 x 旋转是全局方向,y 和 z 旋转是局部方向,因为它已经绕 x 轴旋转了。所以我需要一次旋转所有 3 个角度(?)
翻译本地应该只是将翻译值添加到当前翻译,本地翻译应该是 glm::inverse(m_Orientation) * translationVector 对吗?
最佳答案
在我回答你的问题之前,让我解释一下矩阵的一些核心概念。
假设我们有以下矩阵:
其中 T
是平移矩阵,R
是旋转矩阵。
当我们使用这个矩阵来变换一个顶点(甚至网格)时,会有一个唯一的结果。然而,我们可以借助两种解释得出这个结果:
解释一:从右向左求值
如果我们从右到左评估矩阵,则所有变换都在全局坐标系中执行。因此,如果我们变换位于原点的三角形,我们会得到以下结果:
解读二:从左到右求值
在另一种情况下,所有变换都在局部坐标系中执行:
当然,我们得到了相同的结果。
所以回到你的问题。如果将对象的位置和方向存储为矩阵T
。您可以通过将旋转矩阵乘以当前矩阵的右侧来在其局部坐标系中旋转该对象。并在全局系统中将其乘以左侧。这同样适用于翻译:
void Rotate(float x, float y, float z, bool localOrientation)
{
auto rotationMatrix = glm::rotate(x, glm::vec3(1,0,0));
rotationMatrix *= glm::rotate(y, glm::vec3(0,1,0));
rotationMatrix *= glm::rotate(z, glm::vec3(0,0,1));
if(localOrientation)
this->T = this->T * rotationMatrix;
else
this->T = rotationMatrix * this->T;
}
右/前/上 vector 是矩阵 T
的列 vector 。您可以直接读取它们,也可以通过将矩阵与 (1, 0, 0, 0)
(右)、(0, 1, 0, 0)
相乘来获取它们(向上),(0, 0, 1, 0)
(用于/向后)或 (0, 0, 0, 1)
(位置)。
如果您想阅读更多相关信息,请查看我的 blog article about matrices in DirectX .但它适用于使用转置矩阵的 DirectX。因此矩阵顺序颠倒。阅读文章时请注意这一点。
关于c++ - 使用 glm 在本地和全局方向上旋转和平移对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21923482/