Simple transformation problem

Servus!

I just started to use the OpenGL API.
The problem I can’t solve currently is about transformations.
Yes, I know that it was discussed before, but these discussions in this forum couldn’t really help me.

I want to rotate around two axes.
The problem is that my program rotates with the identity matrix when I call glRotatef.
But I want to rotate using the current model view matrix.

Thanks for your help!

Servus.

Prior to any rotations (translations, scales, whatever) all you have is an identity matrix.

rotate your object about the first axis, then rotate it about the second axis (um…and don’t call glLoadIdentity()).

could you post some code showing what you’re doing?

Not sure if it is your case but you can reverse the order of your rotations.
It is a common problem due to matrix multiplications.
And are you sure there is no glLoadIdentity where you don’t need it ?

The current modelview matrix is the transformed one before I make the glrotatef calls. I checked it with glGetFloatv.

I call

glRotatef((float)xangle , 1.0f, 0.0f, 0.0f);
glRotatef((float)yangle , 0.0f, 1.0f, 0.0f);


glPushMatrix()
glTranslatef(…)
drawStuff
glPopMatrix()

glPushMatrix()
glTranslatef(…)
drawStuff
glPopMatrix()

The result is that it’s rotating around the (1,0,0) and (0,1,0) vector that belongs to the identity matrix, but not the current modelview matrix. But I want that the rotation transformation is using the current modelview matrix.

Do you have any transformations going on before this ?:

  

glRotatef((float)xangle , 1.0f, 0.0f, 0.0f);
glRotatef((float)yangle , 0.0f, 1.0f, 0.0f);

If you don’t, all you have is an identity modelview matrix and everything is happening exactly as it should. If you’re saying that you’re getting the modelview matrix right before those glRotatef calls and it’s not coming up as the identity but your glRotatef calls are producing results as if it where, well then I’m at a total loss as that’s sort of…well…impossible.

Sorry, I’m a bit thick-headed and it’s not so clear as to what you’re trying to accomplish.

EDIT: remember also that the results of one glRotatef call change your coordinate system.
a rotate about the x axis by 90 degrees for example would effectively swap your y and z axes.
is this the unexpected behavior you’re seeing?

This is what I am doing:

void RenderFrame(void)
{
   glClear(...);
   glMatrixMode(GL_MODELVIEW);
   
   glGetFloatv(GL_MODELVIEW_MATRIX, Current_MV_Matrix);

   if(rotate_x)
   {
      glRotatef((float)Angle_x, 1.0f, 0.0f, 0.0f);
      Angle_x = 0;
      rotate_x = FALSE;
   }
   else
   {
      glRotatef((float)Angle_y, 0.0f, 1.0f, 0.0f);
      Angle_y = 0;
      rotate_x = TRUE;
   }

   glPushMatrix();
   glTranslatef(...);
   drawStuff;
   glPopMatrix();
   
   glPushMatrix();
   glTranslatef(...);
   drawStuff;
   glPopMatrix();
}

“Current_MV_Matrix” gives me the identity matrix for the first frame and in all other frames the transformed ones.

The result is that I don’t rotate around the (1,0,0) and (0,1,0) vectors of the translated modelview matrix like I wanted, but around the identity modelview matrix vectors.

Please give me a note if you need more details.

where else are you setting Angle_x and Angle_y ?

On the first frame you haven’t done any transformations yet, so it makes sense that you have the identity modelview.

after that, if you aren’t setting Angle_x and/or Angle_y each frame outside of Display() you’re rotating by 0 degrees each frame.

These variables are global (just for testing) and are changed dynamically (by mouse-input).

PLEASE HEEELLLP!
It’s driving me cracy. :-/

There is no obvious error in the code that you provided, so it must be somewhere else in your code.

You cast Angle_x/Angle_y to an float which makes me think they are probably integers. Maybe you are calculating them wrong? If you do something like:

int Angle_x = 12/11;

The result will be 0 and hence there will be no rotation. Or perhaps rotate_x/rotate_y is always false…

This is where the debugger comes in handy. Set breakpoints to your glRotate() calls and check what values you are passing to OpenGL.

Try calling glRotatef after glTranslatef.

Greetz,

