I have the following code:
void setupCamera() {
// Clear the screen buffer
glClear(GL_COLOR_BUFFER_BIT);
// reset the projection matrix //
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// and set the perspective with the current field of view,
// and the current height and width
gluPerspective(fov, ratio, objDepth - objRadius * 2,
objDepth + objRadius * 2);
glViewport(0, 0, WINDOW_SIZE, WINDOW_SIZE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(first){
glMultMatrixf(rotMatrix);
}
first = true;
//translate everything to be in objDepth//
glTranslatef(initX * 0.01, initY * 0.01, (-1) * objDepth);
glRotatef(200 * angle, rotationVector[0], rotationVector[1],
rotationVector[2]);
glutWireTeapot(1.5);
glGetFloatv (GL_MODELVIEW_MATRIX, rotMatrix);
}
The rotation vector holds the rotation axis,
translate is used for moving all to the correct position.
the thing is, I am using glMultMatrixf in order to use the last matrix saved,
do rotation and then translation, and then save the matrix again with glGetFloatv.
this function is constantly called with timer, but for some reason
I can't figure out, the matrix wont save anything and always be initialized over and over,
meaning rotation is always used with small angles(because matrix isn't saved).
the saved matrix is not being used anywhere else in the code.
Any idea's?
Are you calling setupCamera() every tick? If you are, you may want to stop. You don't need to reset your projection matrix every frame and unless you NEED to, you don't need to reset your model view matrix either. Consider incrementing angle and your translation by itself rather than storing the whole matrix.
The steps you might want to take are:
1) Init matrices. Initialize projection to identity and use gluPerspective. Then switch to modelview and initialize it to identity as well. This should really only be done once.
2) In your update loop, increment your angle and translation on their representative variables.
3) In your draw loop, use glPushMatrix() to push the modelview matrix. Apply your matrix changes with gltranslate and glrotate then draw whatever it is you're drawing. After that, glPopMatrix() in order to return to identity.
I still don't really understand if you're trying to draw something and think that you need to read and store and restore the current glMatrix every frame or if you are actually trying to evaluate what OpenGL does to matrices and really DO need to read it out.
Related
The game is a top-down 2D space ship game -- think of "Asteroids."
Box2Dx is the physics engine and I extended the included DebugDraw, based on OpenTK, to draw additional game objects. Moving the camera so it's always centered on the player's ship and zooming in and out work perfectly. However, I really need the camera to rotate along with the ship so it's always facing in the same direction. That is, the ship will appear to be frozen in the center of the screen and the rest of the game world rotates around it as it turns.
I've tried adapting code samples, but nothing works. The best I've been able to achieve is a skewed and cut-off rendering.
Render loop:
// Clear.
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
// other rendering omitted (planets, ships, etc.)
this.OpenGlControl.Draw();
Update view -- centers on ship and should rotate to match its angle. For now, I'm just trying to rotate it by an arbitrary angle for a proof of concept, but no dice:
public void RefreshView()
{
int width = this.OpenGlControl.Width;
int height = this.OpenGlControl.Height;
Gl.glViewport(0, 0, width, height);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
float ratio = (float)width / (float)height;
Vec2 extents = new Vec2(ratio * 25.0f, 25.0f);
extents *= viewZoom;
// rotate the view
var shipAngle = 180.0f; // just a test angle for proof of concept
Gl.glRotatef(shipAngle, 0, 0, 0);
Vec2 lower = this.viewCenter - extents;
Vec2 upper = this.viewCenter + extents;
// L/R/B/T
Glu.gluOrtho2D(lower.X, upper.X, lower.Y, upper.Y);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
}
Now, I'm obviously doing this wrong. Degrees of 0 and 180 will keep it right-side-up or flip it, but any other degree will actually zoom it in/out or result in only blackness, nothing rendered. Below are examples:
If ship angle is 0.0f, then game world is as expected:
Degree of 180.0f flips it vertically... seems promising:
Degree of 45 zooms out and doesn't rotate at all... that's odd:
Degree of 90 returns all black. In case you've never seen black:
Please help!
Firstly the 2-4 arguments are the axis, so please state them correctly as stated by #pingul.
More importantly the rotation is applied to the projection matrix.
// L/R/B/T
Glu.gluOrtho2D(lower.X, upper.X, lower.Y, upper.Y);
In this line your Orthogonal 2D projection matrix is being multiplied with the previous rotation and applied to your projection matrix. Which I believe is not what you want.
The solution would be move your rotation call to a place after the model view matrix mode is selected, as below
// L/R/B/T
Glu.gluOrtho2D(lower.X, upper.X, lower.Y, upper.Y);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
// rotate the view
var shipAngle = 180.0f; // just a test angle for proof of concept
Gl.glRotatef(shipAngle, 0.0f, 0.0f, 1.0f);
And now your rotations will be applied to the model-view matrix stack. (I believe this is the effect you want). Keep in mind that glRotatef() creates a rotation matrix and multiplies it with the matrix at the top of the selected stack stack.
I would also strongly suggest you move away from fixed function pipeline if possible as suggested by #BDL.
I was wondering if there is an easy way to store a created matrix into a variable to be later called by glLoadMatrix(), the point being to reset the matrix to an earlier state.
For example:
void reshape(int w, int h){
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(dist, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(x_shift, y_shift, z_shift);
}
The goal being to store the matrix produced into a separate variable to effectively save the current matrix state before multiplying on top of it.
I already recommendet to stop using the GL matrix stack at all. It is depracted and has been removed from the core profile of modern OpenGL. Libraries like glm could be used instead.
However, what you ask for can be done with the matrix stack. Just use glGetFloatv() with GL_MODELVIEW matrix, GL_PROJECTION_MATRIX or GL_TEXTURE_MATRIX to query the current the respective matrix:
GLfloat m[16];
glGetFloatv(GL_MODELVIEW_MATRIX, m);
// other GL code modifying the MODELVIEW matrix
// ...
glMatrixMode(GL_MODELVIEW); // make sure we restore to MODELVIEW
glLoadMatrixf(m); // restore it
With the legacy functionality you are using, matrices are managed as a stack. Or to be precise, as a separate stack for each of the 4 matrix modes, where the most commonly used ones are GL_MODELVIEW and GL_PROJECTION.
The most direct way to save/restore matrices is by using the actual stack operations on this matrix stack, which is done with glPushMatrix() and glPopMatrix(), where Push and Pop follow the usual stack semantics:
Push: Adds a stack entry by copying the current top entry.
Pop: Removes the current top entry.
Let's say you first set up a matrix 1, then matrix 2, and then want to restore matrix 1. For illustration, I'll set up matrix 1 as a rotation matrix, and matrix 2 as a translation matrix, but they can of course be anything.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(...);
// This is our matrix 1, now on top of the stack.
glPushMatrix();
// Push a new stack entry, to save matrix 1.
glLoadIdentity();
glTranslatef(...);
// Now we have matrix 2 on top of the stack.
glPopMatrix();
// Since we popped the top entry (matrix 2) off the stack, matrix 1 is
// now the active matrix at the top of the stack again.
You can also use glGetFloatf(GL_MODELVIEW_MATRIX, ...) and glGetFloatf(GL_PROJECTION_MATRIX, ...) to get the current matrix, and later set them again with glLoadMatrix(). But if you care about performance at all, you should really avoid glGet*() calls.
glDisable(GL_DEPTH_TEST);
glViewport(0/*left*/, 0/*botton*/, 200/*width*/, 200/*height*/); //T4
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90 /*fov*/, 1/*aspect*/, 1/*fp*/, 1000/*bp*/); //T3
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0/*eyex*/,0/*eyey*/,0/*eyez*/, 0/*lax*/,0/*lay*/,-1/*laz*/, 0/*upx*/,1/*upy*/,0/*upz*/); //T2
glTranslatef(-15.0, -10.0, -49.0); //T1
glBegin(GL_POINTS);
glVertex4f(0, 0, -1, 1);
glEnd();
Given this code, in what order does the matrix multiplication happen? What do I have to know to follow and verify the calculations on paper?
I suspect to following order, but haven't figured out a way to verify it:
v=[0,0,-1,1]
T4 * T3 * T2 * T1 * v
Is this correct?
This is mostly correct, however glViewport (...) by itself does not define a matrix. It is a simple bias and scale operation. It defines the total width, height and offset in X and Y. There is another component you are missing, which is the depth range.
The multiplication occurs in that order, but since these are column-major matrices and post-multiplied, you conceptually start on the right and then work your way to the left. Cross out T4 because it alone is not a matrix, and the end result of all this is a clip-space vertex coordinate. You still need to divide v.xyz by v.w and then do the viewport transformation to fully replicate what GL does.
You can implement the viewport transform using a matrix, but you also need to factor in glDepthRange (...) which biases and scales the Z coordinate from NDC space to window space.
Here is what such a matrix would look like:
The whole process is discussed in better detail here, under 4.1 Coordinates Transformation.
I want to write a function for rotating an object around its axis contemporaneously with passing the each angle around its x, y and z axis; I read here but I did not understand it completely. for example for rotating around my shape's axis, which parameters I must pass to the glTranslatef() and the How does the matrix which is multiplied to [0 1 0] (for calculating the new y axis) created?
I do not understand why when I call glRotatef() for several time, I just saw the first call in output; I tested gltranslatef and glPushMatrix and glPopMatrix befor and after my code; but none of them help me;
it is very important for me to understand the solution of this topic.
this is my code but it does not work!
glPushMatrix();
glRotatef(90,1,0,0); // rotate around X Axis
glPopMatrix();
glPushMatrix();
glRotatef(90,0,1,0); // rotate around Y Axis
glPopMatrix();
glPushMatrix();
glRotatef(90,0,0,1); // rotate around Z Axis
glPopMatrix();
if you did this tell me your way.
Your above code really doesn't do anything that would be visible because you don't render anything after altering the currently active matrix. The effect of the following code segment is as follows (assume the current stack is MODELVIEW):
glPushMatrix(); // push the stack down one matrix and copy the current matrix
glRotatef(90,1,0,0); // multiply the current matrix M by a rotation matrix R -> M' = M * R
// usually you would render stuff here using the current model-view matrix
glPopMatrix(); // pop the top matrix off the stack
As you can see, by pushing a new matrix onto the stack, you preserve what ever matrix was on top before the push. Then you manipulate the current top matrix in some way, render stuff, and pop the top matrix off to restore the previous state.
I think you can see now why your above code does absolutely nothing of essence - except cause unnecessary overhead.
Using the matrix stack, if you insist on using legacy GL, is generally correct here, because you don't want your modifications affecting subsequently rendered geometry. However, what you really want is simple matrix concatenation. Assuming you want to perform and extrinsic rotation, i.e. a rotation about the fixed basis of world-space in z-y-x, you need to do the following:
glPushMatrix();
glRotatef(90,1,0,0);
glRotatef(90,0,1,0);
glRotatef(90,0,0,1);
// render camera
glPopMatrix();
The above is mathematically equivalent to calculation a rotation matrix R by concatenating the individual rotations R_z, R_y and R_x: R' = R_x * R_y * R_z.
I suggest you also read this and to better understand what you're doing and potential problems with rotations in general.
I need to draw a line between two meshes I've created. Each mesh is associated with a different model matrix. I've been thinking on how to do this and I thought of this:
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(first_object_model_matrix);
glBegin(GL_LINES);
glVertex3f(0, 0, 0); // object coord
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(first_object_model_matrix);
glVertex3f(0, 0, 0); // ending point of the line
glEnd( );
But the problem is that I can't call glMatrixMode and glLoadMatrixf between glBegin and glEnd. I'm also using shaders and the programmable pipeline, so the idea of turning back to the fixed pipeline with my scene rendered isn't exciting.
Can you:
Suggest me precisely how to draw a line between two meshes (I have their model matrix) with shaders.
or
Suggest me how to write code similar to the one above to draw a line having two meshes model matrices.
Calculate the line's two points by multiplying each one with one of your model matrices. The following is pseudo-code. Since you're using Qt, you could use its built-in maths libraries to accomplish this effect.
vec3 line_point_1 = model_matrix_object1 * vec4(0, 0, 0, 1);
vec3 line_point_2 = model_matrix_object2 * vec4(0, 0, 0, 1);
// Draw Lines
The position of the second point can simply be taken from the w vector of the model_matrix_object2. No need to multiply with (0,0,0,1).
This is because a 4x4 matrix in OpenGL is usually an ortho matrix consisting of a 3x3 rotational part and a translational vector. The last row is then padded with 0,0,0,1. If you want to know where a 4x4 matrix would translate simply get the vector in the right-most column.
See Given a 4x4 homogeneous matrix, how can i get 3D world coords? for more info.