Advertisement

How to rotate a cube properly?

Started by October 25, 2018 10:17 PM
10 comments, last by Zakwayda 5 years, 10 months ago

So, I've noticed that when you rotate a cube in local coordinates you somehow rotate the axis as well. If you try to rotate a cube 90 degrees on the x axis and then try constantly rotating it on the y axis, you will see the cube rotating on the z axis instead of y. In order to give you a better understanding for my problem, check the following:

Rotating the cube on the Y axis with initial rotation (0,0,0)

  

Rotating the cube on the y Axis with initial rotation (90,0,0)

 

 In the second video, I was expecting to see the cube rotating around the Y axis, not the Z. This is exactly the effect that you get if with the initial rotation (90,0,0) the Y axis rotates as well (and now lying on the floor ) becoming the Z axis. Is this what is actually happening? So how can I rotate the cube without rotating the actual local Axis (Just rotating the cube around the Axis in local space)?

This is how I rotate the cube before I draw:


//Initialize the mvp transformations.
glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view  = glm::mat4(1.0f);
glm::mat4 proj  = glm::mat4(1.0f);

//Translate.
model = glm::translate(model, m_pos);

//Rotate the model.
model = glm::rotate(model, glm::radians(m_rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::rotate(model, glm::radians(m_rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, glm::radians(m_rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));

//Scale.
model = glm::scale(model, m_scale);

//View.
view = m_core->m_cam->GetView();

//Projection.
proj = glm::perspective(glm::radians(m_core->m_cam->m_fov), (float)m_core->m_width / m_core->m_height, 0.1f, 100.0f);

//Set the tranformation matrices on the shader.
m_program->SetUniformMat4f("model", model);
m_program->SetUniformMat4f("view", view);
m_program->SetUniformMat4f("proj", proj);

//Draw Call.
glDrawArrays(GL_TRIANGLES, 0, 36);

 

And inside the vertex shader you can guess what I'm doing:


gl_Position = proj * view * model * vec4(aPos, 1.0f);

 

My mind goes to the same technique I learned about the camera system. There, I learned that I had to create 3 vectors (up, left and front) which actually are going to define a new coordinate system with origin the center of the camera. Do I have to do the same thing here? Each cube will have 3 vectors which they define a new coordinate system with origin the center of the cube (this will be the local coordinate system of the cube) and then use somehow these vectors to rotate the cube accordingly.

Can you give me some examples?

 

Thank you!


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

What are your values for m_rotation.x, m_rotation.y and m_rotation.z for video 1 and again for video 2?

A rotation on y followed by a 90 degree rotation on x will look like a z rotation.

🙂🙂🙂🙂🙂<←The tone posse, ready for action.

Advertisement
27 minutes ago, fleabay said:

What are your values for m_rotation.x, m_rotation.y and m_rotation.z for video 1 and again for video 2?

Video One:


//Initialization
m_rotation.x  = 0.0f;
m_rotation.y  = 0.0f;
m_rotation.z  = 0.0f;

//Is getting called every frame
MainGameLoop()
{
	m_rotation.y += delta_time;
}

Video Two:


//Initialization
m_rotation.x  = 90.0f;
m_rotation.y  = 0.0f;
m_rotation.z  = 0.0f;

//Is getting called every frame
MainGameLoop()
{
	m_rotation.y += delta_time;
}

 

Quote

A rotation on y followed by a 90 degree rotation on x will look like a z rotation.

So actually what you are saying is that what I see on the second video is the expected behavior? There's nothing wrong?


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

When you calculate your model matrix, the rotation part, you have Z*Y*X?

🙂🙂🙂🙂🙂<←The tone posse, ready for action.

12 minutes ago, fleabay said:

When you calculate your model matrix, the rotation part, you have Z*Y*X?

I don't understand what do you mean with that. If you mean the order of rotations, first I rotate on the X axis then Y and finally Z.


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

Matrix operations are post multiply. Try reversing those 3 lines so it is Z, Y, and finally X. It's damn confusing I know.

🙂🙂🙂🙂🙂<←The tone posse, ready for action.

Advertisement
23 minutes ago, fleabay said:

Matrix operations are post multiply. Try reversing those 3 lines so it is Z, Y, and finally X. It's damn confusing I know.

Yes now it works! But still when I rotate the cube in all axis using the code below:


//Initialization
m_rotation.x  = 0.0f;
m_rotation.y  = 0.0f;
m_rotation.z  = 0.0f;

//Is getting called every frame
MainGameLoop()
{
  	m_rotation.x += delta_time;
	m_rotation.y += delta_time;
  	m_rotation.z += delta_time;
}

I get this behavior:

Is this behavior what I should expected? When you rotate in all axis is difficult to understand what is the total rotation...

It seems like the cube change directions and then start's to rotate backwards that it did in the beginning.


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

That looks about right for any rotation order. :)

🙂🙂🙂🙂🙂<←The tone posse, ready for action.

A couple comments in addition to what fleabay has said:

Quote

My mind goes to the same technique I learned about the camera system. There, I learned that I had to create 3 vectors (up, left and front) which actually are going to define a new coordinate system with origin the center of the camera. Do I have to do the same thing here? Each cube will have 3 vectors which they define a new coordinate system with origin the center of the cube (this will be the local coordinate system of the cube) and then use somehow these vectors to rotate the cube accordingly.

It sounds like maybe you want incremental rotations rather than 'from scratch' rotations.

What you're doing now is building the orientation of the object from scratch each frame using a triplet of angles (often called Euler angles). This approach is fine for some purposes, but it can produce counterintuitive results like gimbal lock (what you're seeing in your second example) or the 'wobbly' rotations you're seeing in your later example.

An alternative is to store the object's orientation from frame to frame, and modify the orientation as needed. Common ways to store the orientation would be a matrix or a quaternion. Each update, you apply whatever rotation you want to the orientation, and then incorporate the orientation into the transform for that frame (which will also incorporate e.g. scale and translation). Typically you'll also want to normalize the orientation periodically to prevent drift.

You could also use three vectors, as you mentioned, but that's basically the same as using a matrix, and given that you already have matrix rotation functions available, it seems like it would make sense to take advantage of them.

35 minutes ago, Zakwayda said:

A couple comments in addition to what fleabay has said:

It sounds like maybe you want incremental rotations rather than 'from scratch' rotations.

What you're doing now is building the orientation of the object from scratch each frame using a triplet of angles (often called Euler angles). This approach is fine for some purposes, but it can produce counterintuitive results like gimbal lock (what you're seeing in your second example) or the 'wobbly' rotations you're seeing in your later example.

An alternative is to store the object's orientation from frame to frame, and modify the orientation as needed. Common ways to store the orientation would be a matrix or a quaternion. Each update, you apply whatever rotation you want to the orientation, and then incorporate the orientation into the transform for that frame (which will also incorporate e.g. scale and translation). Typically you'll also want to normalize the orientation periodically to prevent drift.

You could also use three vectors, as you mentioned, but that's basically the same as using a matrix, and given that you already have matrix rotation functions available, it seems like it would make sense to take advantage of them.

So this is what quaternions do in game engines like unity3D? Oh i didn't know that, so actually I'm not there yet.

So in other words I'm rushing to things I haven't seen yet.

I searched it a little and I found out that quaternions are actually mathematics (extension of the complex numbers to 4 dimensions). Well I have a really good background in mathematics but never new that quaternions are actual maths. It seem like I have to study and learn them 


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

This topic is closed to new replies.

Advertisement