Nico

Originally posted by -NiCo-:
Try calling glRotatef after glTranslatef.

Except this doesnt explain why the modelview transform still equals identity, does it?

RTFP next time.

Some annotated code:

void RenderFrame()
{   
    glClear(...);   
     
    // Setup the camera FIRST.
    
    // Setup the camera projection.
    // (Just an example here)
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective( 60, viewAspectRatio, 1, 1000 );
   
    // Now, create a matrix that positions the 
    // camera in world-space, then invert it. 
    // In other words, apply everything you 
    // would to position the camera in the 
    // world, only in reverse. This has the 
    // effect of transforming everything in 
    // world-space into camera-space.
    // As an example, say you wanted an 
    // arbitrary rotation (Rx,Ry,Rz) at the 
    // origin, followed by a translation
    // into the world (typical first-person view): 
    glMatrixMode(GL_MODELVIEW);  
    glLoadIdentity();    
    glRotatef(-Camera_World_Angle_z, 0, 0, 1);
    glRotatef(-Camera_World_Angle_y, 0, 1, 0);
    glRotatef(-Camera_World_Angle_x, 1, 0, 0);   
    glTanslatef( -Camera_World_x, -Camera_World_y, -Camera_World_z );
    
    // Now ready to transform and draw objects.
     
    // For each object, first push the camera 
    // matrix. 
    glPushMatrix();   
        
    // The first object transform is always 
    // relative to the local object coordinate 
    // system, by definition. 
    // If you want a particular orientation,   
    // this is the place to apply it. For 
    // example, if you're drawing a tank, then 
    // you might transform the body into the 
    // world here.
        
    // Now, draw the object ...
  
    // If you want a subsequent transform 
    // relative to a previous one, then push 
    // the current modelview again, apply the 
    // transforms, draw, then pop. 
    // For the tank, you might want a turret 
    // here, so you could push the matrix, apply 
    // the turret transform, draw, then pop. Then
    // you could repeat this process for the 2 
    // tracks, and so on, all parts relative 
    // to initial body transform.
  
    // This is how skeletal animation is 
    // performed too, by transforming each bone 
    // relative to the last.
    glPopMatrix();      
}

edit: Tried to clarify a few things.

Originally posted by <Somebodyelse>:
[b] [quote]Originally posted by -NiCo-:
Try calling glRotatef after glTranslatef.

Except this doesnt explain why the modelview transform still equals identity, does it?

RTFP next time.[/b][/QUOTE]

The current modelview matrix is the transformed one before I make the glrotatef calls. I checked it with glGetFloatv.

The result is that it’s rotating around the (1,0,0) and (0,1,0) vector that belongs to the identity matrix, but not the current modelview matrix.
He checked it and the modelview transform does not equal identity. He says the rotation is about the identity axes but said nothing about translation. If you postmultiply the translation calls with the rotation calls like he did, the rotation is performed around the axes of the camera coordinate frame, which correspond to the ones of the identity matrix.

I suggest you RTFP next time <Somebodyelse>.

Nico

Sorry, I still haven’t found it out:

This is the OpenGL initialization that I do only once:

void InitGL(void)
{
	glViewport(0, 0, 1280, 1024);								// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);								// Select The Projection Matrix
	glLoadIdentity();											// Reset The Projection Matrix

	glFrustum(-2.0f, 2.0f, -1.5f, 1.5f, 4.0f, 100000.0f);		// !!! Assuming a Aspect-Ratio of 4:3 !!!
		
	glMatrixMode(GL_MODELVIEW);									// Select The Modelview Matrix

	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);											// Depth Buffer Setup
	glDepthFunc(GL_LESS);										// The Type Of Depth Testing To Do
	glEnable(GL_DEPTH_TEST);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	
}

I simplified my Frame rendering code even more:

void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glFrustum(-2.0f, 2.0f, -1.5f, 1.5f, 4.0f, 100000.0f);
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

	glRotatef((float)xmouseD , 0.0f, 1.0f, 0.0f);
	glRotatef((float)ymouseD , 1.0f, 0.0f, 0.0f);

	

	glPushMatrix();
	glTranslatef(-1800.0f, 0.0f, -3000.0f);
	glBegin(GL_QUADS);
		glVertex3f(-250000.0f, -500.0f,  -250000.0f);
		glVertex3f( 250000.0f, -500.0f,  -250000.0f);
		glVertex3f( 250000.0f, -500.0f,  250000.0f);
		glVertex3f(-250000.0f, -500.0f,  250000.0f);
	glEnd();
	glPopMatrix();
}

