1

I try to rotate a .obj 3d model around its own axis using glRotatef. But it's not working as I wish.

Code

public void onDrawFrame(GL10 gl) {

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnable(GL10.GL_LIGHTING);
        gl.glLoadIdentity();

        gl.glTranslatef(0f, -1.2f, -z);
        gl.glRotatef(xrot, 1f, 0f, 0f);
        gl.glRotatef(yrot, 0f, 1f, 0f);

        model.draw(gl);
    }

Problem

The first rotation yrot works pretty good : no matter the position of the model, it always rotates around its own z (well, I ask to rotate around y so it's not perfect. But at least it uses one of its own axis!)

Now when I ask for 'xrot' it rotates around x screen axis. Not its own x. Does someone know why?

Remarks

  • I noticed that onDrawFrame is constantly running. However the model is not constantly translating by 1.2f on y. Only when z != 0. (I don't know why)..
  • I read we cound use trigonometry to get the right x vector. But this does not make sens to me. If the apps is able to keep in memory the position of the model to make right the yrot, why can't it do the same for xrot?
genpfault
  • 51,148
  • 11
  • 85
  • 139
Charbo
  • 11
  • 2

2 Answers2

1

Order of operations matters. The transformations in a chain of matrix multiplications (every OpenGL transformation call actually is just a matrix multiplication) act "in reverse", i.e. the very last transformation multiplied onto the transformation matrix is applied first. And each transformation acts on the "local" origin.

Your first transformation is a rotation about the y axis. Then the x axis rotation is applied, but this happens in the new local coordinate system.

Now when I ask for 'xrot' it rotates around x screen axis. Not its own x. Does someone know why?

In your particular chain of transformations the x axis rotation happens to align with the screen's x axis.

I noticed that onDrawFrame is constantly running. However the model is not constantly translating by 1.2f on y.

OpenGL is not a scene graph. It doesn't even "know" what models are. It just draws single points, lines and triangles, one at a time and that's it. If something changes in the scene, all has to be redrawn. The functions glRotate, glTranslate and so on, don't act on models. All they do is manipulate the values in the currently active transformation matrix. And when you finally draw something it's just this matrix that is used to transform the incoming vertex vectors (not just position, there are also matrices for other attributes in fixed function and when using shaders everything is possible). Anyway, when starting drawing a new frame you want to reset the matrices into a known state. That's what glLoadIdentity does. So every frame you start anew.

Only when z != 0. (I don't know why).

Probably the value of z gets integrated into some other variable somewhere else in your code at each iteration.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Thx for your return! I think I got the matter of the operation's order, due to non-commutative matrix multplication. You write "And each transformation acts on the "local" origin." It works for first rotation but it seems that for the second rotation it does not.. : no matter the object orientation, it will always rotate arouns x screen axis. – Charbo May 04 '16 at 11:35
  • I mean, after few random rotations, let's imagine the model is in some position. If now I ask for a pure yrot rotation, the model will turn around its z axis. -not bad- But if I asf for a pure xrot rotation, the model will turn around the x screen axis. -not good- I keep searching.. – Charbo May 04 '16 at 11:46
0

Here is a solution :

public void onDrawFrame(GL10 gl) {

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        gl.glEnable(GL10.GL_LIGHTING);

        if(flag==0) {
            gl.glLoadIdentity();
            gl.glTranslatef(0f, -1f, -z);
            flag=1; xrotold=0; yrotold=0;
        }
        else{
            float dxrot=xrot-xrotold;
            float dyrot=yrot-yrotold;

            gl.glRotatef(dxrot, 1f, 0f, 0f);
            gl.glRotatef(dyrot, 0f, 1f, 0f);

            yrotold=yrot;
            xrotold=xrot;
        }

        model.draw(gl);
    }

With this solution, we don't LoadIdentity every cycle. We keep the same matrix.

Then we calculate the infinitesimal rotations and apply them to the global matrix.

Thus, at any position of the model, we can turn around its local x or y axis.

Thank you datenwolf for showing me the right direction.

Charbo
  • 11
  • 2