OpenGL screen-space translation of perspective camera view - opengl

I am using a perspective projection camera in OpenGL with an eye-target-up approach along the lines of gluLookAt()
I would like to move the entire 3d view to a different location within the 2d window, as shown in the image below:
I know this can be done with glViewport(), but I would ultimately like to be able to rotate the 3d view in addition to translating it, which I understand won't work with a glViewport approach.
I also understand that taking a non-glViewport approach will require the additional step of stenciling. I'll leave that step for later.
For now, I'm hoping to simply translate the 3d view as shown in the image above (ignoring the stenciling issue).
It seems like translating the projection matrix is the correct approach, however the translation extent is not what I expect. Perhaps I need to scale the parameter I'm using? In any case, I'm hoping someone can explain how to (more-or-less) simulate a translatable/rotatable glViewport for a 3d perspective view.
Thanks!

You use glViewport(). For each view port, you set the viewport, setup model view matrix and draw scene.
For first viewport
glViewport (0, 0, window_width/2, window_height/2);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
//do something with projection matrix
drawScene();
For second viewport
glViewport (window_width/2, 0, window_width/2, window_height/2);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
//do something different with projection matrix
drawScene();

Related

How to design a plane to be in the center of the viewport at any window size

I need to draw a plane (with GL_QUADS) in OpenGL (c++, OS: windows) so that it is aligned to the center of the screen.
What I mean is that the origin will be in the center of the plane at any window resize.
I know I have to use the viewport coordinates and sizes, but I cannot configure how to use them.
Also, I am using gluPerspective.
The origin has nothing to do with your window size. When you resize the window, recalculate the aspect ratio of the window (window.width / window.height) and reset your projection matrix with another call to gluPerspective using the new aspect.
After this, as long as you glLoadIdentity() into the modelview matrix you should be able to draw a quad at the center of the screen using
glBegin(GL_QUADS);
glVertex3f(-.5f,.5f,-1);
glVertex3f(-.5f,-.5f,-1);
glVertex3f(.5f,-.5f,-1);
glVertex3f(.5f,.5f,-1);
glEnd();
That should place a unit sized quad at the center of the screen.
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glBegin(GL_QUADS);
glVertex3f(-.5f,.5f,-1);
glVertex3f(-.5f,-.5f,-1);
glVertex3f(.5f,-.5f,-1);
glVertex3f(.5f,.5f,-1);
glEnd();
glPopMatrix();
Note that this still uses all of your 3D rendering state, such as depth test, shading, etc.. Most likely you'll want to turn that off.

glOrtho in a 3D scene isn't working

I made a 3D scene and I used glOrtho and gluOrtho2D to get things to stay on my screen when I move the camera to look around in my 3D scene. But when I start to look around the characters disappear.
How do you get the characters to stay on your screen.
The projection matrix kind of defines your lens. But no matter what lens you use, if you turn the scene or move the camera, the view will change.
How do you get the characters to stay on your screen.
Well, by keeping the "camera" in place.
OpenGL actually doesn't have a camera. It doesn't even have a scene. The only thing it sees are points, lines and triangles it draws one after another to the screen. What OpenGL has are transformation matrices. And in your case, all you have to do is set a projection and modelview, that will draw the characters at the desired place on the screen. And since OpenGL does not maintain a scene, you can change the transformation matrices anytime you want.
You probably forgot a "glLoadIdentity();" somewhere...
After your calls to glOrtho...
glOrtho(0.0, windowWidth, 0.0, windowHeight, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Hope this helps.
-kropcke

c++ opengl: how can i combine 2 different projection types for 3d graphics and 2d menus?

I would like to use Oblique projection for menus and perspective projection for the 3d-scene. is there a way to combine between this two projections ?
In general I'm asking how can I create menus in opengl for my 3d scene.
Programming using the c++ language.
Thanks!
No problem. Just draw your 3D scene with appropriate
modelview and projection matrices loaded. Then load
up 2D matrices, turn off depth test, and render your
menus. Here's an example of what it might look like.
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_MODELVIEW);
--code to load my Perspective Modelview Matrix
glMatrixMode(GL_PROJECTION);
--code to load my Perspective Projection Matrix
--code to draw my 3D scene
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glMatrixMode(GL_PROJECTION);
--code to setup my "menu" coords, probably something like
gluOrtho2D
glDisable(GL_DEPTH_TEST)
--code to draw the menus
Draw your 3D scene.
Push the projection matrix.
(Maybe clear the depth buffer).
Set up 2D projection.
Draw your 2D menu.
Pop the projection matrix.

