Search code examples
c#openglquaternionsrotational-matricessharpgl

How to rotate objects in OpenGL relative to local or global axes


I'm asking a question that has been asked a million times before, but I still haven't found a good answer after going through these and also resorting to other sites:

How to rotate a graphic over global axes, and not to local axes?

rotating objects in opengl

How to rotate vertices exactly like with glRotatef() in OpenGL?

Rotate object about 3 axes in OpenGL

Rotate an object on its own axes in OpenGL

Is it possible to rotate an object around its own axis and not around the base coordinate's axis?

OpenGL Rotation - Local vs Global Axes

Task is relatively simple, I am making an sensor module with accelerometer and gyro onboard, and I need to display rotation.

I have a 3D model of the object in STL format, I've made an STL parser and I can visualise the object perfectly well.

When I try to rotate it I get all kinds of strange results.

I am using SharpGL (the Scene component).

I tried to write an "effect" that (for now) is controlled with 3 separate trackbars, but this will be the data from the sensors.

I wanted to do it as an effect because (in theory) I could have more objects in the scene and I only need to rotate a specific one (and also for educational purposes as I am relatively new to OpenGL).

I tried to rotate the object using quaternions, multiplying them and generating a rotation matrix, then applying gl.MultMatrix(transformMatrix.AsColumnMajorArray).

I also tried gl.Rotate(angleX, 1, 0, 0) (and similar for Y and Z axes).

Depending on the order of quaternion multiplication or gl.Rotate(...) statements, I would get the object to rotate about the local axis (first), something weird (second), and the "world" third. For example, if I did it with quaternions qX*qY*qZ and got the rotation matrix from that, I would get (I think) the rotations about a local X, "arbitrary" Y, and the world Z axes.

The part I cannot understand is that when I apply gl.Rotate(dx, 1, 0, 0) (and others for Y and Z rotations) inside the trackbar's Scroll event, the entire scene rotates about the X, Y, and Z axes and in that order, and exactly as I expected the rotation to happen.

My only issue with this approach is that the entire scene rotates. So if I (hypothetically) wanted to draw a room around the object, the whole room would rotate too, which is not what I want.

I will post any code requested, but I feel there is too much and the aforementioned links have similar code to what I have.

At the end of the day, I want my object (Polygon in SharpGL terms) to rotate about its own axes (or about the "world" axes, but be consistent).

EDIT:

I've placed the project in my dropbox: https://goo.gl/1LzNhn

If someone wants to look at it, any help will be greatly appreciated.

In the MainForm, the TbRotXYZScroll function has trackbar code and the Rotation class is where the problem resides (or so I think).

Rotate X, Y, and Z by say 45 degrees in that order. All seems to work great. Now rotate X, Y, and Z further by another 30 or so degrees, try to visualise about which axis the rotation is happening as you rotate...
X seems to be always world and Z seems to be always local, while Y is something in between (changing the order of rotation changes this).

Going into TbRotXYZScroll function and changing method to 2 does what I want (except the rotation of the entire scene). Tried quaternions and they produce the exact same result, so I must be doing something wrong...
Changing it to 1 produces similar result, but that is applying the rotation to the polygons alone (not what's being rendered as that includes local coordinate axes too).


Solution

  • At the end of the day, I want my object (Polygon in SharpGL terms) to rotate about its own axes (or about the "world" axes, but be consistent).

    I think this answer you put in your question is somehow explaining the situation. In order to perform rotation around object axis:

    1. Perform Translation/Rotation to your object and make the object axis overlap with one of base axis (x,y or z)

    2. Perform your rotation

    3. Revert your object back to its original position. (simply revert the translation/rotations at step1)

    Note: While doing that, one thing you should consider is openGL apply transformations from the reverse order.

    Example :

    glRotatef(90,1,0,0); 
    glTranslatef(-5,-10,5); 
    drawMyObject();
    

    In this case, opengl will first translate your object and then rotate. So while writing your transformations consider that. Here is my answer that may give you an idea.