使用glm以局部和全局方向旋转和平移对象

时间:2014-02-21 01:37:46

标签: c++ opengl math rotation glm-math

我正在尝试实现函数,我可以使用glm在局部或全局方向上旋转/平移对象,就像在3D建模软件中一样。像这样:

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建模程序中一样。在大多数情况下,你有一个按钮可以在本地和全球之间切换。

那么我如何计算前进/右/向上矢量呢? 通常它应该是这样的,对吧?:

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对吗?

1 个答案:

答案 0 :(得分:15)

在我提出你的问题之前,让我解释一下矩阵的一些核心概念。

假设我们有以下矩阵:

Matrix

wher T是翻译,R是轮换矩阵。

当我们使用这个矩阵来变换顶点(甚至是网格)时,有一个唯一的结果。但是,我们可以借助两种解释来得到这个结果:

解读1:从右到左进行评估

如果我们从右到左评估矩阵,则所有变换都在全局坐标系中执行。因此,如果我们变换位于原点的三角形,我们得到以下结果:

Transformation from right to left

解读2:从左到右进行评估

在另一种情况下,所有转换都在本地坐标系中执行:

Transformation from left to right

当然,我们得到了相同的结果。

回到你的问题。如果将对象的位置和方向存储为矩阵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;
}

右/前/上向量是矩阵T的列向量。您可以直接阅读它们,也可以通过将矩阵乘以(1, 0, 0, 0)(右),(0, 1, 0, 0)(向上),(0, 0, 1, 0)(用于/向后)或(0, 0, 0, 1)(位置)来获取它们)。

如果您想了解更多相关信息,请查看我的blog article about matrices in DirectX。但它适用于使用转置矩阵的DirectX。因此,矩阵顺序是相反的。阅读文章时请注意这一点。