store a matrix created by a function opengl - opengl

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.

Related

OpenGL switching between ortho and perspective

I have a tile engine using orthographic projection in immediate mode and I'm just trying to draw a 3d cube on top of my tile scene, in hopes that I can eventually incorporate 3d models into my engine instead of just sprites / textured quads. I would also like to make the tiles 3d for that slight bit of extra eye candy.. Hopefully I can eventually convert this to use modern OpenGL so I can take advantage of those extra features. Not on the top of my priority list at the moment. So on to the question.
I'm initializing OpenGL with this:
void initGL()
{
glDisable(GL_DEPTH_TEST);
glViewport( 0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
//Initialize Projection Matrix
glMatrixMode( GL_PROJECTION );
glPushMatrix();
glLoadIdentity();
//Initialize Modelview Matrix
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//...setting some various other attributes, omitted for brevity...
glEnable(GL_TEXTURE_2D);
glClearColor( 0, 0, 0, 0 );
}
I have a function for drawing a cube that works.
void draw_cube()
{
/* position object */
glRotatef(30.0F, 1.0F, 0.0F, 0.0F);
glRotatef(30.0F, 0.0F, 1.0F, 0.0F);
/* draw six faces of a cube */
glBegin(GL_QUADS);
...vertices... (removed for brevity)
glEnd();
}
I made 2 functions for setting the 2d and 3d projection modes.
void set3d()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(0,SCREEN_WIDTH,0,SCREEN_HEIGHT, 0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void set2d()
{
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,SCREEN_WIDTH,SCREEN_HEIGHT,0,0,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
For the sake of completeness, some pseudocode of my textured quad drawing..
pushmatrix();
translate();
rotate();
-translate();
glbegin();
...vertices
glend();
popmatrix();
So far I have managed to get the cube to draw on top of the tiles, but it disappears after approximately 1 second to never be seen again until I run the program again.
Basically what I'm doing in the main loop is this:
move objects around, process collisions, etc.
set2d();
draw textured quads, lines, text, etc. in 2d mode.
set3d();
draw_cube();
My question is: Why is the cube disappearing, and are there any errors in my set2d() and set3d() functions?
You have quite a few problems in this code, too many to list in comments in fact.
Your projection matrices are changing the handedness of your post-projected coordinate space, which will affect polygon winding.
Stick to a single handedness, unless you want to reverse the direction used for front- / back-facing polygon facets (glFrontFace (...)) - it is CCW by default, but you will have to change it to CW when you use set3d (...) to maintain consistent behavior.
This problem arises because you have the Y-axis going different directions
The behavior your are describing, where the object appears briefly and then disappears is indicative of an issue with your matrix stack.
Are you calling initGL (...) more than once in your software? You will run into a stack overflow if you do this enough times since you needlessly push the current matrix onto the stack and never pop it off.
You cannot use 0.0 for zNear with a perspective projection matrix, this will result in wonky math during the perspective divide step that comes after transformation to clip-space; the depth buffer will not work correctly.
In fact, glFrustum (...) will generate a GL_INVALID_VALUE error and do exactly nothing if you pass a value ≤ 0.0 for zNear. On a related note, gluPerspective (...) will not do this since it is not actually part of OpenGL, but it is equally invalid behavior to pass such a value to gluPerspective (...).

Roatating an Object around its (x,y&z) axis contemporaneously in C++ using OpenGL

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.

Cant load and save matrix Opengl

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.

OpenGL gluLookAt() not working as intended

I am making a rollercoaster inside of a skybox in OpenGL, and without much background on it's functions or computer graphics it is proving to be very difficult. I drew a rollercoaster using Catmull-Rom spline interpolation, and drew each point with glVertex3f. Now I want to call an update() function every 50ms to move the camera around the track. gluLookAt() is producing weird results, either removing the track from the screen, producing a black screen, etc. I think I need to move some of the matrix functions around but I am not sure where to put each one. Here is my code so far:
int main(int argc, char** argc)
{
// ... load track, etc ...
// Init currpos, nextpos, iter, up
currpos = Vec3f(0, 0, 0);
nextpos = currpos;
iter = 0;
up = Vec3f(0, 1, 0);
deque<Vec3f> points;
Vec3f newpt;
// Loop through the points and interpolate
for (pointVectorIter pv = g_Track.points().begin(); pv != g_Track.points().end(); pv++)
{
Vec3f curr(*pv); // Initialize the current point and a new point (to be drawn)
points.push_back(curr); // Push the current point onto the stack
allpoints.push_back(curr); // Add current point to the total stack
if (points.size() == 4) // Check if there are 4 points in the stack, if so interpolate
{
for (float u = 0.0f; u < 1.0f; u += 0.01f)
{
newpt = interpolate(points[0], points[1], points[2], points[3], u);
glColor3f(1, 1, 1);
glVertex3f(newpt.x(), newpt.y(), newpt.z());
allpoints.push_back(newpt);
}
points.pop_front();
}
}
// glutInit, InitGL(), etc...
}
void InitGL(GLvoid)
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(100.0, (GLfloat)WINDOW_WIDTH / (GLfloat)WINDOW_HEIGHT, .0001, 999999);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
}
void display (void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(currpos.x(), currpos.y(), currpos.z(), nextpos.x(), nextpos.y(), nextpos.z(), up.x(), up.y(), up.z());
glPushMatrix();
glEnable(GL_TEXTURE_2D); // Enable texturing from now on
/* draw skybox, this was from previous assignment and renders correctly */
glPopMatrix();
// now draw rollercoaster ...
glPushMatrix();
glBegin(GL_LINE_STRIP);
deque<Vec3f> points;
Vec3f newpt;
for each (Vec3f pt in allpoints)
{
glColor3f(1, 1, 1);
glVertex3f(pt.x(), pt.y(), pt.z());
}
glutTimerFunc(50, update, 1);
glEnd();
glPopMatrix();
// Swap buffers, so one we just drew is displayed
glutSwapBuffers();
}
void update(int a)
{
if (iter < allpoints.size())
{
currpos = allpoints[iter];
nextpos = allpoints[iter + 1];
gaze = nextpos - currpos;
gaze.Normalize();
Vec3f::Cross3(binorm, gaze, up);
binorm.Normalize();
Vec3f::Cross3(up, binorm, gaze);
up.Normalize();
glutPostRedisplay();
}
iter++;
}
The idea is that I am keeping a global deque allpoints that includes the control points of the spline and the interpolated points. Once that is complete, I call update() every 50ms, and move the camera along each point in allpoints. In a previous version of the project, I could see that the rollercoaster was being drawn correctly. It is gluLookAt() that doesn't seem to work how I want it to. With the code above, the program starts with the camera looking at one side of the skybox with a part of the rollercoaster, and then when update() is called, the rollercoaster disappears but the camera does not move. I have been messing around with where I am putting the OpenGL matrix functions, and depending on where they are sometimes update() will cause a blank screen as well.
Besides the absence of glPopMatrix (which user971377 already spotted), you call glLoadIdentity in your drawing routine, which of course overwrites any changes you did on the modelview matrix in the update method (using gluLookAt).
Always keep in mind: gluLookAt, glOrtho, gluPerspective, glTranslate, glRotate, and all other matrix and transformation functions always work on the top element (changed by glPush/PopMatrix) of the currently selected matrix stack (changed by glMatrixMode). And they always multiply the current matrix, istead of replacing it. So like for gluPerspective, you should call glLoadIdentity before calling gluLookAt. And the whole camera change should be done in the rendering routine, istead of the update routine.
Instead of doing any GL transformations in update you should rather change the variables on which the camera depends and set the camera (gluLookAt on the modelview matrix) in the display method. To demonstrate the standard use of these functions, your code should be something like:
void display()
{
<general state setup (glClear, ...)>
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLookAt(camera); //view transformation (camera)
//object 1
glPushMatrix(); //save modelview
glTranslate/glRotate/glScale; //local model transformations
<draw object 1>
glPopMatrix();
...
//object n
glPushMatrix(); //save modelview
glTranslate/glRotate/glScale; //local model transformations
<draw object n>
glPopMatrix();
gluSwapBuffers();
}
void update()
{
camera = ...;
}
}
Noticed in your code glPushMatrix(); is called with no glPopMatrix();
Just a thought, this might have something to do with you issue.
gluLookAt always applies its result to current matrix, which in your case is GL_MODEL_VIEW. But when you render your roller coaster, you load identity in that matrix, which erase the value you put using gluLookAt.
In this case, you don't need to touch the model view. In fact, GL_MODEL_VIEW stands for model matrix multiply by view matrix. In this case, you can glPushMatrix() followed by glMulMatrix( myModelMatrix ) and after rendering glPopMatrix(). With this, you can keep your view matrix inside the GL_MODEL_VIEW and still use a different model matrix for each object
I also suggest you only change projection matrix once a frame, and not each frame.
It's been a long time since I touched OpenGL, but here are a few things to consider:
With each call to display(), you are drawing the skybox with the current matrix then loading the identity matrix to draw the roller coaster. Perhaps load the identity within the push/pop so that the skybox is constant, but your prevailing tranformations on the roller coaster are applied.
Do you need to call gluPerspective and glMatrixMode with every call to display()?
Repeatedly calculating binorm from up and then up from binorm will probably give you unexpected results in terms of rotation of the camera around the screen's z axis.
The call to gluLookAt appears to have nextpos and currpos reversed, pointing the camera in the opposite direction.
(Opinion only) It may still look wierd with a completely stationary skybox. Matching camera rotation (but not translation) when drawing the skybox and roller coaster may look better.

Why do reshape codes end in glMatrixMode(GL_MODELVIEW)?

When looking at the reshape examples in the redbook, I usually find something like:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
}
I understand that calling glMatrixMode(GL_PROJECTION); followed by glLoadIdentity(); resets the projection matrix but I don't understand why glMatrixMode(GL_MODELVIEW) is usually called at the end of reshape.
In this particular example glFrustum affects the projection matrix, right? Why is GL_MODELVIEW called later? Would it make a difference if the last call to glMatrixMode(GL_MODELVIEW) is omitted?
Most of your rendering code is going to affect GL_MODELVIEW, because it's what affects object translation and camera position. However, the resizing code works on GL_PROJECTION. The programmer probably assumes the current matrix is the modelview one in most of his code, and when a different one needs to be affected, he/she would change the matrix, update it, and then change the target back to GL_MODELVIEW so the rest of the code doesn't target the wrong matrix.
Generally, OpenGL functions affect whatever matrix is currently being targeted, which is why you change the matrix.