30 Nov 2015, 12:09
Hi Flávio,
It looks like you would carry the axis but in fact it is the order of transformations that is the important factor. Keep in mind that the order of transformations is not associative. Let me explain it with a simple example using the example code you have provided.
I’m pressing 8 times the UP ARROW key to rotate the cube by 90° around the X axis (in world space).
Next I am pressing 8 times the RIGHT ARROW key to rotate the cube by 90° around the Y axis (in world space).
Now I’m again pressing two times the UP ARROW key.
What you probably want is that the cube now should again rotate around the X axis (in world space) but what actually happens, is that the cube is rotating around the Z axis (in world space). It looks like the cube has carried its X axis and is rotating around its local model space X axis which is the same direction as world space Z axis.
Now why does this happen? Let’s take a look at your code. You are using two transformation matrices and apply Mx first and My second. Mx rotates the cube around the X axis first and My rotates the cube around the y axis second. If you press the UP ARROW key you just increase the first x axis rotation.
What you want is:
What you do is:
No method can guess that you want to rotate 90x, 90y, 22.5x if you just give two angles 112.5x and 90y. The rotation method you are expecting cannot exist.
To solve the problem you have to apply the delta rotation and not the absolute angle. Here is the needed code change:
I hope that addresses your problem.
Best regard, Ketschak
It looks like you would carry the axis but in fact it is the order of transformations that is the important factor. Keep in mind that the order of transformations is not associative. Let me explain it with a simple example using the example code you have provided.
I’m pressing 8 times the UP ARROW key to rotate the cube by 90° around the X axis (in world space).
Next I am pressing 8 times the RIGHT ARROW key to rotate the cube by 90° around the Y axis (in world space).
Now I’m again pressing two times the UP ARROW key.
What you probably want is that the cube now should again rotate around the X axis (in world space) but what actually happens, is that the cube is rotating around the Z axis (in world space). It looks like the cube has carried its X axis and is rotating around its local model space X axis which is the same direction as world space Z axis.
Now why does this happen? Let’s take a look at your code. You are using two transformation matrices and apply Mx first and My second. Mx rotates the cube around the X axis first and My rotates the cube around the y axis second. If you press the UP ARROW key you just increase the first x axis rotation.
What you want is:
- ROTATE X 90°
- ROTATE Y 90°
- ROTATE X 22.5°
What you do is:
- ROTATE X 112.5°
- ROTATE Y 90°
No method can guess that you want to rotate 90x, 90y, 22.5x if you just give two angles 112.5x and 90y. The rotation method you are expecting cannot exist.
To solve the problem you have to apply the delta rotation and not the absolute angle. Here is the needed code change:
void App::ColorCubeLogic::TransformCube(const Logic::IState* state)
{
Graph::Matrix& cubeTransform = mCubeTransform->GetTransform();
//cubeTransform.SetIdentity();
mAngleX = Math::Fmod(mAngleX, Math::TWO_PI);
mAngleY = Math::Fmod(mAngleY, Math::TWO_PI);
Graph::Matrix Mx(Matrix::IDENTITY);
Mx.SetRotationComponentX(mAngleX);
cubeTransform = Mx * cubeTransform;
Graph::Matrix My(Matrix::IDENTITY);
My.SetRotationComponentY(mAngleY);
cubeTransform = My * cubeTransform;
debugMsg += Util::DoubleToString(mAngleX) + " / " +
Util::DoubleToString(mAngleY);
state->SetUserDebugMessage(debugMsg);
}
void App::ColorCubeLogic::OnProcessTick(const Logic::IState* state)
{
Logic::IDeviceHandler* deviceHandler = state->GetDeviceHandler();
mAngleX = 0;
mAngleY = 0;
if (deviceHandler->WasRawKeyPressed(RAWKEY_UP_ARROW)) {
debugMsg = "Angle X +" + Util::DoubleToString(mSpinSpeed) + "-> ";
mAngleX += mSpinSpeed;
TransformCube(state);
}
else if (deviceHandler->WasRawKeyPressed(RAWKEY_DOWN_ARROW)) {
debugMsg = "Angle X -" + Util::DoubleToString(mSpinSpeed) + "-> ";
mAngleX -= mSpinSpeed;
TransformCube(state);
}
else if (deviceHandler->WasRawKeyPressed(RAWKEY_LEFT_ARROW)) {
debugMsg = "Angle Y -" + Util::DoubleToString(mSpinSpeed) + "-> ";
mAngleY -= mSpinSpeed;
TransformCube(state);
}
else if (deviceHandler->WasRawKeyPressed(RAWKEY_RIGHT_ARROW)) {
debugMsg = "Angle Y +" + Util::DoubleToString(mSpinSpeed) + "-> ";
mAngleY += mSpinSpeed;
TransformCube(state);
}
}
I hope that addresses your problem.
Best regard, Ketschak