What is a good way of implementing HCI in OpenGL?

I'd like to try and implement some HCI for my existing OpenGL application. If possible, the menus should appear infront of my 3D graphics which would be in the background.
I was thinking of drawing a square directly in front of the "camera", and then drawing either textures or more primatives on top of the "base" square.
While the menus are active the camera can't move, so that the camera doesn't look away from the menus.
Does this sound far feteched to anyone or am I on the right tracks? How would everyone else do it?
I would just glPushMatrix, glLoadIdentity, do your drawing, then glPopMatrix and not worry about where your camera is.
You'll also need to disable and re-enable depth test, lighting and such
There is the GLUI library to do this (no personal experience)
Or if you are using Qt there are ways of rendering Qt widgets transparently on top of the OpenGL model, there is also beta support for rendering all of Qt in opengl.
You could also do all your 3d Rendering, then switch to orthographic projection and draw all your menu objects. This would be much easier than putting it all on a large billboarded quad as you suggested.
Check out this exerpt, specifically the heading "Projection Transformations".
As stated here, you need to apply a translation of 0.375 in x and y to get pixel perfect alignment:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.375, 0.375, 0.0);
/* render all primitives at integer positions */
The algorithm is simple:
Draw your 3D scene, presumably with depth testing enabled.
Disable depth testing so that your GUI elements will draw over the 3D stuff.
Use glPushMatrix to store you current model view and projection matrices (assuming you want to restore them - otherwise, just trump on them)
Set up your model view and projection matrices as described in the above code
Draw your UI stuff
Use glPushMatrix to restore your pushed matrices (assuming you pushed them)
Doing it like this makes the camera position irrelevant - in fact, as the camera moves, the 3D parts will be affected as normal, but the 2D overlay stays in place. I'm expecting that this is the behaviour you want.

Why is my glutWireCube not placed in origin?

I have the following OpenGL code in the display function:
glLoadIdentity();
gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx, upy, upz);
// called as: gluLookAt(20, 5, 5, -20, 5, 5, 0, 1, 0);
axis();
glutWireCube (1.);
glFlush ();
axis() draws lines from (0,0,0) to (10,0,0), (0,10,0) and (0,10,0), plus a line from (1,0,0) to (1,3,0).
My reshape function contains the following:
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(45.0, (GLsizei) w / (GLsizei) h, 1.0, 100.0);
glMatrixMode (GL_MODELVIEW);
This image shows the result of running the program with 1. as the argument to glutWireCube:
As you can see, the cube isn't centered around (0,0,0) as the documentation says it should be:
The cube is centered at the modeling
coordinates origin (...) (source)
If I run the program with 5. as the argument, the cube is displaced even further:
Why is that, and how do I place the cubes around (0,0,0)?
FURTHER INFORMATION
It doesn't matter if I switch the order of axis() and glutWireCube. Surrounding axis() with glPushMatrix() and glPopMatrix() doesn't fix it either.
SOLUTION
I modified gluPerspective to start looking further away from the camera, and now the Z-buffering works properly, so it is clear that the cubes are placed around the origin.
Are you sure axis does not mess with the view matrix ?
What happens if you call it after the drawing of the cube ?
Edit to add:
Actually... Looking at the picture closer, it looks like it might be centered at the origin.
The center of the cube seems to align exactly with the intersection of the 3 axes. The only thing that looks suspicious is that the red line does not write over the white edge. do you have Z-buffering properly set up ?
It might be right, I think it's hard to determine due to the perspective ... But I guess it isn't from staring a bit more at it.
To quickly rule out that axis() isn't modifying the model view matrix, surround the call with matrix push/pops:
glPushMatrix();
axis();
glPopMatrix();
Things to investigate/check:
Is this the entire window? It seems odd that the view is down in one corner.
Does it help if you add an increasing rotation before the rendering? That can make it easier to determine the perspective, by giving more clues.
You can also try moving the "camera" around, by changing the arguments to gluLookAt() dynamically.