Rotate and translate object in local and global orientation using glm

C0dR picture C0dR · Feb 21, 2014 · Viewed 10.7k times · Source

i am trying to implement functions, where i can rotate/ translate an object in local or global orientation, like in 3D modeling software, using glm. Something like this:

void Rotate(float x, float y, float z, bool localOrientation);

but I dont know how to get it working. Local rotation rotation should just be something like this(?):

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)

But how to combine this with local orientation? Actually i need to rotate the rotation matrix in world orientation, right? I hope you know what i mean with local and global oriented rotation/translation, like it is in 3D modeling programs. In most of them you have a button to switch between local and global.

And how would i calculating the forward/right/up vector then? normally it should be something like this, right?:

forward = m_Orientation * glm::vec4(0,0,-1,0);

I tried global rotation with this:

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);

but then only x rotation is in global orientation, y and z rotation is in local orientation, since it is already rotated around x axis. So I need to rotate all 3 angles at once(?)

Translating local should just be adding translation values to current translation, and local translation should be glm::inverse(m_Orientation) * translationVector right?

Answer

Nico Schertler picture Nico Schertler · Feb 27, 2014

Before I come to your question, let me explain some core concepts of matrices.

Assume that we have the following matrix:

Matrix

wher T is a translation and R is a rotation matrix.

When we use this matrix to transform a vertex (or even mesh), there is one unique result. However, we can get to this result with the help of two interpretations:

Interpretation 1: Evaluate from right to left

If we evaluate the matrix from right to left, all transformations are performed in the global coordinate system. So if we transform a triangle that sits at the origin, we get the following result:

Transformation from right to left

Interpretation 2: Evaluate from left to right

In the other case, all transformations are performed in the local coordinate system:

Transformation from left to right

Of course, we get the same result.

So coming back to your question. If you store the position and orientation of the object as a matrix T. You can rotate this object in its local coordinate system by multiplying a rotation matrix to the right side of the current matrix. And in the global system by multiplying it at the left side. The same applies for translation:

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;
}

The right / forward / up vectors are the column vectors of the matrix T. You can either read them directly or get them by multiplying the matrix with (1, 0, 0, 0) (right), (0, 1, 0, 0) (up), (0, 0, 1, 0) (for/backward) or (0, 0, 0, 1) (position).

If you want to read more about this, take a look at my blog article about matrices in DirectX. But it's for DirectX, which uses transposed matrices. Therefore the matrix order is reversed. Watch out for that when reading the article.