# How should I rotate vertices around the origin on the CPU?

I have tried using glm::rotate and such. glm::translate works fine, but rotate doesn't work (if I rotate before/after a translation).

Here is my current setup:

glm::vec4 Off = glm::vec4(0, 0, 0, 1);
glm::vec4 result = Util::createTransform(offset) * Off;

for (int i = 0; i < Tvertex.size(); i++) {
Tvertex[i] += glm::vec3(result.x, result.y, result.z);
Tcolors[i] = currentColor;
}


And here is my Util::createTransform:

glm::mat4 Util::createTransform(glm::vec3 pos) {
glm::mat4 trans = glm::mat4(1.0);
trans = glm::translate(trans, pos);
return trans;
}

glm::mat4 Util::createTransform(glm::vec3 pos, glm::vec3 rot) {
glm::mat4 trans = glm::mat4(1.0);
trans = glm::rotate(trans, glm::radians(rot.x), glm::vec3(1, 0, 0));
trans = glm::rotate(trans, glm::radians(rot.y), glm::vec3(0, 1, 0));
trans = glm::rotate(trans, glm::radians(rot.z), glm::vec3(0, 0, 1));
trans = glm::translate(trans, pos);
return trans;
}

• What is your intention here? createTransform seems to take two parameters but you supply only one in your call. What is offset in the first code block? Jan 17, 2016 at 16:34
• Ah, I have another createTransform that only takes in a position.
– user68817
Jan 17, 2016 at 16:41
• Multiply all the vertices by the transformation matrix? (IIRC the transformation matrix needs to be on the left of the multiply, so note that you can't use *=) Jan 18, 2016 at 3:50

It's unclear where your issue lies.

To rotate a vector about the origin, you create a rotation matrix, and then you multiply the vertex by the matrix. In order to create the rotation matrix, you need a rotation axis and an angle.

With glm, you can do it this way:

glm::vec3 v3RotAxis( 0.0f, 0.0f, 1.0f ); // Rotate about z+
float angleRad = glm::half_pi<float>(); // Rotate of a quarter of a turn
glm::mat4x4 matRot = glm::rotate( angleRad, v3RotAxis );


Alternatively, you can use a quaternion:

glm::quat quatRot = glm::angleAxis( angleRad, v3RotAxis );
glm::mat4x4 matRot = glm::mat4_cast( quatRot );


To apply this to a vertex (a point in space), you would then do:

glm::vec4 out = matRot * v4In;


If you need to rotate about a point that is not the origin, you have to

1. translate the pointToRotate to the origin
2. perform the rotation
3. translate back the point to the original location

To achieve that, you create a translation matrix, and an inverse of that translation. You then 'sandwich' the rotation matrix in-between these other two:

glm::vec4
rotateAround(
glm::vec4 aPointToRotate,
glm::vec4 aRotationCenter,
glm::mat4x4 aRotationMatrix )
{
glm::mat4x4 translate =
glm::translate(
glm::mat4(),
glm::vec3( aRotationCenter.x, aRotationCenter.y, aRotationCenter.z ) );
glm::mat4x4 invTranslate = glm::inverse( translate );

// The idea:
// 1) Translate the object to the center
// 2) Make the rotation
// 3) Translate the object back to its original location

glm::mat4x4 transform = translate * aRotationMatrix * invTranslate;

return transform * aPointToRotate;
}


Keep in mind that with all the operations done with matrices, the order is important.

I join the whole test program if you want to play with stuff.

#include <iostream>

#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/transform.hpp>

glm::vec4
rotateAround(
const glm::vec4&   aPointToRotate,
const glm::vec4&   aRotationCenter,
const glm::mat4x4& aRotationMatrix )
{
glm::mat4x4 translate =
glm::translate(
glm::mat4(),
glm::vec3( aRotationCenter.x, aRotationCenter.y, aRotationCenter.z ) );
glm::mat4x4 invTranslate = glm::inverse( translate );

// The idea:
// 1) Translate the object to the center
// 2) Make the rotation
// 3) Translate the object back to its original location

glm::mat4x4 transform = translate * aRotationMatrix * invTranslate;

return transform * aPointToRotate;
}

int main( void )
{
{
glm::vec4 v4In( 2.0f, 0.0f, 0.0f, 1.0f );
glm::vec4 v4RotCenter( 1.0f, 0.0f, 0.0f, 1.0f );
glm::vec3 v3RotAxis( 0.0f, 0.0f, 1.0f );
glm::mat4x4 matRot = glm::rotate( angleRad, v3RotAxis );
glm::vec4 out = rotateAround( v4In, v4RotCenter, matRot );
std::cout << out.x << " " << out.y << " " << out.z << " " << out.w << " " <<std::endl;
}

{
glm::vec4 v4In( 2.0f, 0.0f, 0.0f, 1.0f );
glm::vec3 v3RotAxis( 0.0f, 0.0f, 1.0f );