I'm writing an OpenGL application (C# and OpenTK) and I'm confused about how OpenGL transformations work.
I've set up a perspective projection and I'm at the default location with the default orientation (+X to the right, +Y up, +Z coming at me.) Now I draw a quad in my XY plane, on the Z-axis at -10.
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();
This works as expected. But now I want to rotate the quad along its local Y-axis, so I added in a rotate, which is being applied to my identity matrix. Here's the relevant section of code:
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Rotate(10, 0, 1, 0);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();
But this will rotate the plane around my "world" Y-axis, so now the plane is no longer speared through my -Z axis, but it's at an angle.
Question
How can I keep the object at the desired location (at -10 along my Z axis) but have it rotated about its own axis?
What I've tried
I've tried first translating to the origin, performing the rotation, drawing, then moving back, but this doesn't work either, presumably because once I've rotated, now I'm no longer translating along the "world" axis, but the rotated axis. This is the code:
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
GL.Translate(0, 0, 10);
GL.Rotate(10, 0, 1, 0);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();
GL.Translate(0, 0, -10);
I have a feeling I need to be using PushMatrix
and PopMatrix
, but I'm not quite sure I understand how they come into play. If I push my matrix before performing any operations, then pop it, shouldn't my view return back to normal? If so, why doesn't this work:
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
// Push current matrix onto the stack
GL.PushMatrix();
// Perform operations on newly pushed matrix
GL.Translate(0, 0, 10);
GL.Rotate(10, 0, 1, 0);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();
// Pop it off, so return to my previous matrix
GL.PopMatrix();