Tuesday, December 19, 2017

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

Answer




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

#include
#include
#include

#include
#include


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 );
float angleRad = glm::half_pi();
glm::mat4x4 matRot = glm::rotate( angleRad, v3RotAxis );
glm::vec4 out = rotateAround( v4In, v4RotCenter, matRot );
std::cout << out.x << " " << out.y << " " << out.z << " " << out.w << " " < }

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

glm::vec3 v3RotAxis( 0.0f, 0.0f, 1.0f );
float angleRad = glm::half_pi();
glm::mat4x4 matRot = glm::rotate( angleRad, v3RotAxis );
glm::vec4 out = matRot * v4In;
std::cout << out.x << " " << out.y << " " << out.z << " " << out.w << " " < }
return 0;
}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...