I still get the same result that correct rotations are only performed, when the “camera-vector” is the same as the one when no transformations have been performed at all.

Usually you load the identity matrix at the start of each frame. So your function should look:
void RencerFrame()
{
glClear(…);
glLoadIdentity();
//rest goes here
glFlush();
SwapBuffers();
}
The reason we do this is that it is less expensive computationaly to draw our object in a new position each frame, than to try to move the object from its last position which is what you’re doing. So remember, at the start of each frame, there should be a glClear, glLoadIdentity call.

Thanks for the performance tip my code looks like this now:

void InitGL(void)
{
	glViewport(0, 0, 1280, 1024);								// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);								// Select The Projection Matrix
	glLoadIdentity();											// Reset The Projection Matrix

	glFrustum(-2.0f, 2.0f, -1.5f, 1.5f, 4.0f, 100000.0f);		// !!! Assuming a Aspect-Ratio of 4:3 !!!
		
	glMatrixMode(GL_MODELVIEW);									// Select The Modelview Matrix

	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);											// Depth Buffer Setup
	glDepthFunc(GL_LESS);										// The Type Of Depth Testing To Do
	glEnable(GL_DEPTH_TEST);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	
}


void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glRotatef((float)xmouseD , 0.0f, 1.0f, 0.0f);
	glRotatef((float)ymouseD , 1.0f, 0.0f, 0.0f);

	glPushMatrix();
	glTranslatef(-1800.0f, 0.0f, -3000.0f);
	glBegin(GL_QUADS);
		glVertex3f(-250000.0f, -500.0f,  -250000.0f);
		glVertex3f( 250000.0f, -500.0f,  -250000.0f);
		glVertex3f( 250000.0f, -500.0f,  250000.0f);
		glVertex3f(-250000.0f, -500.0f,  250000.0f);
	glEnd();
	glPopMatrix();

	glFlush();
}

And the problem still exists.

I can see nowhere else that you might be making an error except on the calculations of your rotation angles. when are they calculated and how?

Using a debugger: can you verify that your values for xmouseD and/or ymouseD are not 0?

and you’re not calling glMatrixMode(GL_PROJECTION) anywhere besides your init, right?

Try this:

void InitGL(void)
{
	glViewport(0, 0, 1280, 1024);								// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);								// Select The Projection Matrix
	glLoadIdentity();											// Reset The Projection Matrix

	glFrustum(-2.0f, 2.0f, -1.5f, 1.5f, 4.0f, 100000.0f);		// !!! Assuming a Aspect-Ratio of 4:3 !!!
		
	glMatrixMode(GL_MODELVIEW);									// Select The Modelview Matrix

	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);											// Depth Buffer Setup
	glDepthFunc(GL_LESS);										// The Type Of Depth Testing To Do
	glEnable(GL_DEPTH_TEST);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	
}


void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	glTranslatef(-1800.0f, 0.0f, -3000.0f);
	glRotatef((float)xmouseD , 0.0f, 1.0f, 0.0f);
	glRotatef((float)ymouseD , 1.0f, 0.0f, 0.0f);
        glBegin(GL_QUADS);
		glVertex3f(-250000.0f, -500.0f,  -250000.0f);
		glVertex3f( 250000.0f, -500.0f,  -250000.0f);
		glVertex3f( 250000.0f, -500.0f,  250000.0f);
		glVertex3f(-250000.0f, -500.0f,  250000.0f);
	glEnd();
	
	glFlush();
}

It’s working finally! :slight_smile:

I tried to exchange the rotation calls before with the code that didn’t load the identity matrix at start of each frame and it didn’t help.

But with the new code that performs all previous rotation (and the new ones) for each frame on the identity matrix again is working correctly when the rotation calls are exchanged.

What is the reason behind this?

Big thanks for your patience to help me!